|
|
1.1 ! root 1: /* ! 2: * n1/i386/mtree2.c ! 3: * Machine dependent parts of the tree modifier. ! 4: * A conditionalization handles machines that have an 80x87. ! 5: * i386. ! 6: */ ! 7: ! 8: #ifdef vax ! 9: #include "INC$LIB:cc1.h" ! 10: #else ! 11: #include "cc1.h" ! 12: #endif ! 13: ! 14: int blkflab; ! 15: ! 16: #if SPLIT_CC1 ! 17: /* ! 18: * Function prolog. ! 19: * Clear "BLK function" label. ! 20: */ ! 21: doprolog() ! 22: { ! 23: blkflab = 0; ! 24: } ! 25: ! 26: /* ! 27: * Copy auto information. ! 28: */ ! 29: doautos() ! 30: { ! 31: iput(iget()); ! 32: iput(iget()); ! 33: } ! 34: #endif ! 35: ! 36: /* ! 37: * This function performs machine specific tree modifications. ! 38: * It is called from "modtree" after all of the machine ! 39: * independent transformations have been done. ! 40: * It returns either a pointer to the new tree ! 41: * (telling "modtree" to do another pass) ! 42: * or NULL (which implies that no changes were made). ! 43: */ ! 44: TREE * ! 45: modoper(tp, ac, ptp) register TREE *tp; int ac; TREE *ptp; ! 46: { ! 47: register TREE *lp, *rp, *tp1, *tp2, *tp3; ! 48: register int c, op, nseg; ! 49: register int tt, lt, rt; ! 50: sizeof_t offs; ! 51: ! 52: c = ac; ! 53: if (c==MRETURN || c==MSWITCH || c==MINIT) ! 54: c = MRVALUE; ! 55: op = tp->t_op; ! 56: if (isleaf(op)) { ! 57: if (op==AID || op==PID) { ! 58: /* Modify autos and parameters to "*(%ebp+offset)". */ ! 59: offs = tp->t_offs; ! 60: tp->t_op = STAR; ! 61: tp->t_rp = NULL; ! 62: tp->t_lp = tp2 = makenode(ADD, PTR); ! 63: tp2->t_lp = tp3 = makenode(REG, PTR); ! 64: tp3->t_reg = EBP; ! 65: tp2->t_rp = ivalnode((ival_t)offs); ! 66: return tp; ! 67: } else ! 68: goto done; ! 69: } ! 70: ! 71: /* ! 72: * Beat on lvalue fields. ! 73: */ ! 74: if ((op==ASSIGN || (op>=AADD && op<=ASHR) ! 75: || (op>=INCBEF && op<=DECAFT)) ! 76: && tp->t_lp->t_op==FIELD && tp->t_lp->t_type<FLD8) ! 77: return modlfld(tp, c); ! 78: ! 79: /* ! 80: * Non leaf. ! 81: * Gather up subtrees. ! 82: * Rewrite some things as calls to library routines. ! 83: */ ! 84: tt = tp->t_type; ! 85: lp = tp->t_lp; ! 86: if (lp != NULL) ! 87: lt = lp->t_type; ! 88: rp = NULL; ! 89: if (op != FIELD) { ! 90: rp = tp->t_rp; ! 91: if (rp != NULL) ! 92: rt = rp->t_type; ! 93: } ! 94: ! 95: /* ! 96: * If there is an NDP, rewrite conversions ! 97: * from bytes and unsigned things ! 98: * and all conversions from float to fixed ! 99: * as calls of support routines. ! 100: */ ! 101: if (isvariant(VNDP)) { ! 102: if (isflt(tt)) { ! 103: if (op==CONVERT || op==CAST) { ! 104: if ((lp->t_flag&T_REG) != 0 ! 105: || (lp->t_flag&T_LEAF) == 0 ! 106: || (lt!=S16 && lt!=S32 && lt!=F32)) ! 107: return modxfun(tp); ! 108: } ! 109: } else if ((op>=GT && op<=LT) && isflt(lt)) ! 110: tp->t_op += UGT-GT; ! 111: else if ((op==CONVERT || op==CAST) && isflt(lt)) ! 112: return modxfun(tp); ! 113: } ! 114: switch (op) { ! 115: ! 116: case FIELD: ! 117: if (c != MLADDR) ! 118: return modefld(tp->t_lp, tp, c, 1); ! 119: break; ! 120: ! 121: case ASSIGN: ! 122: if (tt == BLK) { ! 123: tp = modsasg(lp, rp, tp->t_size); ! 124: if (c != MEFFECT) ! 125: tp = leftnode(STAR, tp, BLK, tp->t_size); ! 126: return tp; ! 127: } ! 128: break; ! 129: ! 130: case CONVERT: ! 131: case CAST: ! 132: if (modkind(tt) == modkind(lp->t_type)) { ! 133: lp->t_type = tt; ! 134: return lp; ! 135: } ! 136: } ! 137: ! 138: /* ! 139: * If this tree is the return value of a structure function, ! 140: * arrange to copy the value into a secret place ! 141: * and return the address of the place. ! 142: */ ! 143: done: ! 144: if (tp->t_type==BLK && ac==MRETURN) { ! 145: if (blkflab == 0) { ! 146: blkflab = newlab(); ! 147: nseg = newseg(SBSS); ! 148: genlab(blkflab); ! 149: bput(BLOCK); ! 150: iput((ival_t) tp->t_size); ! 151: newseg(nseg); ! 152: } ! 153: lp = makenode(LID, BLK, tp->t_size); ! 154: lp->t_label = blkflab; ! 155: lp->t_seg = SBSS; ! 156: return modsasg(lp, tp, tp->t_size); ! 157: } ! 158: return NULL; ! 159: } ! 160: ! 161: /* ! 162: * Given a type, return a kind that is used to see ! 163: * if two objects are just different names for the same bits. ! 164: */ ! 165: modkind(t) register int t; ! 166: { ! 167: if (t == U8) ! 168: t = S8; ! 169: else if (t == U16) ! 170: t = S16; ! 171: else if (t == U32) ! 172: t = S32; ! 173: return t; ! 174: } ! 175: ! 176: /* ! 177: * Build a call node for the assignment of structure data. ! 178: * The rep and a copy operation are not used so that the ES need not be used. ! 179: * The type of the CALL is PTR. ! 180: * The size is valid. ! 181: */ ! 182: TREE * ! 183: modsasg(lp, rp, s) register TREE *lp, *rp; ! 184: { ! 185: register TREE *tp; ! 186: ! 187: rp = leftnode(ADDR, rp, PTR); ! 188: rp = leftnode(ARGLST, rp, PTR); ! 189: rp->t_rp = ivalnode((ival_t)s); ! 190: lp = leftnode(ADDR, lp, PTR); ! 191: lp = leftnode(ARGLST, lp, PTR); ! 192: lp->t_rp = rp; ! 193: tp = makenode(GID, PTR); ! 194: tp->t_sp = gidpool("memcpy"); ! 195: tp->t_seg = SANY; ! 196: tp = leftnode(CALL, tp, PTR); ! 197: tp->t_size = s; ! 198: tp->t_rp = lp; ! 199: return tp; ! 200: } ! 201: ! 202: /* ! 203: * Modify function calls. ! 204: * Handle functions that return objects of type "BLK" ! 205: * by adding a free indirection node. ! 206: */ ! 207: TREE * ! 208: modcall(tp, c) register TREE *tp; int c; ! 209: { ! 210: fixtoptype(tp); ! 211: tp->t_lp = modtree(tp->t_lp, MLADDR, tp); ! 212: tp->t_rp = modargs(tp->t_rp, tp); ! 213: if (tp->t_type == BLK) { ! 214: tp->t_type = PTR; ! 215: if (c != MEFFECT) ! 216: tp = leftnode(STAR, tp, BLK, tp->t_size); ! 217: } ! 218: return tp; ! 219: } ! 220: ! 221: /* ! 222: * Modify argument lists. ! 223: */ ! 224: TREE * ! 225: modargs(tp, ptp) register TREE *tp; TREE *ptp; ! 226: { ! 227: if (tp == NULL) ! 228: return NULL; ! 229: if (tp->t_op == ARGLST) { ! 230: tp->t_lp = modargs(tp->t_lp, tp); ! 231: tp->t_rp = modargs(tp->t_rp, tp); ! 232: return tp; ! 233: } ! 234: if (tp->t_type == BLK) { ! 235: tp = leftnode(ADDR, tp, PTB, tp->t_size); ! 236: return modtree(tp, MRVALUE, ptp); ! 237: } ! 238: return modtree(tp, MFNARG, ptp); ! 239: } ! 240: ! 241: static char modoptab[] = { ! 242: 'i', 'u', /* S8 U8 */ ! 243: 'i', 'u', /* S16 U16 */ ! 244: 'i', 'u', /* S32 U32 */ ! 245: 'f', 'd', /* F32 F64 */ ! 246: 'b', /* BLK */ ! 247: 'i', 'i', 'i', /* FLD8 FLD16 FLD32 */ ! 248: 'p', 'p' /* PTR PTB */ ! 249: }; ! 250: ! 251: /* ! 252: * Rewrite a TREE node which describes an operation ! 253: * that the machine cannot directly perform as a CALL to a magic routine. ! 254: * On the i386 we rewrite NDP floating point conversions. ! 255: * This used to rewrite software fp as subroutine calls, ! 256: * now the code tables generate the calls directly instead. ! 257: */ ! 258: TREE * ! 259: modxfun(tp) ! 260: TREE *tp; ! 261: { ! 262: register TREE *lp, *rp; ! 263: register char *p1, *p2; ! 264: register TREE *tp1; ! 265: register int tt, lt, op; ! 266: ! 267: op = tp->t_op; ! 268: lp = tp->t_lp; ! 269: rp = tp->t_rp; ! 270: tt = tp->t_type; ! 271: if (lp != NULL) ! 272: lt = lp->t_type; ! 273: p1 = id; ! 274: *p1++ = '_'; ! 275: *p1++ = modoptab[tt]; ! 276: if (lt==F32 && tt!=F64) ! 277: lt = F64; ! 278: *p1++ = modoptab[lt]; ! 279: p2 = "cvt"; ! 280: while (*p1++ = *p2++) ! 281: ; ! 282: *p1 = '\0'; ! 283: tp1 = makenode(GID, PTR); ! 284: tp1->t_sp = gidpool(id); ! 285: tp1->t_seg = SANY; ! 286: tp->t_op = CALL; ! 287: tp->t_lp = tp1; ! 288: tp->t_rp = lp; ! 289: fixtoptype(tp); ! 290: if (tp->t_type!=tt && tt!=F32) ! 291: tp = leftnode(CONVERT, tp, tt); ! 292: if (isrelop(op)) { ! 293: tp = leftnode(op, tp, TRUTH); ! 294: tp->t_rp = ivalnode((ival_t)0); ! 295: } ! 296: return tp; ! 297: } ! 298: ! 299: /* ! 300: * Zap a DCON into a block of memory with a double in it. ! 301: */ ! 302: storedcon(tp) register TREE *tp; ! 303: { ! 304: if (tp->t_op != DCON) ! 305: return; ! 306: pool(tp); ! 307: tp->t_flag = T_DIR; ! 308: } ! 309: ! 310: /* ! 311: * Test if 1) the tree pointed to by "tp" is a register ! 312: * and 2) the operation "op" can be computed in it. ! 313: */ ! 314: isokareg(tp, op) register TREE *tp; register op; ! 315: { ! 316: if (op==MUL || op==DIV || op==REM) ! 317: return 0; ! 318: if (tp->t_op!=REG || !isword(tp->t_type)) ! 319: return 0; ! 320: return 1; ! 321: } ! 322: ! 323: /* ! 324: * Modify bit fields in lvalue contexts. ! 325: * The "tp" argument is a pointer to the tree node ! 326: * with the FIELD operation on the left side. ! 327: * This routine has two tasks. ! 328: * First, it rewrites the type in the FIELD node to be the type used by ! 329: * select to match the tree; this is also used as a flag ! 330: * to prevent this routine from being called twice on a node. ! 331: * Second, it inserts explict shift nodes to ! 332: * the operands and results so that all of the optimizations ! 333: * applied to shifts work for fields. ! 334: * A pointer to the new top of the tree is returned. ! 335: */ ! 336: TREE * ! 337: modlfld(tp, c) register TREE *tp; int c; ! 338: { ! 339: register TREE *lp, *rp; ! 340: register lt, tt; ! 341: register op; ! 342: register bmop; ! 343: register MASK mask; ! 344: ! 345: op = tp->t_op; ! 346: tt = tp->t_type; ! 347: lp = tp->t_lp; ! 348: if (lp != NULL) ! 349: lt = lp->t_type; ! 350: if (op!=AMUL && op!=ADIV && op!=ASHL && op!=ASHR) { ! 351: rp = tp->t_rp; ! 352: rp = leftnode(SHL, rp, rp->t_type); ! 353: rp->t_rp = ivalnode((ival_t)lp->t_base); ! 354: tp->t_rp = rp; ! 355: } ! 356: if (op==AAND || op==AOR || op==AXOR || op==ASSIGN) { ! 357: mask = ((MASK)01<<lp->t_width) - 1; ! 358: mask = mask << lp->t_base; ! 359: bmop = AND; ! 360: if (op == AAND) { ! 361: mask = ~mask; ! 362: bmop = OR; ! 363: } ! 364: /* rp set above */ ! 365: rp = leftnode(bmop, rp, rp->t_type); ! 366: fixtoptype(rp); ! 367: if (rp->t_type != rp->t_lp->t_type) ! 368: rp->t_lp = leftnode(CONVERT, rp->t_lp, rp->t_type); ! 369: rp->t_rp = ivalnode((ival_t)mask); ! 370: tp->t_rp = rp; ! 371: } ! 372: if (c != MEFFECT) ! 373: tp = modefld(tp, lp, c, 0); ! 374: if (isbyte(lt)) ! 375: lp->t_type = FLD8; ! 376: else if (isword(lt)) ! 377: lp->t_type = FLD16; ! 378: else ! 379: lp->t_type = FLD32; ! 380: return tp; ! 381: } ! 382: ! 383: /* ! 384: * Rewrite field extraction. ! 385: * The argument "tp" is the base of the field. ! 386: * The argument "fp" is a FIELD node that supplies the width and the base. ! 387: * The argument "flag" is true to enable the mask off in unsigned field extract. ! 388: */ ! 389: TREE * ! 390: modefld(tp, fp, c, flag) register TREE *tp, *fp; int c, flag; ! 391: { ! 392: register int n, tt; ! 393: register MASK mask; ! 394: ! 395: if (isbyte(tt = tp->t_type) || isword(tt)) { ! 396: /* Byte and word fields. Make the top a computational type. */ ! 397: tp = leftnode(CONVERT, tp, tt); ! 398: fixtoptype(tp); ! 399: tt = tp->t_type; ! 400: } ! 401: if (c == MFLOW) { ! 402: /* In a flow context, the field offset is irrelevant. */ ! 403: mask = ((MASK)1 << fp->t_width) - 1; ! 404: if ((n = fp->t_base) != 0) ! 405: mask <<= n; ! 406: tp = leftnode(AND, tp, tt); ! 407: tp->t_rp = ivalnode((ival_t)mask); ! 408: return tp; ! 409: } ! 410: if (isuns(tt) || fp->t_width==1) { ! 411: /* Unsigned fields: shift right and mask to extract. */ ! 412: /* Field width 1 is a special case, can be treated like unsigned. */ ! 413: if ((n = fp->t_base) != 0) { ! 414: tp = leftnode(SHR, tp, tt); ! 415: tp->t_rp = ivalnode((ival_t)n); ! 416: } ! 417: if (flag) { ! 418: tp = leftnode(AND, tp, tt); ! 419: tp->t_rp = ivalnode(((ival_t)1 << fp->t_width) - 1); ! 420: } ! 421: return tp; ! 422: } ! 423: /* Signed fields: shift left and then right to extract and sign extend. */ ! 424: if ((n = 32 - (fp->t_base + fp->t_width)) != 0) { ! 425: tp = leftnode(SHL, tp, tt); ! 426: tp->t_rp = ivalnode((ival_t)n); ! 427: } ! 428: if ((n = 32 - fp->t_width) != 0) { ! 429: tp = leftnode(SHR, tp, tt); ! 430: tp->t_rp = ivalnode((ival_t)n); ! 431: } ! 432: return tp; ! 433: } ! 434: ! 435: /* ! 436: * Check if a tree should have its left and right subtrees swapped. ! 437: * Do it if it is required. ! 438: * Sometimes the relational operation must be adjusted. ! 439: */ ! 440: modswap(tp, ptp) register TREE *tp; TREE *ptp; ! 441: { ! 442: register TREE *lp, *rp; ! 443: FLAG lf, rf; ! 444: ! 445: switch (tp->t_op) { ! 446: ! 447: case ADD: ! 448: case MUL: ! 449: case AND: ! 450: case OR: ! 451: case XOR: ! 452: case EQ: ! 453: case NE: ! 454: case GT: ! 455: case GE: ! 456: case LT: ! 457: case LE: ! 458: case UGT: ! 459: case UGE: ! 460: case ULT: ! 461: case ULE: ! 462: lp = tp->t_lp; ! 463: rp = tp->t_rp; ! 464: lf = lp->t_flag; ! 465: rf = rp->t_flag; ! 466: if (lf!=0 || rf!=0) { ! 467: if ((lf&T_CON) != 0 ! 468: || (rf&T_REG) != 0 ! 469: || (lf!=0 && rf==0)) ! 470: swapit(tp); ! 471: } else if (lp->t_cost > rp->t_cost) ! 472: swapit(tp); ! 473: } ! 474: } ! 475: ! 476: /* ! 477: * Swap subtrees. ! 478: * Fix up relational ops. ! 479: */ ! 480: swapit(tp) register TREE *tp; ! 481: { ! 482: register TREE *xp; ! 483: register op; ! 484: ! 485: xp = tp->t_lp; ! 486: tp->t_lp = tp->t_rp; ! 487: tp->t_rp = xp; ! 488: op = tp->t_op; ! 489: if (isrelop(op)) ! 490: tp->t_op = fliprel[op-EQ]; ! 491: } ! 492: ! 493: /* ! 494: * Convert integer constant val to type t. ! 495: */ ! 496: lval_t ! 497: constcvt(t, val) register int t; lval_t val; ! 498: { ! 499: if (isbyte(t)) ! 500: val &= 0xFFL; ! 501: else if (isword(t)) ! 502: val &= 0xFFFFL; ! 503: if (!isuns(t)) { ! 504: if (isbyte(t) && (val & 0x80L) != 0) ! 505: val |= 0xFFFFFF00L; ! 506: else if (isword(t) && (val & 0x8000L) != 0) ! 507: val |= 0xFFFF0000L; ! 508: } ! 509: return val; ! 510: } ! 511: ! 512: /* end of n1/i386/mtree2.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.