|
|
1.1 ! root 1: /* Medium-level subroutines: convert bit-field store and extract ! 2: and shifts, multiplies and divides to rtl instructions. ! 3: Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc. ! 4: ! 5: This file is part of GNU CC. ! 6: ! 7: GNU CC is free software; you can redistribute it and/or modify ! 8: it under the terms of the GNU General Public License as published by ! 9: the Free Software Foundation; either version 2, or (at your option) ! 10: any later version. ! 11: ! 12: GNU CC is distributed in the hope that it will be useful, ! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: GNU General Public License for more details. ! 16: ! 17: You should have received a copy of the GNU General Public License ! 18: along with GNU CC; see the file COPYING. If not, write to ! 19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 20: ! 21: ! 22: #include "config.h" ! 23: #include "rtl.h" ! 24: #include "tree.h" ! 25: #include "flags.h" ! 26: #include "insn-flags.h" ! 27: #include "insn-codes.h" ! 28: #include "insn-config.h" ! 29: #include "expr.h" ! 30: #include "real.h" ! 31: #include "recog.h" ! 32: ! 33: static rtx extract_split_bit_field (); ! 34: static rtx extract_fixed_bit_field (); ! 35: static void store_split_bit_field (); ! 36: static void store_fixed_bit_field (); ! 37: static rtx mask_rtx (); ! 38: static rtx lshift_value (); ! 39: ! 40: #define CEIL(x,y) (((x) + (y) - 1) / (y)) ! 41: ! 42: /* Non-zero means multiply instructions are cheaper than shifts. */ ! 43: int mult_is_very_cheap; ! 44: ! 45: /* Non-zero means divides or modulus operations are relatively cheap for ! 46: powers of two, so don't use branches; emit the operation instead. ! 47: Usually, this will mean that the MD file will emit non-branch ! 48: sequences. */ ! 49: ! 50: static int sdiv_pow2_cheap, smod_pow2_cheap; ! 51: ! 52: /* Cost of various pieces of RTL. */ ! 53: static int add_cost, shift_cost, mult_cost, negate_cost, lea_cost; ! 54: ! 55: /* Max scale factor for scaled address in lea instruction. */ ! 56: static int lea_max_mul; ! 57: ! 58: void ! 59: init_expmed () ! 60: { ! 61: char *free_point = (char *) oballoc (1); ! 62: /* This is "some random pseudo register" for purposes of calling recog ! 63: to see what insns exist. */ ! 64: rtx reg = gen_rtx (REG, word_mode, FIRST_PSEUDO_REGISTER); ! 65: rtx pow2 = gen_rtx (CONST_INT, VOIDmode, 32); ! 66: rtx lea; ! 67: int i, dummy; ! 68: ! 69: add_cost = rtx_cost (gen_rtx (PLUS, word_mode, reg, reg)); ! 70: shift_cost = rtx_cost (gen_rtx (LSHIFT, word_mode, reg, ! 71: /* Using a constant gives better ! 72: estimate of typical costs. ! 73: 1 or 2 might have quirks. */ ! 74: gen_rtx (CONST_INT, VOIDmode, 3))); ! 75: mult_cost = rtx_cost (gen_rtx (MULT, word_mode, reg, reg)); ! 76: negate_cost = rtx_cost (gen_rtx (NEG, word_mode, reg)); ! 77: ! 78: mult_is_very_cheap ! 79: = (rtx_cost (gen_rtx (MULT, word_mode, reg, ! 80: gen_rtx (CONST_INT, VOIDmode, 128))) ! 81: < rtx_cost (gen_rtx (LSHIFT, word_mode, reg, ! 82: gen_rtx (CONST_INT, VOIDmode, 7)))); ! 83: ! 84: sdiv_pow2_cheap ! 85: = rtx_cost (gen_rtx (DIV, word_mode, reg, pow2)) <= 2 * add_cost; ! 86: smod_pow2_cheap ! 87: = rtx_cost (gen_rtx (MOD, word_mode, reg, pow2)) <= 2 * add_cost; ! 88: ! 89: init_recog (); ! 90: for (i = 2;; i <<= 1) ! 91: { ! 92: lea = gen_rtx (SET, VOIDmode, reg, ! 93: gen_rtx (PLUS, word_mode, reg, ! 94: gen_rtx (MULT, word_mode, reg, ! 95: gen_rtx (CONST_INT, VOIDmode, i)))); ! 96: /* Using 0 as second argument is not quite right, ! 97: but what else is there to do? */ ! 98: if (recog (lea, 0, &dummy) < 0) ! 99: break; ! 100: lea_max_mul = i; ! 101: lea_cost = rtx_cost (SET_SRC (lea)); ! 102: } ! 103: ! 104: /* Free the objects we just allocated. */ ! 105: obfree (free_point); ! 106: } ! 107: ! 108: /* Return an rtx representing minus the value of X. ! 109: MODE is the intended mode of the result, ! 110: useful if X is a CONST_INT. */ ! 111: ! 112: rtx ! 113: negate_rtx (mode, x) ! 114: enum machine_mode mode; ! 115: rtx x; ! 116: { ! 117: if (GET_CODE (x) == CONST_INT) ! 118: { ! 119: int val = - INTVAL (x); ! 120: if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) ! 121: { ! 122: /* Sign extend the value from the bits that are significant. */ ! 123: if (val & (1 << (GET_MODE_BITSIZE (mode) - 1))) ! 124: val |= (-1) << GET_MODE_BITSIZE (mode); ! 125: else ! 126: val &= (1 << GET_MODE_BITSIZE (mode)) - 1; ! 127: } ! 128: return gen_rtx (CONST_INT, VOIDmode, val); ! 129: } ! 130: else ! 131: return expand_unop (GET_MODE (x), neg_optab, x, 0, 0); ! 132: } ! 133: ! 134: /* Generate code to store value from rtx VALUE ! 135: into a bit-field within structure STR_RTX ! 136: containing BITSIZE bits starting at bit BITNUM. ! 137: FIELDMODE is the machine-mode of the FIELD_DECL node for this field. ! 138: ALIGN is the alignment that STR_RTX is known to have, measured in bytes. ! 139: TOTAL_SIZE is the size of the structure in bytes, or -1 if varying. */ ! 140: ! 141: /* ??? Note that there are two different ideas here for how ! 142: to determine the size to count bits within, for a register. ! 143: One is BITS_PER_WORD, and the other is the size of operand 3 ! 144: of the insv pattern. (The latter assumes that an n-bit machine ! 145: will be able to insert bit fields up to n bits wide.) ! 146: It isn't certain that either of these is right. ! 147: extract_bit_field has the same quandary. */ ! 148: ! 149: rtx ! 150: store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size) ! 151: rtx str_rtx; ! 152: register int bitsize; ! 153: int bitnum; ! 154: enum machine_mode fieldmode; ! 155: rtx value; ! 156: int align; ! 157: int total_size; ! 158: { ! 159: int unit = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD; ! 160: register int offset = bitnum / unit; ! 161: register int bitpos = bitnum % unit; ! 162: register rtx op0 = str_rtx; ! 163: ! 164: if (GET_CODE (str_rtx) == MEM && ! MEM_IN_STRUCT_P (str_rtx)) ! 165: abort (); ! 166: ! 167: /* Discount the part of the structure before the desired byte. ! 168: We need to know how many bytes are safe to reference after it. */ ! 169: if (total_size >= 0) ! 170: total_size -= (bitpos / BIGGEST_ALIGNMENT ! 171: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); ! 172: ! 173: while (GET_CODE (op0) == SUBREG) ! 174: { ! 175: /* The following line once was done only if WORDS_BIG_ENDIAN, ! 176: but I think that is a mistake. WORDS_BIG_ENDIAN is ! 177: meaningful at a much higher level; when structures are copied ! 178: between memory and regs, the higher-numbered regs ! 179: always get higher addresses. */ ! 180: offset += SUBREG_WORD (op0); ! 181: /* We used to adjust BITPOS here, but now we do the whole adjustment ! 182: right after the loop. */ ! 183: op0 = SUBREG_REG (op0); ! 184: } ! 185: ! 186: #if BYTES_BIG_ENDIAN ! 187: /* If OP0 is a register, BITPOS must count within a word. ! 188: But as we have it, it counts within whatever size OP0 now has. ! 189: On a bigendian machine, these are not the same, so convert. */ ! 190: if (GET_CODE (op0) != MEM && unit > GET_MODE_BITSIZE (GET_MODE (op0))) ! 191: bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0)); ! 192: #endif ! 193: ! 194: value = protect_from_queue (value, 0); ! 195: ! 196: if (flag_force_mem) ! 197: value = force_not_mem (value); ! 198: ! 199: /* Note that the adjustment of BITPOS above has no effect on whether ! 200: BITPOS is 0 in a REG bigger than a word. */ ! 201: if (GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD && GET_CODE (op0) != MEM ! 202: && bitpos == 0 && bitsize == GET_MODE_BITSIZE (fieldmode)) ! 203: { ! 204: /* Storing in a full-word or multi-word field in a register ! 205: can be done with just SUBREG. */ ! 206: if (GET_MODE (op0) != fieldmode) ! 207: op0 = gen_rtx (SUBREG, fieldmode, op0, offset); ! 208: emit_move_insn (op0, value); ! 209: return value; ! 210: } ! 211: ! 212: /* Storing an lsb-aligned field in a register ! 213: can be done with a movestrict instruction. */ ! 214: ! 215: if (GET_CODE (op0) != MEM ! 216: #if BYTES_BIG_ENDIAN ! 217: && bitpos + bitsize == unit ! 218: #else ! 219: && bitpos == 0 ! 220: #endif ! 221: && bitsize == GET_MODE_BITSIZE (fieldmode) ! 222: && (GET_MODE (op0) == fieldmode ! 223: || (movstrict_optab->handlers[(int) fieldmode].insn_code ! 224: != CODE_FOR_nothing))) ! 225: { ! 226: /* Get appropriate low part of the value being stored. */ ! 227: if (GET_CODE (value) == CONST_INT || GET_CODE (value) == REG) ! 228: value = gen_lowpart (fieldmode, value); ! 229: else if (!(GET_CODE (value) == SYMBOL_REF ! 230: || GET_CODE (value) == LABEL_REF ! 231: || GET_CODE (value) == CONST)) ! 232: value = convert_to_mode (fieldmode, value, 0); ! 233: ! 234: if (GET_MODE (op0) == fieldmode) ! 235: emit_move_insn (op0, value); ! 236: else ! 237: { ! 238: int icode = movstrict_optab->handlers[(int) fieldmode].insn_code; ! 239: if(! (*insn_operand_predicate[icode][1]) (value, fieldmode)) ! 240: value = copy_to_mode_reg (fieldmode, value); ! 241: emit_insn (GEN_FCN (icode) ! 242: (gen_rtx (SUBREG, fieldmode, op0, offset), value)); ! 243: } ! 244: return value; ! 245: } ! 246: ! 247: /* Handle fields bigger than a word. */ ! 248: ! 249: if (bitsize > BITS_PER_WORD) ! 250: { ! 251: /* Here we transfer the words of the field ! 252: in the order least significant first. ! 253: This is because the most significant word is the one which may ! 254: be less than full. */ ! 255: ! 256: int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD; ! 257: int i; ! 258: ! 259: /* This is the mode we must force value to, so that there will be enough ! 260: subwords to extract. Note that fieldmode will often (always?) be ! 261: VOIDmode, because that is what store_field uses to indicate that this ! 262: is a bit field, but passing VOIDmode to operand_subword_force will ! 263: result in an abort. */ ! 264: fieldmode = mode_for_size (nwords * BITS_PER_WORD, MODE_INT, 0); ! 265: ! 266: for (i = 0; i < nwords; i++) ! 267: { ! 268: /* If I is 0, use the low-order word in both field and target; ! 269: if I is 1, use the next to lowest word; and so on. */ ! 270: int wordnum = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); ! 271: int bit_offset = (WORDS_BIG_ENDIAN ! 272: ? MAX (bitsize - (i + 1) * BITS_PER_WORD, 0) ! 273: : i * BITS_PER_WORD); ! 274: store_bit_field (op0, MIN (BITS_PER_WORD, ! 275: bitsize - i * BITS_PER_WORD), ! 276: bitnum + bit_offset, word_mode, ! 277: operand_subword_force (value, wordnum, fieldmode), ! 278: align, total_size); ! 279: } ! 280: return value; ! 281: } ! 282: ! 283: /* From here on we can assume that the field to be stored in is ! 284: a full-word (whatever type that is), since it is shorter than a word. */ ! 285: ! 286: /* OFFSET is the number of words or bytes (UNIT says which) ! 287: from STR_RTX to the first word or byte containing part of the field. */ ! 288: ! 289: if (GET_CODE (op0) == REG) ! 290: { ! 291: if (offset != 0 ! 292: || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD) ! 293: op0 = gen_rtx (SUBREG, TYPE_MODE (type_for_size (BITS_PER_WORD, 0)), ! 294: op0, offset); ! 295: offset = 0; ! 296: } ! 297: else ! 298: { ! 299: op0 = protect_from_queue (op0, 1); ! 300: } ! 301: ! 302: /* Now OFFSET is nonzero only if OP0 is memory ! 303: and is therefore always measured in bytes. */ ! 304: ! 305: #ifdef HAVE_insv ! 306: if (HAVE_insv ! 307: && !(bitsize == 1 && GET_CODE (value) == CONST_INT) ! 308: /* Ensure insv's size is wide enough for this field. */ ! 309: && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]) ! 310: >= bitsize)) ! 311: { ! 312: int xbitpos = bitpos; ! 313: rtx value1; ! 314: rtx xop0 = op0; ! 315: rtx last = get_last_insn (); ! 316: rtx pat; ! 317: enum machine_mode maxmode ! 318: = insn_operand_mode[(int) CODE_FOR_insv][3]; ! 319: ! 320: int save_volatile_ok = volatile_ok; ! 321: volatile_ok = 1; ! 322: ! 323: /* If this machine's insv can only insert into a register, or if we ! 324: are to force MEMs into a register, copy OP0 into a register and ! 325: save it back later. */ ! 326: if (GET_CODE (op0) == MEM ! 327: && (flag_force_mem ! 328: || ! ((*insn_operand_predicate[(int) CODE_FOR_insv][0]) ! 329: (op0, VOIDmode)))) ! 330: { ! 331: rtx tempreg; ! 332: enum machine_mode bestmode; ! 333: ! 334: /* Get the mode to use for inserting into this field. If OP0 is ! 335: BLKmode, get the smallest mode consistent with the alignment. If ! 336: OP0 is a non-BLKmode object that is no wider than MAXMODE, use its ! 337: mode. Otherwise, use the smallest mode containing the field. */ ! 338: ! 339: if (GET_MODE (op0) == BLKmode ! 340: || GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (maxmode)) ! 341: bestmode ! 342: = get_best_mode (bitsize, bitnum, ! 343: align * BITS_PER_UNIT, maxmode, ! 344: GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0)); ! 345: else ! 346: bestmode = GET_MODE (op0); ! 347: ! 348: if (bestmode == VOIDmode) ! 349: goto insv_loses; ! 350: ! 351: /* Adjust address to point to the containing unit of that mode. */ ! 352: unit = GET_MODE_BITSIZE (bestmode); ! 353: /* Compute offset as multiple of this unit, counting in bytes. */ ! 354: offset = (bitnum / unit) * GET_MODE_SIZE (bestmode); ! 355: bitpos = bitnum % unit; ! 356: op0 = change_address (op0, bestmode, ! 357: plus_constant (XEXP (op0, 0), offset)); ! 358: ! 359: /* Fetch that unit, store the bitfield in it, then store the unit. */ ! 360: tempreg = copy_to_reg (op0); ! 361: store_bit_field (tempreg, bitsize, bitpos, fieldmode, value, ! 362: align, total_size); ! 363: emit_move_insn (op0, tempreg); ! 364: return value; ! 365: } ! 366: volatile_ok = save_volatile_ok; ! 367: ! 368: /* Add OFFSET into OP0's address. */ ! 369: if (GET_CODE (xop0) == MEM) ! 370: xop0 = change_address (xop0, byte_mode, ! 371: plus_constant (XEXP (xop0, 0), offset)); ! 372: ! 373: /* If xop0 is a register, we need it in MAXMODE ! 374: to make it acceptable to the format of insv. */ ! 375: if (GET_CODE (xop0) == SUBREG) ! 376: PUT_MODE (xop0, maxmode); ! 377: if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode) ! 378: xop0 = gen_rtx (SUBREG, maxmode, xop0, 0); ! 379: ! 380: /* On big-endian machines, we count bits from the most significant. ! 381: If the bit field insn does not, we must invert. */ ! 382: ! 383: #if BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN ! 384: xbitpos = unit - bitsize - xbitpos; ! 385: #endif ! 386: /* We have been counting XBITPOS within UNIT. ! 387: Count instead within the size of the register. */ ! 388: #if BITS_BIG_ENDIAN ! 389: if (GET_CODE (xop0) != MEM) ! 390: xbitpos += GET_MODE_BITSIZE (maxmode) - unit; ! 391: #endif ! 392: unit = GET_MODE_BITSIZE (maxmode); ! 393: ! 394: /* Convert VALUE to maxmode (which insv insn wants) in VALUE1. */ ! 395: value1 = value; ! 396: if (GET_MODE (value) != maxmode) ! 397: { ! 398: if (GET_MODE_BITSIZE (GET_MODE (value)) >= bitsize) ! 399: { ! 400: /* Optimization: Don't bother really extending VALUE ! 401: if it has all the bits we will actually use. */ ! 402: ! 403: /* Avoid making subreg of a subreg, or of a mem. */ ! 404: if (GET_CODE (value1) != REG) ! 405: value1 = copy_to_reg (value1); ! 406: value1 = gen_rtx (SUBREG, maxmode, value1, 0); ! 407: } ! 408: else if (!CONSTANT_P (value)) ! 409: /* Parse phase is supposed to make VALUE's data type ! 410: match that of the component reference, which is a type ! 411: at least as wide as the field; so VALUE should have ! 412: a mode that corresponds to that type. */ ! 413: abort (); ! 414: } ! 415: ! 416: /* If this machine's insv insists on a register, ! 417: get VALUE1 into a register. */ ! 418: if (! ((*insn_operand_predicate[(int) CODE_FOR_insv][3]) ! 419: (value1, maxmode))) ! 420: value1 = force_reg (maxmode, value1); ! 421: ! 422: pat = gen_insv (xop0, ! 423: gen_rtx (CONST_INT, VOIDmode, bitsize), ! 424: gen_rtx (CONST_INT, VOIDmode, xbitpos), ! 425: value1); ! 426: if (pat) ! 427: emit_insn (pat); ! 428: else ! 429: { ! 430: delete_insns_since (last); ! 431: store_fixed_bit_field (op0, offset, bitsize, bitpos, value, align); ! 432: } ! 433: } ! 434: else ! 435: insv_loses: ! 436: #endif ! 437: /* Insv is not available; store using shifts and boolean ops. */ ! 438: store_fixed_bit_field (op0, offset, bitsize, bitpos, value, align); ! 439: return value; ! 440: } ! 441: ! 442: /* Use shifts and boolean operations to store VALUE ! 443: into a bit field of width BITSIZE ! 444: in a memory location specified by OP0 except offset by OFFSET bytes. ! 445: (OFFSET must be 0 if OP0 is a register.) ! 446: The field starts at position BITPOS within the byte. ! 447: (If OP0 is a register, it may be a full word or a narrower mode, ! 448: but BITPOS still counts within a full word, ! 449: which is significant on bigendian machines.) ! 450: STRUCT_ALIGN is the alignment the structure is known to have (in bytes). ! 451: ! 452: Note that protect_from_queue has already been done on OP0 and VALUE. */ ! 453: ! 454: static void ! 455: store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align) ! 456: register rtx op0; ! 457: register int offset, bitsize, bitpos; ! 458: register rtx value; ! 459: int struct_align; ! 460: { ! 461: register enum machine_mode mode; ! 462: int total_bits = BITS_PER_WORD; ! 463: rtx subtarget, temp; ! 464: int all_zero = 0; ! 465: int all_one = 0; ! 466: ! 467: /* Add OFFSET to OP0's address (if it is in memory) ! 468: and if a single byte contains the whole bit field ! 469: change OP0 to a byte. */ ! 470: ! 471: /* There is a case not handled here: ! 472: a structure with a known alignment of just a halfword ! 473: and a field split across two aligned halfwords within the structure. ! 474: Or likewise a structure with a known alignment of just a byte ! 475: and a field split across two bytes. ! 476: Such cases are not supposed to be able to occur. */ ! 477: ! 478: if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG) ! 479: { ! 480: if (offset != 0) ! 481: abort (); ! 482: /* Special treatment for a bit field split across two registers. */ ! 483: if (bitsize + bitpos > BITS_PER_WORD) ! 484: { ! 485: store_split_bit_field (op0, bitsize, bitpos, value, BITS_PER_WORD); ! 486: return; ! 487: } ! 488: } ! 489: else ! 490: { ! 491: /* Get the proper mode to use for this field. We want a mode that ! 492: includes the entire field. If such a mode would be larger than ! 493: a word, we won't be doing the extraction the normal way. */ ! 494: ! 495: mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT, ! 496: struct_align * BITS_PER_UNIT, word_mode, ! 497: GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0)); ! 498: ! 499: if (mode == VOIDmode) ! 500: { ! 501: /* The only way this should occur is if the field spans word ! 502: boundaries. */ ! 503: store_split_bit_field (op0, bitsize, bitpos + offset * BITS_PER_UNIT, ! 504: value, struct_align); ! 505: return; ! 506: } ! 507: ! 508: total_bits = GET_MODE_BITSIZE (mode); ! 509: ! 510: /* Get ref to an aligned byte, halfword, or word containing the field. ! 511: Adjust BITPOS to be position within a word, ! 512: and OFFSET to be the offset of that word. ! 513: Then alter OP0 to refer to that word. */ ! 514: bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT; ! 515: offset -= (offset % (total_bits / BITS_PER_UNIT)); ! 516: op0 = change_address (op0, mode, ! 517: plus_constant (XEXP (op0, 0), offset)); ! 518: } ! 519: ! 520: mode = GET_MODE (op0); ! 521: ! 522: /* Now MODE is either some integral mode for a MEM as OP0, ! 523: or is a full-word for a REG as OP0. TOTAL_BITS corresponds. ! 524: The bit field is contained entirely within OP0. ! 525: BITPOS is the starting bit number within OP0. ! 526: (OP0's mode may actually be narrower than MODE.) */ ! 527: ! 528: #if BYTES_BIG_ENDIAN ! 529: /* BITPOS is the distance between our msb ! 530: and that of the containing datum. ! 531: Convert it to the distance from the lsb. */ ! 532: ! 533: bitpos = total_bits - bitsize - bitpos; ! 534: #endif ! 535: /* Now BITPOS is always the distance between our lsb ! 536: and that of OP0. */ ! 537: ! 538: /* Shift VALUE left by BITPOS bits. If VALUE is not constant, ! 539: we must first convert its mode to MODE. */ ! 540: ! 541: if (GET_CODE (value) == CONST_INT) ! 542: { ! 543: register int v = INTVAL (value); ! 544: ! 545: if (bitsize < HOST_BITS_PER_INT) ! 546: v &= (1 << bitsize) - 1; ! 547: ! 548: if (v == 0) ! 549: all_zero = 1; ! 550: else if ((bitsize < HOST_BITS_PER_INT && v == (1 << bitsize) - 1) ! 551: || (bitsize == HOST_BITS_PER_INT && v == -1)) ! 552: all_one = 1; ! 553: ! 554: value = lshift_value (mode, value, bitpos, bitsize); ! 555: } ! 556: else ! 557: { ! 558: int must_and = (GET_MODE_BITSIZE (GET_MODE (value)) != bitsize ! 559: && bitpos + bitsize != GET_MODE_BITSIZE (mode)); ! 560: ! 561: if (GET_MODE (value) != mode) ! 562: { ! 563: /* If VALUE is a floating-point mode, access it as an integer ! 564: of the corresponding size, then convert it. This can occur on ! 565: a machine with 64 bit registers that uses SFmode for float. */ ! 566: if (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT) ! 567: { ! 568: if (GET_CODE (value) != REG) ! 569: value = copy_to_reg (value); ! 570: value ! 571: = gen_rtx (SUBREG, word_mode, value, 0); ! 572: } ! 573: ! 574: if ((GET_CODE (value) == REG || GET_CODE (value) == SUBREG) ! 575: && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (value))) ! 576: value = gen_lowpart (mode, value); ! 577: else ! 578: value = convert_to_mode (mode, value, 1); ! 579: } ! 580: ! 581: if (must_and) ! 582: value = expand_binop (mode, and_optab, value, ! 583: mask_rtx (mode, 0, bitsize, 0), ! 584: 0, 1, OPTAB_LIB_WIDEN); ! 585: if (bitpos > 0) ! 586: value = expand_shift (LSHIFT_EXPR, mode, value, ! 587: build_int_2 (bitpos, 0), 0, 1); ! 588: } ! 589: ! 590: /* Now clear the chosen bits in OP0, ! 591: except that if VALUE is -1 we need not bother. */ ! 592: ! 593: subtarget = (GET_CODE (op0) == REG || ! flag_force_mem) ? op0 : 0; ! 594: ! 595: if (! all_one) ! 596: { ! 597: temp = expand_binop (mode, and_optab, op0, ! 598: mask_rtx (mode, bitpos, bitsize, 1), ! 599: subtarget, 1, OPTAB_LIB_WIDEN); ! 600: subtarget = temp; ! 601: } ! 602: else ! 603: temp = op0; ! 604: ! 605: /* Now logical-or VALUE into OP0, unless it is zero. */ ! 606: ! 607: if (! all_zero) ! 608: temp = expand_binop (mode, ior_optab, temp, value, ! 609: subtarget, 1, OPTAB_LIB_WIDEN); ! 610: if (op0 != temp) ! 611: emit_move_insn (op0, temp); ! 612: } ! 613: ! 614: /* Store a bit field that is split across two words. ! 615: ! 616: OP0 is the REG, SUBREG or MEM rtx for the first of the two words. ! 617: BITSIZE is the field width; BITPOS the position of its first bit ! 618: (within the word). ! 619: VALUE is the value to store. */ ! 620: ! 621: static void ! 622: store_split_bit_field (op0, bitsize, bitpos, value, align) ! 623: rtx op0; ! 624: int bitsize, bitpos; ! 625: rtx value; ! 626: int align; ! 627: { ! 628: /* BITSIZE_1 is size of the part in the first word. */ ! 629: int bitsize_1 = BITS_PER_WORD - bitpos % BITS_PER_WORD; ! 630: /* BITSIZE_2 is size of the rest (in the following word). */ ! 631: int bitsize_2 = bitsize - bitsize_1; ! 632: rtx part1, part2; ! 633: int unit = GET_CODE (op0) == MEM ? BITS_PER_UNIT : BITS_PER_WORD; ! 634: int offset = bitpos / unit; ! 635: rtx word; ! 636: ! 637: /* The field must span exactly one word boundary. */ ! 638: if (bitpos / BITS_PER_WORD != (bitpos + bitsize - 1) / BITS_PER_WORD - 1) ! 639: abort (); ! 640: ! 641: if (GET_MODE (value) != VOIDmode) ! 642: value = convert_to_mode (word_mode, value, 1); ! 643: if (CONSTANT_P (value) && GET_CODE (value) != CONST_INT) ! 644: value = copy_to_reg (value); ! 645: ! 646: /* Split the value into two parts: ! 647: PART1 gets that which goes in the first word; PART2 the other. */ ! 648: #if BYTES_BIG_ENDIAN ! 649: /* PART1 gets the more significant part. */ ! 650: if (GET_CODE (value) == CONST_INT) ! 651: { ! 652: part1 = gen_rtx (CONST_INT, VOIDmode, ! 653: (unsigned) (INTVAL (value)) >> bitsize_2); ! 654: part2 = gen_rtx (CONST_INT, VOIDmode, ! 655: (unsigned) (INTVAL (value)) & ((1 << bitsize_2) - 1)); ! 656: } ! 657: else ! 658: { ! 659: part1 = extract_fixed_bit_field (word_mode, value, 0, bitsize_1, ! 660: BITS_PER_WORD - bitsize, 0, 1, ! 661: BITS_PER_WORD); ! 662: part2 = extract_fixed_bit_field (word_mode, value, 0, bitsize_2, ! 663: BITS_PER_WORD - bitsize_2, 0, 1, ! 664: BITS_PER_WORD); ! 665: } ! 666: #else ! 667: /* PART1 gets the less significant part. */ ! 668: if (GET_CODE (value) == CONST_INT) ! 669: { ! 670: part1 = gen_rtx (CONST_INT, VOIDmode, ! 671: (unsigned) (INTVAL (value)) & ((1 << bitsize_1) - 1)); ! 672: part2 = gen_rtx (CONST_INT, VOIDmode, ! 673: (unsigned) (INTVAL (value)) >> bitsize_1); ! 674: } ! 675: else ! 676: { ! 677: part1 = extract_fixed_bit_field (word_mode, value, 0, bitsize_1, 0, ! 678: 0, 1, BITS_PER_WORD); ! 679: part2 = extract_fixed_bit_field (word_mode, value, 0, bitsize_2, ! 680: bitsize_1, 0, 1, BITS_PER_WORD); ! 681: } ! 682: #endif ! 683: ! 684: /* Store PART1 into the first word. If OP0 is a MEM, pass OP0 and the ! 685: offset computed above. Otherwise, get the proper word and pass an ! 686: offset of zero. */ ! 687: word = (GET_CODE (op0) == MEM ? op0 ! 688: : operand_subword (op0, offset, 1, GET_MODE (op0))); ! 689: if (word == 0) ! 690: abort (); ! 691: ! 692: store_fixed_bit_field (word, GET_CODE (op0) == MEM ? offset : 0, ! 693: bitsize_1, bitpos % unit, part1, align); ! 694: ! 695: /* Offset op0 by 1 word to get to the following one. */ ! 696: if (GET_CODE (op0) == SUBREG) ! 697: word = operand_subword (SUBREG_REG (op0), SUBREG_WORD (op0) + offset + 1, ! 698: 1, VOIDmode); ! 699: else if (GET_CODE (op0) == MEM) ! 700: word = op0; ! 701: else ! 702: word = operand_subword (op0, offset + 1, 1, GET_MODE (op0)); ! 703: ! 704: if (word == 0) ! 705: abort (); ! 706: ! 707: /* Store PART2 into the second word. */ ! 708: store_fixed_bit_field (word, ! 709: (GET_CODE (op0) == MEM ! 710: ? CEIL (offset + 1, UNITS_PER_WORD) * UNITS_PER_WORD ! 711: : 0), ! 712: bitsize_2, 0, part2, align); ! 713: } ! 714: ! 715: /* Generate code to extract a byte-field from STR_RTX ! 716: containing BITSIZE bits, starting at BITNUM, ! 717: and put it in TARGET if possible (if TARGET is nonzero). ! 718: Regardless of TARGET, we return the rtx for where the value is placed. ! 719: It may be a QUEUED. ! 720: ! 721: STR_RTX is the structure containing the byte (a REG or MEM). ! 722: UNSIGNEDP is nonzero if this is an unsigned bit field. ! 723: MODE is the natural mode of the field value once extracted. ! 724: TMODE is the mode the caller would like the value to have; ! 725: but the value may be returned with type MODE instead. ! 726: ! 727: ALIGN is the alignment that STR_RTX is known to have, measured in bytes. ! 728: TOTAL_SIZE is the size in bytes of the containing structure, ! 729: or -1 if varying. ! 730: ! 731: If a TARGET is specified and we can store in it at no extra cost, ! 732: we do so, and return TARGET. ! 733: Otherwise, we return a REG of mode TMODE or MODE, with TMODE preferred ! 734: if they are equally easy. */ ! 735: ! 736: rtx ! 737: extract_bit_field (str_rtx, bitsize, bitnum, unsignedp, ! 738: target, mode, tmode, align, total_size) ! 739: rtx str_rtx; ! 740: register int bitsize; ! 741: int bitnum; ! 742: int unsignedp; ! 743: rtx target; ! 744: enum machine_mode mode, tmode; ! 745: int align; ! 746: int total_size; ! 747: { ! 748: int unit = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD; ! 749: register int offset = bitnum / unit; ! 750: register int bitpos = bitnum % unit; ! 751: register rtx op0 = str_rtx; ! 752: rtx spec_target = target; ! 753: rtx spec_target_subreg = 0; ! 754: ! 755: if (GET_CODE (str_rtx) == MEM && ! MEM_IN_STRUCT_P (str_rtx)) ! 756: abort (); ! 757: ! 758: /* Discount the part of the structure before the desired byte. ! 759: We need to know how many bytes are safe to reference after it. */ ! 760: if (total_size >= 0) ! 761: total_size -= (bitpos / BIGGEST_ALIGNMENT ! 762: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); ! 763: ! 764: if (tmode == VOIDmode) ! 765: tmode = mode; ! 766: ! 767: while (GET_CODE (op0) == SUBREG) ! 768: { ! 769: offset += SUBREG_WORD (op0); ! 770: op0 = SUBREG_REG (op0); ! 771: } ! 772: ! 773: #if BYTES_BIG_ENDIAN ! 774: /* If OP0 is a register, BITPOS must count within a word. ! 775: But as we have it, it counts within whatever size OP0 now has. ! 776: On a bigendian machine, these are not the same, so convert. */ ! 777: if (GET_CODE (op0) != MEM && unit > GET_MODE_BITSIZE (GET_MODE (op0))) ! 778: bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0)); ! 779: #endif ! 780: ! 781: /* Extracting a full-word or multi-word value ! 782: from a structure in a register. ! 783: This can be done with just SUBREG. ! 784: So too extracting a subword value in ! 785: the least significant part of the register. */ ! 786: ! 787: if (GET_CODE (op0) == REG ! 788: && ((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode) ! 789: && bitpos % BITS_PER_WORD == 0) ! 790: || (mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0) != BLKmode ! 791: #if BYTES_BIG_ENDIAN ! 792: && bitpos + bitsize == BITS_PER_WORD ! 793: #else ! 794: && bitpos == 0 ! 795: #endif ! 796: ))) ! 797: { ! 798: enum machine_mode mode1 ! 799: = mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0); ! 800: ! 801: if (mode1 != GET_MODE (op0)) ! 802: op0 = gen_rtx (SUBREG, mode1, op0, offset); ! 803: ! 804: if (mode1 != mode) ! 805: return convert_to_mode (tmode, op0, unsignedp); ! 806: return op0; ! 807: } ! 808: ! 809: /* Handle fields bigger than a word. */ ! 810: ! 811: if (bitsize > BITS_PER_WORD) ! 812: { ! 813: /* Here we transfer the words of the field ! 814: in the order least significant first. ! 815: This is because the most significant word is the one which may ! 816: be less than full. */ ! 817: ! 818: int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD; ! 819: int i; ! 820: ! 821: if (target == 0 || GET_CODE (target) != REG) ! 822: target = gen_reg_rtx (mode); ! 823: ! 824: for (i = 0; i < nwords; i++) ! 825: { ! 826: /* If I is 0, use the low-order word in both field and target; ! 827: if I is 1, use the next to lowest word; and so on. */ ! 828: int wordnum = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); ! 829: int bit_offset = (WORDS_BIG_ENDIAN ! 830: ? MAX (0, bitsize - (i + 1) * BITS_PER_WORD) ! 831: : i * BITS_PER_WORD); ! 832: rtx target_part = operand_subword (target, wordnum, 1, VOIDmode); ! 833: rtx result_part ! 834: = extract_bit_field (op0, MIN (BITS_PER_WORD, ! 835: bitsize - i * BITS_PER_WORD), ! 836: bitnum + bit_offset, ! 837: 1, target_part, mode, word_mode, ! 838: align, total_size); ! 839: ! 840: if (target_part == 0) ! 841: abort (); ! 842: ! 843: if (result_part != target_part) ! 844: emit_move_insn (target_part, result_part); ! 845: } ! 846: ! 847: return target; ! 848: } ! 849: ! 850: /* From here on we know the desired field is smaller than a word ! 851: so we can assume it is an integer. So we can safely extract it as one ! 852: size of integer, if necessary, and then truncate or extend ! 853: to the size that is wanted. */ ! 854: ! 855: /* OFFSET is the number of words or bytes (UNIT says which) ! 856: from STR_RTX to the first word or byte containing part of the field. */ ! 857: ! 858: if (GET_CODE (op0) == REG) ! 859: { ! 860: if (offset != 0 ! 861: || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD) ! 862: op0 = gen_rtx (SUBREG, TYPE_MODE (type_for_size (BITS_PER_WORD, 0)), ! 863: op0, offset); ! 864: offset = 0; ! 865: } ! 866: else ! 867: { ! 868: op0 = protect_from_queue (str_rtx, 1); ! 869: } ! 870: ! 871: /* Now OFFSET is nonzero only for memory operands. */ ! 872: ! 873: if (unsignedp) ! 874: { ! 875: #ifdef HAVE_extzv ! 876: if (HAVE_extzv ! 877: && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]) ! 878: >= bitsize)) ! 879: { ! 880: int xbitpos = bitpos, xoffset = offset; ! 881: rtx bitsize_rtx, bitpos_rtx; ! 882: rtx last = get_last_insn(); ! 883: rtx xop0 = op0; ! 884: rtx xtarget = target; ! 885: rtx xspec_target = spec_target; ! 886: rtx xspec_target_subreg = spec_target_subreg; ! 887: rtx pat; ! 888: enum machine_mode maxmode ! 889: = insn_operand_mode[(int) CODE_FOR_extzv][0]; ! 890: ! 891: if (GET_CODE (xop0) == MEM) ! 892: { ! 893: int save_volatile_ok = volatile_ok; ! 894: volatile_ok = 1; ! 895: ! 896: /* Is the memory operand acceptable? */ ! 897: if (flag_force_mem ! 898: || ! ((*insn_operand_predicate[(int) CODE_FOR_extzv][1]) ! 899: (xop0, GET_MODE (xop0)))) ! 900: { ! 901: /* No, load into a reg and extract from there. */ ! 902: enum machine_mode bestmode; ! 903: ! 904: /* Get the mode to use for inserting into this field. If ! 905: OP0 is BLKmode, get the smallest mode consistent with the ! 906: alignment. If OP0 is a non-BLKmode object that is no ! 907: wider than MAXMODE, use its mode. Otherwise, use the ! 908: smallest mode containing the field. */ ! 909: ! 910: if (GET_MODE (xop0) == BLKmode ! 911: || (GET_MODE_SIZE (GET_MODE (op0)) ! 912: > GET_MODE_SIZE (maxmode))) ! 913: bestmode = get_best_mode (bitsize, bitnum, ! 914: align * BITS_PER_UNIT, maxmode, ! 915: (GET_CODE (xop0) == MEM ! 916: && MEM_VOLATILE_P (xop0))); ! 917: else ! 918: bestmode = GET_MODE (xop0); ! 919: ! 920: if (bestmode == VOIDmode) ! 921: goto extzv_loses; ! 922: ! 923: /* Compute offset as multiple of this unit, ! 924: counting in bytes. */ ! 925: unit = GET_MODE_BITSIZE (bestmode); ! 926: xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode); ! 927: xbitpos = bitnum % unit; ! 928: xop0 = change_address (xop0, bestmode, ! 929: plus_constant (XEXP (xop0, 0), ! 930: xoffset)); ! 931: /* Fetch it to a register in that size. */ ! 932: xop0 = force_reg (bestmode, xop0); ! 933: ! 934: /* XBITPOS counts within UNIT, which is what is expected. */ ! 935: } ! 936: else ! 937: /* Get ref to first byte containing part of the field. */ ! 938: xop0 = change_address (xop0, byte_mode, ! 939: plus_constant (XEXP (xop0, 0), xoffset)); ! 940: ! 941: volatile_ok = save_volatile_ok; ! 942: } ! 943: ! 944: /* If op0 is a register, we need it in MAXMODE (which is usually ! 945: SImode). to make it acceptable to the format of extzv. */ ! 946: if (GET_CODE (xop0) == SUBREG && GET_MODE (xop0) != maxmode) ! 947: abort (); ! 948: if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode) ! 949: xop0 = gen_rtx (SUBREG, maxmode, xop0, 0); ! 950: ! 951: /* On big-endian machines, we count bits from the most significant. ! 952: If the bit field insn does not, we must invert. */ ! 953: #if BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN ! 954: xbitpos = unit - bitsize - xbitpos; ! 955: #endif ! 956: /* Now convert from counting within UNIT to counting in MAXMODE. */ ! 957: #if BITS_BIG_ENDIAN ! 958: if (GET_CODE (xop0) != MEM) ! 959: xbitpos += GET_MODE_BITSIZE (maxmode) - unit; ! 960: #endif ! 961: unit = GET_MODE_BITSIZE (maxmode); ! 962: ! 963: if (xtarget == 0 ! 964: || (flag_force_mem && GET_CODE (xtarget) == MEM)) ! 965: xtarget = xspec_target = gen_reg_rtx (tmode); ! 966: ! 967: if (GET_MODE (xtarget) != maxmode) ! 968: { ! 969: if (GET_CODE (xtarget) == REG) ! 970: xspec_target_subreg = xtarget = gen_lowpart (maxmode, xtarget); ! 971: else ! 972: xtarget = gen_reg_rtx (maxmode); ! 973: } ! 974: ! 975: /* If this machine's extzv insists on a register target, ! 976: make sure we have one. */ ! 977: if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][0]) ! 978: (xtarget, maxmode))) ! 979: xtarget = gen_reg_rtx (maxmode); ! 980: ! 981: bitsize_rtx = gen_rtx (CONST_INT, VOIDmode, bitsize); ! 982: bitpos_rtx = gen_rtx (CONST_INT, VOIDmode, xbitpos); ! 983: ! 984: pat = gen_extzv (protect_from_queue (xtarget, 1), ! 985: xop0, bitsize_rtx, bitpos_rtx); ! 986: if (pat) ! 987: { ! 988: emit_insn (pat); ! 989: target = xtarget; ! 990: spec_target = xspec_target; ! 991: spec_target_subreg = xspec_target_subreg; ! 992: } ! 993: else ! 994: { ! 995: delete_insns_since (last); ! 996: target = extract_fixed_bit_field (tmode, op0, offset, bitsize, ! 997: bitpos, target, 1, align); ! 998: } ! 999: } ! 1000: else ! 1001: extzv_loses: ! 1002: #endif ! 1003: target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, ! 1004: target, 1, align); ! 1005: } ! 1006: else ! 1007: { ! 1008: #ifdef HAVE_extv ! 1009: if (HAVE_extv ! 1010: && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]) ! 1011: >= bitsize)) ! 1012: { ! 1013: int xbitpos = bitpos, xoffset = offset; ! 1014: rtx bitsize_rtx, bitpos_rtx; ! 1015: rtx last = get_last_insn(); ! 1016: rtx xop0 = op0, xtarget = target; ! 1017: rtx xspec_target = spec_target; ! 1018: rtx xspec_target_subreg = spec_target_subreg; ! 1019: rtx pat; ! 1020: enum machine_mode maxmode ! 1021: = insn_operand_mode[(int) CODE_FOR_extv][0]; ! 1022: ! 1023: if (GET_CODE (xop0) == MEM) ! 1024: { ! 1025: /* Is the memory operand acceptable? */ ! 1026: if (! ((*insn_operand_predicate[(int) CODE_FOR_extv][1]) ! 1027: (xop0, GET_MODE (xop0)))) ! 1028: { ! 1029: /* No, load into a reg and extract from there. */ ! 1030: enum machine_mode bestmode; ! 1031: ! 1032: /* Get the mode to use for inserting into this field. If ! 1033: OP0 is BLKmode, get the smallest mode consistent with the ! 1034: alignment. If OP0 is a non-BLKmode object that is no ! 1035: wider than MAXMODE, use its mode. Otherwise, use the ! 1036: smallest mode containing the field. */ ! 1037: ! 1038: if (GET_MODE (xop0) == BLKmode ! 1039: || (GET_MODE_SIZE (GET_MODE (op0)) ! 1040: > GET_MODE_SIZE (maxmode))) ! 1041: bestmode = get_best_mode (bitsize, bitnum, ! 1042: align * BITS_PER_UNIT, maxmode, ! 1043: (GET_CODE (xop0) == MEM ! 1044: && MEM_VOLATILE_P (xop0))); ! 1045: else ! 1046: bestmode = GET_MODE (xop0); ! 1047: ! 1048: if (bestmode == VOIDmode) ! 1049: goto extv_loses; ! 1050: ! 1051: /* Compute offset as multiple of this unit, ! 1052: counting in bytes. */ ! 1053: unit = GET_MODE_BITSIZE (bestmode); ! 1054: xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode); ! 1055: xbitpos = bitnum % unit; ! 1056: xop0 = change_address (xop0, bestmode, ! 1057: plus_constant (XEXP (xop0, 0), ! 1058: xoffset)); ! 1059: /* Fetch it to a register in that size. */ ! 1060: xop0 = force_reg (bestmode, xop0); ! 1061: ! 1062: /* XBITPOS counts within UNIT, which is what is expected. */ ! 1063: } ! 1064: else ! 1065: /* Get ref to first byte containing part of the field. */ ! 1066: xop0 = change_address (xop0, byte_mode, ! 1067: plus_constant (XEXP (xop0, 0), xoffset)); ! 1068: } ! 1069: ! 1070: /* If op0 is a register, we need it in MAXMODE (which is usually ! 1071: SImode) to make it acceptable to the format of extv. */ ! 1072: if (GET_CODE (xop0) == SUBREG && GET_MODE (xop0) != maxmode) ! 1073: abort (); ! 1074: if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode) ! 1075: xop0 = gen_rtx (SUBREG, maxmode, xop0, 0); ! 1076: ! 1077: /* On big-endian machines, we count bits from the most significant. ! 1078: If the bit field insn does not, we must invert. */ ! 1079: #if BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN ! 1080: xbitpos = unit - bitsize - xbitpos; ! 1081: #endif ! 1082: /* XBITPOS counts within a size of UNIT. ! 1083: Adjust to count within a size of MAXMODE. */ ! 1084: #if BITS_BIG_ENDIAN ! 1085: if (GET_CODE (xop0) != MEM) ! 1086: xbitpos += (GET_MODE_BITSIZE (maxmode) - unit); ! 1087: #endif ! 1088: unit = GET_MODE_BITSIZE (maxmode); ! 1089: ! 1090: if (xtarget == 0 ! 1091: || (flag_force_mem && GET_CODE (xtarget) == MEM)) ! 1092: xtarget = xspec_target = gen_reg_rtx (tmode); ! 1093: ! 1094: if (GET_MODE (xtarget) != maxmode) ! 1095: { ! 1096: if (GET_CODE (xtarget) == REG) ! 1097: xspec_target_subreg = xtarget = gen_lowpart (maxmode, xtarget); ! 1098: else ! 1099: xtarget = gen_reg_rtx (maxmode); ! 1100: } ! 1101: ! 1102: /* If this machine's extv insists on a register target, ! 1103: make sure we have one. */ ! 1104: if (! ((*insn_operand_predicate[(int) CODE_FOR_extv][0]) ! 1105: (xtarget, maxmode))) ! 1106: xtarget = gen_reg_rtx (maxmode); ! 1107: ! 1108: bitsize_rtx = gen_rtx (CONST_INT, VOIDmode, bitsize); ! 1109: bitpos_rtx = gen_rtx (CONST_INT, VOIDmode, xbitpos); ! 1110: ! 1111: pat = gen_extv (protect_from_queue (xtarget, 1), ! 1112: xop0, bitsize_rtx, bitpos_rtx); ! 1113: if (pat) ! 1114: { ! 1115: emit_insn (pat); ! 1116: target = xtarget; ! 1117: spec_target = xspec_target; ! 1118: spec_target_subreg = xspec_target_subreg; ! 1119: } ! 1120: else ! 1121: { ! 1122: delete_insns_since (last); ! 1123: target = extract_fixed_bit_field (tmode, op0, offset, bitsize, ! 1124: bitpos, target, 0, align); ! 1125: } ! 1126: } ! 1127: else ! 1128: extv_loses: ! 1129: #endif ! 1130: target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, ! 1131: target, 0, align); ! 1132: } ! 1133: if (target == spec_target) ! 1134: return target; ! 1135: if (target == spec_target_subreg) ! 1136: return spec_target; ! 1137: if (GET_MODE (target) != tmode && GET_MODE (target) != mode) ! 1138: { ! 1139: /* If the target mode is floating-point, first convert to the ! 1140: integer mode of that size and then access it as a floating-point ! 1141: value via a SUBREG. */ ! 1142: if (GET_MODE_CLASS (tmode) == MODE_FLOAT) ! 1143: { ! 1144: target = convert_to_mode (mode_for_size (GET_MODE_BITSIZE (tmode), ! 1145: MODE_INT, 0), ! 1146: target, unsignedp); ! 1147: if (GET_CODE (target) != REG) ! 1148: target = copy_to_reg (target); ! 1149: return gen_rtx (SUBREG, tmode, target, 0); ! 1150: } ! 1151: else ! 1152: return convert_to_mode (tmode, target, unsignedp); ! 1153: } ! 1154: return target; ! 1155: } ! 1156: ! 1157: /* Extract a bit field using shifts and boolean operations ! 1158: Returns an rtx to represent the value. ! 1159: OP0 addresses a register (word) or memory (byte). ! 1160: BITPOS says which bit within the word or byte the bit field starts in. ! 1161: OFFSET says how many bytes farther the bit field starts; ! 1162: it is 0 if OP0 is a register. ! 1163: BITSIZE says how many bits long the bit field is. ! 1164: (If OP0 is a register, it may be narrower than a full word, ! 1165: but BITPOS still counts within a full word, ! 1166: which is significant on bigendian machines.) ! 1167: ! 1168: UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value). ! 1169: If TARGET is nonzero, attempts to store the value there ! 1170: and return TARGET, but this is not guaranteed. ! 1171: If TARGET is not used, create a pseudo-reg of mode TMODE for the value. ! 1172: ! 1173: ALIGN is the alignment that STR_RTX is known to have, measured in bytes. */ ! 1174: ! 1175: static rtx ! 1176: extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos, ! 1177: target, unsignedp, align) ! 1178: enum machine_mode tmode; ! 1179: register rtx op0, target; ! 1180: register int offset, bitsize, bitpos; ! 1181: int unsignedp; ! 1182: int align; ! 1183: { ! 1184: int total_bits = BITS_PER_WORD; ! 1185: enum machine_mode mode; ! 1186: ! 1187: if (GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG) ! 1188: { ! 1189: /* Special treatment for a bit field split across two registers. */ ! 1190: if (bitsize + bitpos > BITS_PER_WORD) ! 1191: return extract_split_bit_field (op0, bitsize, bitpos, ! 1192: unsignedp, align); ! 1193: } ! 1194: else ! 1195: { ! 1196: /* Get the proper mode to use for this field. We want a mode that ! 1197: includes the entire field. If such a mode would be larger than ! 1198: a word, we won't be doing the extraction the normal way. */ ! 1199: ! 1200: mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT, ! 1201: align * BITS_PER_UNIT, word_mode, ! 1202: GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0)); ! 1203: ! 1204: if (mode == VOIDmode) ! 1205: /* The only way this should occur is if the field spans word ! 1206: boundaries. */ ! 1207: return extract_split_bit_field (op0, bitsize, ! 1208: bitpos + offset * BITS_PER_UNIT, ! 1209: unsignedp, align); ! 1210: ! 1211: total_bits = GET_MODE_BITSIZE (mode); ! 1212: ! 1213: /* Get ref to an aligned byte, halfword, or word containing the field. ! 1214: Adjust BITPOS to be position within a word, ! 1215: and OFFSET to be the offset of that word. ! 1216: Then alter OP0 to refer to that word. */ ! 1217: bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT; ! 1218: offset -= (offset % (total_bits / BITS_PER_UNIT)); ! 1219: op0 = change_address (op0, mode, ! 1220: plus_constant (XEXP (op0, 0), offset)); ! 1221: } ! 1222: ! 1223: mode = GET_MODE (op0); ! 1224: ! 1225: #if BYTES_BIG_ENDIAN ! 1226: /* BITPOS is the distance between our msb and that of OP0. ! 1227: Convert it to the distance from the lsb. */ ! 1228: ! 1229: bitpos = total_bits - bitsize - bitpos; ! 1230: #endif ! 1231: /* Now BITPOS is always the distance between the field's lsb and that of OP0. ! 1232: We have reduced the big-endian case to the little-endian case. */ ! 1233: ! 1234: if (unsignedp) ! 1235: { ! 1236: if (bitpos) ! 1237: { ! 1238: /* If the field does not already start at the lsb, ! 1239: shift it so it does. */ ! 1240: tree amount = build_int_2 (bitpos, 0); ! 1241: /* Maybe propagate the target for the shift. */ ! 1242: /* But not if we will return it--could confuse integrate.c. */ ! 1243: rtx subtarget = (target != 0 && GET_CODE (target) == REG ! 1244: && !REG_FUNCTION_VALUE_P (target) ! 1245: ? target : 0); ! 1246: if (tmode != mode) subtarget = 0; ! 1247: op0 = expand_shift (RSHIFT_EXPR, mode, op0, amount, subtarget, 1); ! 1248: } ! 1249: /* Convert the value to the desired mode. */ ! 1250: if (mode != tmode) ! 1251: op0 = convert_to_mode (tmode, op0, 1); ! 1252: ! 1253: /* Unless the msb of the field used to be the msb when we shifted, ! 1254: mask out the upper bits. */ ! 1255: ! 1256: if (GET_MODE_BITSIZE (mode) != bitpos + bitsize ! 1257: #if 0 ! 1258: #ifdef SLOW_ZERO_EXTEND ! 1259: /* Always generate an `and' if ! 1260: we just zero-extended op0 and SLOW_ZERO_EXTEND, since it ! 1261: will combine fruitfully with the zero-extend. */ ! 1262: || tmode != mode ! 1263: #endif ! 1264: #endif ! 1265: ) ! 1266: return expand_binop (GET_MODE (op0), and_optab, op0, ! 1267: mask_rtx (GET_MODE (op0), 0, bitsize, 0), ! 1268: target, 1, OPTAB_LIB_WIDEN); ! 1269: return op0; ! 1270: } ! 1271: ! 1272: /* To extract a signed bit-field, first shift its msb to the msb of the word, ! 1273: then arithmetic-shift its lsb to the lsb of the word. */ ! 1274: op0 = force_reg (mode, op0); ! 1275: if (mode != tmode) ! 1276: target = 0; ! 1277: ! 1278: /* Find the narrowest integer mode that contains the field. */ ! 1279: ! 1280: for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; ! 1281: mode = GET_MODE_WIDER_MODE (mode)) ! 1282: if (GET_MODE_BITSIZE (mode) >= bitsize + bitpos) ! 1283: { ! 1284: op0 = convert_to_mode (mode, op0, 0); ! 1285: break; ! 1286: } ! 1287: ! 1288: if (GET_MODE_BITSIZE (mode) != (bitsize + bitpos)) ! 1289: { ! 1290: tree amount = build_int_2 (GET_MODE_BITSIZE (mode) - (bitsize + bitpos), 0); ! 1291: /* Maybe propagate the target for the shift. */ ! 1292: /* But not if we will return the result--could confuse integrate.c. */ ! 1293: rtx subtarget = (target != 0 && GET_CODE (target) == REG ! 1294: && ! REG_FUNCTION_VALUE_P (target) ! 1295: ? target : 0); ! 1296: op0 = expand_shift (LSHIFT_EXPR, mode, op0, amount, subtarget, 1); ! 1297: } ! 1298: ! 1299: return expand_shift (RSHIFT_EXPR, mode, op0, ! 1300: build_int_2 (GET_MODE_BITSIZE (mode) - bitsize, 0), ! 1301: target, 0); ! 1302: } ! 1303: ! 1304: /* Return a constant integer (CONST_INT or CONST_DOUBLE) mask value ! 1305: of mode MODE with BITSIZE ones followed by BITPOS zeros, or the ! 1306: complement of that if COMPLEMENT. The mask is truncated if ! 1307: necessary to the width of mode MODE. */ ! 1308: ! 1309: static rtx ! 1310: mask_rtx (mode, bitpos, bitsize, complement) ! 1311: enum machine_mode mode; ! 1312: int bitpos, bitsize, complement; ! 1313: { ! 1314: int masklow, maskhigh; ! 1315: ! 1316: if (bitpos < HOST_BITS_PER_INT) ! 1317: masklow = -1 << bitpos; ! 1318: else ! 1319: masklow = 0; ! 1320: ! 1321: if (bitpos + bitsize < HOST_BITS_PER_INT) ! 1322: masklow &= (unsigned) -1 >> (HOST_BITS_PER_INT - bitpos - bitsize); ! 1323: ! 1324: if (bitpos <= HOST_BITS_PER_INT) ! 1325: maskhigh = -1; ! 1326: else ! 1327: maskhigh = -1 << (bitpos - HOST_BITS_PER_INT); ! 1328: ! 1329: if (bitpos + bitsize > HOST_BITS_PER_INT) ! 1330: maskhigh &= (unsigned) -1 >> (2 * HOST_BITS_PER_INT - bitpos - bitsize); ! 1331: else ! 1332: maskhigh = 0; ! 1333: ! 1334: if (complement) ! 1335: { ! 1336: maskhigh = ~maskhigh; ! 1337: masklow = ~masklow; ! 1338: } ! 1339: ! 1340: return immed_double_const (masklow, maskhigh, mode); ! 1341: } ! 1342: ! 1343: /* Return a constant integer (CONST_INT or CONST_DOUBLE) rtx with the value ! 1344: VALUE truncated to BITSIZE bits and then shifted left BITPOS bits. */ ! 1345: ! 1346: static rtx ! 1347: lshift_value (mode, value, bitpos, bitsize) ! 1348: enum machine_mode mode; ! 1349: rtx value; ! 1350: int bitpos, bitsize; ! 1351: { ! 1352: unsigned v = INTVAL (value); ! 1353: int low, high; ! 1354: ! 1355: if (bitsize < HOST_BITS_PER_INT) ! 1356: v &= ~(-1 << bitsize); ! 1357: ! 1358: if (bitpos < HOST_BITS_PER_INT) ! 1359: { ! 1360: low = v << bitpos; ! 1361: high = (bitpos > 0 ? (v >> (HOST_BITS_PER_INT - bitpos)) : 0); ! 1362: } ! 1363: else ! 1364: { ! 1365: low = 0; ! 1366: high = v << (bitpos - HOST_BITS_PER_INT); ! 1367: } ! 1368: ! 1369: return immed_double_const (low, high, mode); ! 1370: } ! 1371: ! 1372: /* Extract a bit field that is split across two words ! 1373: and return an RTX for the result. ! 1374: ! 1375: OP0 is the REG, SUBREG or MEM rtx for the first of the two words. ! 1376: BITSIZE is the field width; BITPOS, position of its first bit, in the word. ! 1377: UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend. */ ! 1378: ! 1379: static rtx ! 1380: extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align) ! 1381: rtx op0; ! 1382: int bitsize, bitpos, unsignedp, align; ! 1383: { ! 1384: /* BITSIZE_1 is size of the part in the first word. */ ! 1385: int bitsize_1 = BITS_PER_WORD - bitpos % BITS_PER_WORD; ! 1386: /* BITSIZE_2 is size of the rest (in the following word). */ ! 1387: int bitsize_2 = bitsize - bitsize_1; ! 1388: rtx part1, part2, result; ! 1389: int unit = GET_CODE (op0) == MEM ? BITS_PER_UNIT : BITS_PER_WORD; ! 1390: int offset = bitpos / unit; ! 1391: rtx word; ! 1392: ! 1393: /* The field must span exactly one word boundary. */ ! 1394: if (bitpos / BITS_PER_WORD != (bitpos + bitsize - 1) / BITS_PER_WORD - 1) ! 1395: abort (); ! 1396: ! 1397: /* Get the part of the bit field from the first word. If OP0 is a MEM, ! 1398: pass OP0 and the offset computed above. Otherwise, get the proper ! 1399: word and pass an offset of zero. */ ! 1400: word = (GET_CODE (op0) == MEM ? op0 ! 1401: : operand_subword_force (op0, offset, GET_MODE (op0))); ! 1402: part1 = extract_fixed_bit_field (word_mode, word, ! 1403: GET_CODE (op0) == MEM ? offset : 0, ! 1404: bitsize_1, bitpos % unit, 0, 1, align); ! 1405: ! 1406: /* Offset op0 by 1 word to get to the following one. */ ! 1407: if (GET_CODE (op0) == SUBREG) ! 1408: word = operand_subword_force (SUBREG_REG (op0), ! 1409: SUBREG_WORD (op0) + offset + 1, VOIDmode); ! 1410: else if (GET_CODE (op0) == MEM) ! 1411: word = op0; ! 1412: else ! 1413: word = operand_subword_force (op0, offset + 1, GET_MODE (op0)); ! 1414: ! 1415: /* Get the part of the bit field from the second word. */ ! 1416: part2 = extract_fixed_bit_field (word_mode, word, ! 1417: (GET_CODE (op0) == MEM ! 1418: ? CEIL (offset + 1, UNITS_PER_WORD) * UNITS_PER_WORD ! 1419: : 0), ! 1420: bitsize_2, 0, 0, 1, align); ! 1421: ! 1422: /* Shift the more significant part up to fit above the other part. */ ! 1423: #if BYTES_BIG_ENDIAN ! 1424: part1 = expand_shift (LSHIFT_EXPR, word_mode, part1, ! 1425: build_int_2 (bitsize_2, 0), 0, 1); ! 1426: #else ! 1427: part2 = expand_shift (LSHIFT_EXPR, word_mode, part2, ! 1428: build_int_2 (bitsize_1, 0), 0, 1); ! 1429: #endif ! 1430: ! 1431: /* Combine the two parts with bitwise or. This works ! 1432: because we extracted both parts as unsigned bit fields. */ ! 1433: result = expand_binop (word_mode, ior_optab, part1, part2, 0, 1, ! 1434: OPTAB_LIB_WIDEN); ! 1435: ! 1436: /* Unsigned bit field: we are done. */ ! 1437: if (unsignedp) ! 1438: return result; ! 1439: /* Signed bit field: sign-extend with two arithmetic shifts. */ ! 1440: result = expand_shift (LSHIFT_EXPR, word_mode, result, ! 1441: build_int_2 (BITS_PER_WORD - bitsize, 0), 0, 0); ! 1442: return expand_shift (RSHIFT_EXPR, word_mode, result, ! 1443: build_int_2 (BITS_PER_WORD - bitsize, 0), 0, 0); ! 1444: } ! 1445: ! 1446: /* Add INC into TARGET. */ ! 1447: ! 1448: void ! 1449: expand_inc (target, inc) ! 1450: rtx target, inc; ! 1451: { ! 1452: rtx value = expand_binop (GET_MODE (target), add_optab, ! 1453: target, inc, ! 1454: target, 0, OPTAB_LIB_WIDEN); ! 1455: if (value != target) ! 1456: emit_move_insn (target, value); ! 1457: } ! 1458: ! 1459: /* Subtract INC from TARGET. */ ! 1460: ! 1461: void ! 1462: expand_dec (target, dec) ! 1463: rtx target, dec; ! 1464: { ! 1465: rtx value = expand_binop (GET_MODE (target), sub_optab, ! 1466: target, dec, ! 1467: target, 0, OPTAB_LIB_WIDEN); ! 1468: if (value != target) ! 1469: emit_move_insn (target, value); ! 1470: } ! 1471: ! 1472: /* Output a shift instruction for expression code CODE, ! 1473: with SHIFTED being the rtx for the value to shift, ! 1474: and AMOUNT the tree for the amount to shift by. ! 1475: Store the result in the rtx TARGET, if that is convenient. ! 1476: If UNSIGNEDP is nonzero, do a logical shift; otherwise, arithmetic. ! 1477: Return the rtx for where the value is. */ ! 1478: ! 1479: rtx ! 1480: expand_shift (code, mode, shifted, amount, target, unsignedp) ! 1481: enum tree_code code; ! 1482: register enum machine_mode mode; ! 1483: rtx shifted; ! 1484: tree amount; ! 1485: register rtx target; ! 1486: int unsignedp; ! 1487: { ! 1488: register rtx op1, temp = 0; ! 1489: register int left = (code == LSHIFT_EXPR || code == LROTATE_EXPR); ! 1490: register int rotate = (code == LROTATE_EXPR || code == RROTATE_EXPR); ! 1491: int try; ! 1492: ! 1493: /* Previously detected shift-counts computed by NEGATE_EXPR ! 1494: and shifted in the other direction; but that does not work ! 1495: on all machines. */ ! 1496: ! 1497: op1 = expand_expr (amount, 0, VOIDmode, 0); ! 1498: ! 1499: if (op1 == const0_rtx) ! 1500: return shifted; ! 1501: ! 1502: for (try = 0; temp == 0 && try < 3; try++) ! 1503: { ! 1504: enum optab_methods methods; ! 1505: ! 1506: if (try == 0) ! 1507: methods = OPTAB_DIRECT; ! 1508: else if (try == 1) ! 1509: methods = OPTAB_WIDEN; ! 1510: else ! 1511: methods = OPTAB_LIB_WIDEN; ! 1512: ! 1513: if (rotate) ! 1514: { ! 1515: /* Widening does not work for rotation. */ ! 1516: if (methods == OPTAB_WIDEN) ! 1517: continue; ! 1518: else if (methods == OPTAB_LIB_WIDEN) ! 1519: methods = OPTAB_LIB; ! 1520: ! 1521: temp = expand_binop (mode, ! 1522: left ? rotl_optab : rotr_optab, ! 1523: shifted, op1, target, unsignedp, methods); ! 1524: } ! 1525: else if (unsignedp) ! 1526: { ! 1527: temp = expand_binop (mode, ! 1528: left ? lshl_optab : lshr_optab, ! 1529: shifted, op1, target, unsignedp, methods); ! 1530: if (temp == 0 && left) ! 1531: temp = expand_binop (mode, ashl_optab, ! 1532: shifted, op1, target, unsignedp, methods); ! 1533: } ! 1534: ! 1535: /* Do arithmetic shifts. ! 1536: Also, if we are going to widen the operand, we can just as well ! 1537: use an arithmetic right-shift instead of a logical one. */ ! 1538: if (temp == 0 && ! rotate ! 1539: && (! unsignedp || (! left && methods == OPTAB_WIDEN))) ! 1540: { ! 1541: enum optab_methods methods1 = methods; ! 1542: ! 1543: /* If trying to widen a log shift to an arithmetic shift, ! 1544: don't accept an arithmetic shift of the same size. */ ! 1545: if (unsignedp) ! 1546: methods1 = OPTAB_MUST_WIDEN; ! 1547: ! 1548: /* Arithmetic shift */ ! 1549: ! 1550: temp = expand_binop (mode, ! 1551: left ? ashl_optab : ashr_optab, ! 1552: shifted, op1, target, unsignedp, methods1); ! 1553: } ! 1554: ! 1555: #ifdef HAVE_extzv ! 1556: /* We can do a logical (unsigned) right shift with a bit-field ! 1557: extract insn. But first check if one of the above methods worked. */ ! 1558: if (temp != 0) ! 1559: return temp; ! 1560: ! 1561: if (unsignedp && code == RSHIFT_EXPR && ! BITS_BIG_ENDIAN && HAVE_extzv) ! 1562: { ! 1563: enum machine_mode output_mode ! 1564: = insn_operand_mode[(int) CODE_FOR_extzv][0]; ! 1565: ! 1566: if ((methods == OPTAB_DIRECT && mode == output_mode) ! 1567: || (methods == OPTAB_WIDEN ! 1568: && GET_MODE_SIZE (mode) < GET_MODE_SIZE (output_mode))) ! 1569: { ! 1570: /* Note convert_to_mode does protect_from_queue. */ ! 1571: rtx shifted1 = convert_to_mode (output_mode, shifted, 1); ! 1572: enum machine_mode length_mode ! 1573: = insn_operand_mode[(int) CODE_FOR_extzv][2]; ! 1574: enum machine_mode pos_mode ! 1575: = insn_operand_mode[(int) CODE_FOR_extzv][3]; ! 1576: rtx target1 = 0; ! 1577: rtx last = get_last_insn (); ! 1578: rtx width; ! 1579: rtx xop1 = op1; ! 1580: rtx pat; ! 1581: ! 1582: if (target != 0) ! 1583: target1 = protect_from_queue (target, 1); ! 1584: ! 1585: /* We define extract insns as having OUTPUT_MODE in a register ! 1586: and the mode of operand 1 in memory. Since we want ! 1587: OUTPUT_MODE, we will always force the operand into a ! 1588: register. At some point we might want to support MEM ! 1589: directly. */ ! 1590: shifted1 = force_reg (output_mode, shifted1); ! 1591: ! 1592: /* If we don't have or cannot use a suggested target, ! 1593: make a place for the result, in the proper mode. */ ! 1594: if (methods == OPTAB_WIDEN || target1 == 0 ! 1595: || ! ((*insn_operand_predicate[(int) CODE_FOR_extzv][0]) ! 1596: (target1, output_mode))) ! 1597: target1 = gen_reg_rtx (output_mode); ! 1598: ! 1599: xop1 = convert_to_mode (pos_mode, xop1, ! 1600: TREE_UNSIGNED (TREE_TYPE (amount))); ! 1601: ! 1602: /* If this machine's extzv insists on a register for ! 1603: operand 3 (position), arrange for that. */ ! 1604: if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][3]) ! 1605: (xop1, pos_mode))) ! 1606: xop1 = force_reg (pos_mode, xop1); ! 1607: ! 1608: /* WIDTH gets the width of the bit field to extract: ! 1609: wordsize minus # bits to shift by. */ ! 1610: if (GET_CODE (xop1) == CONST_INT) ! 1611: width = gen_rtx (CONST_INT, VOIDmode, ! 1612: (GET_MODE_BITSIZE (mode) - INTVAL (op1))); ! 1613: else ! 1614: { ! 1615: /* Now get the width in the proper mode. */ ! 1616: width = convert_to_mode (length_mode, op1, ! 1617: TREE_UNSIGNED (TREE_TYPE (amount))); ! 1618: ! 1619: width = expand_binop (length_mode, sub_optab, ! 1620: gen_rtx (CONST_INT, VOIDmode, ! 1621: GET_MODE_BITSIZE (mode)), ! 1622: width, 0, 0, OPTAB_LIB_WIDEN); ! 1623: } ! 1624: ! 1625: /* If this machine's extzv insists on a register for ! 1626: operand 2 (length), arrange for that. */ ! 1627: if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][2]) ! 1628: (width, length_mode))) ! 1629: width = force_reg (length_mode, width); ! 1630: ! 1631: /* Now extract with WIDTH, omitting OP1 least sig bits. */ ! 1632: pat = gen_extzv (target1, shifted1, width, xop1); ! 1633: if (pat) ! 1634: { ! 1635: emit_insn (pat); ! 1636: temp = convert_to_mode (mode, target1, 1); ! 1637: } ! 1638: else ! 1639: delete_insns_since (last); ! 1640: } ! 1641: ! 1642: /* Can also do logical shift with signed bit-field extract ! 1643: followed by inserting the bit-field at a different position. ! 1644: That strategy is not yet implemented. */ ! 1645: } ! 1646: #endif /* HAVE_extzv */ ! 1647: } ! 1648: ! 1649: if (temp == 0) ! 1650: abort (); ! 1651: return temp; ! 1652: } ! 1653: ! 1654: enum alg_code { alg_add, alg_subtract, alg_compound }; ! 1655: ! 1656: /* This structure records a sequence of operations. ! 1657: `ops' is the number of operations recorded. ! 1658: `cost' is their total cost. ! 1659: The operations are stored in `op' and the corresponding ! 1660: integer coefficients in `coeff'. ! 1661: These are the operations: ! 1662: alg_add Add to the total the multiplicand times the coefficient. ! 1663: alg_subtract Subtract the multiplicand times the coefficient. ! 1664: alg_compound This coefficient plus or minus the following one ! 1665: is multiplied into the total. The following operation ! 1666: is alg_add or alg_subtract to indicate whether to add ! 1667: or subtract the two coefficients. */ ! 1668: ! 1669: #ifndef MAX_BITS_PER_WORD ! 1670: #define MAX_BITS_PER_WORD BITS_PER_WORD ! 1671: #endif ! 1672: ! 1673: struct algorithm ! 1674: { ! 1675: int cost; ! 1676: unsigned int ops; ! 1677: enum alg_code op[MAX_BITS_PER_WORD]; ! 1678: unsigned int coeff[MAX_BITS_PER_WORD]; ! 1679: }; ! 1680: ! 1681: /* Compute and return the best algorithm for multiplying by T. ! 1682: Assume that add insns cost ADD_COST and shifts cost SHIFT_COST. ! 1683: Return cost -1 if would cost more than MAX_COST. */ ! 1684: ! 1685: static struct algorithm ! 1686: synth_mult (t, add_cost, shift_cost, max_cost) ! 1687: unsigned int t; ! 1688: int add_cost, shift_cost; ! 1689: int max_cost; ! 1690: { ! 1691: int m, n; ! 1692: struct algorithm *best_alg = (struct algorithm *)alloca (sizeof (struct algorithm)); ! 1693: struct algorithm *alg_in = (struct algorithm *)alloca (sizeof (struct algorithm)); ! 1694: unsigned int cost; ! 1695: ! 1696: /* No matter what happens, we want to return a valid algorithm. */ ! 1697: best_alg->cost = max_cost; ! 1698: best_alg->ops = 0; ! 1699: ! 1700: /* Is t an exponent of 2, so we can just do a shift? */ ! 1701: ! 1702: if ((t & -t) == t) ! 1703: { ! 1704: if (t > 1) ! 1705: { ! 1706: if (max_cost >= shift_cost) ! 1707: { ! 1708: best_alg->cost = shift_cost; ! 1709: best_alg->ops = 1; ! 1710: best_alg->op[0] = alg_add; ! 1711: best_alg->coeff[0] = t; ! 1712: } ! 1713: else ! 1714: best_alg->cost = -1; ! 1715: } ! 1716: else if (t == 1) ! 1717: { ! 1718: if (max_cost >= 0) ! 1719: best_alg->cost = 0; ! 1720: } ! 1721: else ! 1722: best_alg->cost = 0; ! 1723: ! 1724: return *best_alg; ! 1725: } ! 1726: ! 1727: /* If MAX_COST just permits as little as an addition (or less), we won't ! 1728: succeed in synthesizing an algorithm for t. Return immediately with ! 1729: an indication of failure. */ ! 1730: if (max_cost <= add_cost) ! 1731: { ! 1732: best_alg->cost = -1; ! 1733: return *best_alg; ! 1734: } ! 1735: ! 1736: /* Look for factors of t of the form ! 1737: t = q(2**m +- 1), 2 <= m <= floor(log2(t)) - 1. ! 1738: If we find such a factor, we can multiply by t using an algorithm that ! 1739: multiplies by q, shift the result by m and add/subtract it to itself. */ ! 1740: ! 1741: for (m = floor_log2 (t) - 1; m >= 2; m--) ! 1742: { ! 1743: int m_exp_2 = 1 << m; ! 1744: int d; ! 1745: ! 1746: d = m_exp_2 + 1; ! 1747: if (t % d == 0) ! 1748: { ! 1749: int q = t / d; ! 1750: ! 1751: cost = add_cost + shift_cost * 2; ! 1752: ! 1753: *alg_in = synth_mult (q, add_cost, shift_cost, ! 1754: MIN (max_cost, best_alg->cost) - cost); ! 1755: ! 1756: if (alg_in->cost >= 0) ! 1757: { ! 1758: cost += alg_in->cost; ! 1759: ! 1760: if (cost < best_alg->cost) ! 1761: { ! 1762: struct algorithm *x; ! 1763: x = alg_in; ! 1764: alg_in = best_alg; ! 1765: best_alg = x; ! 1766: best_alg->coeff[best_alg->ops] = m_exp_2; ! 1767: best_alg->op[best_alg->ops++] = alg_compound; ! 1768: best_alg->coeff[best_alg->ops] = 1; ! 1769: best_alg->op[best_alg->ops++] = alg_add; ! 1770: best_alg->cost = cost; ! 1771: } ! 1772: } ! 1773: } ! 1774: ! 1775: d = m_exp_2 - 1; ! 1776: if (t % d == 0) ! 1777: { ! 1778: int q = t / d; ! 1779: ! 1780: cost = add_cost + shift_cost * 2; ! 1781: ! 1782: *alg_in = synth_mult (q, add_cost, shift_cost, ! 1783: MIN (max_cost, best_alg->cost) - cost); ! 1784: ! 1785: if (alg_in->cost >= 0) ! 1786: { ! 1787: cost += alg_in->cost; ! 1788: ! 1789: if (cost < best_alg->cost) ! 1790: { ! 1791: struct algorithm *x; ! 1792: x = alg_in; ! 1793: alg_in = best_alg; ! 1794: best_alg = x; ! 1795: best_alg->coeff[best_alg->ops] = m_exp_2; ! 1796: best_alg->op[best_alg->ops++] = alg_compound; ! 1797: best_alg->coeff[best_alg->ops] = 1; ! 1798: best_alg->op[best_alg->ops++] = alg_subtract; ! 1799: best_alg->cost = cost; ! 1800: } ! 1801: } ! 1802: } ! 1803: } ! 1804: ! 1805: /* Try load effective address instructions, i.e. do a*3, a*5, a*9. */ ! 1806: ! 1807: { ! 1808: int q; ! 1809: int w; ! 1810: ! 1811: q = t & -t; /* get out lsb */ ! 1812: w = (t - q) & -(t - q); /* get out next lsb */ ! 1813: ! 1814: if (w / q <= lea_max_mul) ! 1815: { ! 1816: cost = lea_cost + (q != 1 ? shift_cost : 0); ! 1817: ! 1818: *alg_in = synth_mult (t - q - w, add_cost, shift_cost, ! 1819: MIN (max_cost, best_alg->cost) - cost); ! 1820: ! 1821: if (alg_in->cost >= 0) ! 1822: { ! 1823: cost += alg_in->cost; ! 1824: ! 1825: /* Use <= to prefer this method to the factoring method ! 1826: when the cost appears the same, because this method ! 1827: uses fewer temporary registers. */ ! 1828: if (cost <= best_alg->cost) ! 1829: { ! 1830: struct algorithm *x; ! 1831: x = alg_in; ! 1832: alg_in = best_alg; ! 1833: best_alg = x; ! 1834: best_alg->coeff[best_alg->ops] = w; ! 1835: best_alg->op[best_alg->ops++] = alg_add; ! 1836: best_alg->coeff[best_alg->ops] = q; ! 1837: best_alg->op[best_alg->ops++] = alg_add; ! 1838: best_alg->cost = cost; ! 1839: } ! 1840: } ! 1841: } ! 1842: } ! 1843: ! 1844: /* Now, use the good old method to add or subtract at the leftmost ! 1845: 1-bit. */ ! 1846: ! 1847: { ! 1848: int q; ! 1849: int w; ! 1850: ! 1851: q = t & -t; /* get out lsb */ ! 1852: for (w = q; (w & t) != 0; w <<= 1) ! 1853: ; ! 1854: if ((w > q << 1) ! 1855: /* Reject the case where t has only two bits. ! 1856: Thus we prefer addition in that case. */ ! 1857: && !(t < w && w == q << 2)) ! 1858: { ! 1859: /* There are many bits in a row. Make 'em by subtraction. */ ! 1860: ! 1861: cost = add_cost; ! 1862: if (q != 1) ! 1863: cost += shift_cost; ! 1864: ! 1865: *alg_in = synth_mult (t + q, add_cost, shift_cost, ! 1866: MIN (max_cost, best_alg->cost) - cost); ! 1867: ! 1868: if (alg_in->cost >= 0) ! 1869: { ! 1870: cost += alg_in->cost; ! 1871: ! 1872: /* Use <= to prefer this method to the factoring method ! 1873: when the cost appears the same, because this method ! 1874: uses fewer temporary registers. */ ! 1875: if (cost <= best_alg->cost) ! 1876: { ! 1877: struct algorithm *x; ! 1878: x = alg_in; ! 1879: alg_in = best_alg; ! 1880: best_alg = x; ! 1881: best_alg->coeff[best_alg->ops] = q; ! 1882: best_alg->op[best_alg->ops++] = alg_subtract; ! 1883: best_alg->cost = cost; ! 1884: } ! 1885: } ! 1886: } ! 1887: else ! 1888: { ! 1889: /* There's only one bit at the left. Make it by addition. */ ! 1890: ! 1891: cost = add_cost; ! 1892: if (q != 1) ! 1893: cost += shift_cost; ! 1894: ! 1895: *alg_in = synth_mult (t - q, add_cost, shift_cost, ! 1896: MIN (max_cost, best_alg->cost) - cost); ! 1897: ! 1898: if (alg_in->cost >= 0) ! 1899: { ! 1900: cost += alg_in->cost; ! 1901: ! 1902: if (cost <= best_alg->cost) ! 1903: { ! 1904: struct algorithm *x; ! 1905: x = alg_in; ! 1906: alg_in = best_alg; ! 1907: best_alg = x; ! 1908: best_alg->coeff[best_alg->ops] = q; ! 1909: best_alg->op[best_alg->ops++] = alg_add; ! 1910: best_alg->cost = cost; ! 1911: } ! 1912: } ! 1913: } ! 1914: } ! 1915: ! 1916: if (best_alg->cost >= max_cost) ! 1917: best_alg->cost = -1; ! 1918: return *best_alg; ! 1919: } ! 1920: ! 1921: /* Perform a multiplication and return an rtx for the result. ! 1922: MODE is mode of value; OP0 and OP1 are what to multiply (rtx's); ! 1923: TARGET is a suggestion for where to store the result (an rtx). ! 1924: ! 1925: We check specially for a constant integer as OP1. ! 1926: If you want this check for OP0 as well, then before calling ! 1927: you should swap the two operands if OP0 would be constant. */ ! 1928: ! 1929: rtx ! 1930: expand_mult (mode, op0, op1, target, unsignedp) ! 1931: enum machine_mode mode; ! 1932: register rtx op0, op1, target; ! 1933: int unsignedp; ! 1934: { ! 1935: rtx const_op1 = op1; ! 1936: ! 1937: /* If we are multiplying in DImode, it may still be a win ! 1938: to try to work with shifts and adds. */ ! 1939: if (GET_CODE (op1) == CONST_DOUBLE ! 1940: && GET_MODE_CLASS (GET_MODE (op1)) == MODE_INT ! 1941: && HOST_BITS_PER_INT <= BITS_PER_WORD) ! 1942: { ! 1943: if ((CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) >= 0) ! 1944: || (CONST_DOUBLE_HIGH (op1) == -1 && CONST_DOUBLE_LOW (op1) < 0)) ! 1945: const_op1 = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1)); ! 1946: } ! 1947: ! 1948: if (GET_CODE (const_op1) == CONST_INT && ! mult_is_very_cheap && optimize) ! 1949: { ! 1950: struct algorithm alg; ! 1951: struct algorithm neg_alg; ! 1952: int negate = 0; ! 1953: int absval = INTVAL (op1); ! 1954: rtx last; ! 1955: ! 1956: /* Try to do the computation two ways: multiply by the negative of OP1 ! 1957: and then negate, or do the multiplication directly. The latter is ! 1958: usually faster for positive numbers and the former for negative ! 1959: numbers, but the opposite can be faster if the original value ! 1960: has a factor of 2**m +/- 1, while the negated value does not or ! 1961: vice versa. */ ! 1962: ! 1963: alg = synth_mult (absval, add_cost, shift_cost, mult_cost); ! 1964: neg_alg = synth_mult (- absval, add_cost, shift_cost, ! 1965: mult_cost - negate_cost); ! 1966: ! 1967: if (neg_alg.cost >= 0 && neg_alg.cost + negate_cost < alg.cost) ! 1968: alg = neg_alg, negate = 1, absval = - absval; ! 1969: ! 1970: if (alg.cost >= 0) ! 1971: { ! 1972: /* If we found something, it must be cheaper than multiply. ! 1973: So use it. */ ! 1974: int opno = 0; ! 1975: rtx accum, tem; ! 1976: int factors_seen = 0; ! 1977: ! 1978: op0 = protect_from_queue (op0, 0); ! 1979: ! 1980: /* Avoid referencing memory over and over. ! 1981: For speed, but also for correctness when mem is volatile. */ ! 1982: if (GET_CODE (op0) == MEM) ! 1983: op0 = force_reg (mode, op0); ! 1984: ! 1985: if (alg.ops == 0) ! 1986: accum = copy_to_mode_reg (mode, op0); ! 1987: else ! 1988: { ! 1989: /* 1 if this is the last in a series of adds and subtracts. */ ! 1990: int last = (1 == alg.ops || alg.op[1] == alg_compound); ! 1991: int log = floor_log2 (alg.coeff[0]); ! 1992: if (! factors_seen && ! last) ! 1993: log -= floor_log2 (alg.coeff[1]); ! 1994: ! 1995: if (alg.op[0] != alg_add) ! 1996: abort (); ! 1997: accum = expand_shift (LSHIFT_EXPR, mode, op0, ! 1998: build_int_2 (log, 0), ! 1999: 0, 0); ! 2000: } ! 2001: ! 2002: while (++opno < alg.ops) ! 2003: { ! 2004: int log = floor_log2 (alg.coeff[opno]); ! 2005: /* 1 if this is the last in a series of adds and subtracts. */ ! 2006: int last = (opno + 1 == alg.ops ! 2007: || alg.op[opno + 1] == alg_compound); ! 2008: ! 2009: /* If we have not yet seen any separate factors (alg_compound) ! 2010: then turn op0<<a1 + op0<<a2 + op0<<a3... into ! 2011: (op0<<(a1-a2) + op0)<<(a2-a3) + op0... */ ! 2012: switch (alg.op[opno]) ! 2013: { ! 2014: case alg_add: ! 2015: if (factors_seen) ! 2016: { ! 2017: tem = expand_shift (LSHIFT_EXPR, mode, op0, ! 2018: build_int_2 (log, 0), 0, 0); ! 2019: accum = force_operand (gen_rtx (PLUS, mode, accum, tem), ! 2020: accum); ! 2021: } ! 2022: else ! 2023: { ! 2024: if (! last) ! 2025: log -= floor_log2 (alg.coeff[opno + 1]); ! 2026: accum = force_operand (gen_rtx (PLUS, mode, accum, op0), ! 2027: accum); ! 2028: accum = expand_shift (LSHIFT_EXPR, mode, accum, ! 2029: build_int_2 (log, 0), accum, 0); ! 2030: } ! 2031: break; ! 2032: ! 2033: case alg_subtract: ! 2034: if (factors_seen) ! 2035: { ! 2036: tem = expand_shift (LSHIFT_EXPR, mode, op0, ! 2037: build_int_2 (log, 0), 0, 0); ! 2038: accum = force_operand (gen_rtx (MINUS, mode, accum, tem), ! 2039: accum); ! 2040: } ! 2041: else ! 2042: { ! 2043: if (! last) ! 2044: log -= floor_log2 (alg.coeff[opno + 1]); ! 2045: accum = force_operand (gen_rtx (MINUS, mode, accum, op0), ! 2046: accum); ! 2047: accum = expand_shift (LSHIFT_EXPR, mode, accum, ! 2048: build_int_2 (log, 0), accum, 0); ! 2049: } ! 2050: ! 2051: break; ! 2052: ! 2053: case alg_compound: ! 2054: factors_seen = 1; ! 2055: tem = expand_shift (LSHIFT_EXPR, mode, accum, ! 2056: build_int_2 (log, 0), 0, 0); ! 2057: ! 2058: log = floor_log2 (alg.coeff[opno + 1]); ! 2059: accum = expand_shift (LSHIFT_EXPR, mode, accum, ! 2060: build_int_2 (log, 0), 0, 0); ! 2061: opno++; ! 2062: if (alg.op[opno] == alg_add) ! 2063: accum = force_operand (gen_rtx (PLUS, mode, tem, accum), ! 2064: tem); ! 2065: else ! 2066: accum = force_operand (gen_rtx (MINUS, mode, tem, accum), ! 2067: tem); ! 2068: } ! 2069: } ! 2070: ! 2071: /* Write a REG_EQUAL note on the last insn so that we can cse ! 2072: multiplication sequences. We need not do this if we were ! 2073: multiplying by a power of two, since only one insn would have ! 2074: been generated. ! 2075: ! 2076: ??? We could also write REG_EQUAL notes on the last insn of ! 2077: each sequence that uses a single temporary, but it is not ! 2078: clear how to calculate the partial product so far. ! 2079: ! 2080: Torbjorn: Can you do this? */ ! 2081: ! 2082: if (exact_log2 (absval) < 0) ! 2083: { ! 2084: last = get_last_insn (); ! 2085: REG_NOTES (last) ! 2086: = gen_rtx (EXPR_LIST, REG_EQUAL, ! 2087: gen_rtx (MULT, mode, op0, ! 2088: negate ? gen_rtx (CONST_INT, ! 2089: VOIDmode, absval) ! 2090: : op1), ! 2091: REG_NOTES (last)); ! 2092: } ! 2093: ! 2094: return (negate ? expand_unop (mode, neg_optab, accum, target, 0) ! 2095: : accum); ! 2096: } ! 2097: } ! 2098: ! 2099: /* This used to use umul_optab if unsigned, ! 2100: but I think that for non-widening multiply there is no difference ! 2101: between signed and unsigned. */ ! 2102: op0 = expand_binop (mode, smul_optab, ! 2103: op0, op1, target, unsignedp, OPTAB_LIB_WIDEN); ! 2104: if (op0 == 0) ! 2105: abort (); ! 2106: return op0; ! 2107: } ! 2108: ! 2109: /* Emit the code to divide OP0 by OP1, putting the result in TARGET ! 2110: if that is convenient, and returning where the result is. ! 2111: You may request either the quotient or the remainder as the result; ! 2112: specify REM_FLAG nonzero to get the remainder. ! 2113: ! 2114: CODE is the expression code for which kind of division this is; ! 2115: it controls how rounding is done. MODE is the machine mode to use. ! 2116: UNSIGNEDP nonzero means do unsigned division. */ ! 2117: ! 2118: /* ??? For CEIL_MOD_EXPR, can compute incorrect remainder with ANDI ! 2119: and then correct it by or'ing in missing high bits ! 2120: if result of ANDI is nonzero. ! 2121: For ROUND_MOD_EXPR, can use ANDI and then sign-extend the result. ! 2122: This could optimize to a bfexts instruction. ! 2123: But C doesn't use these operations, so their optimizations are ! 2124: left for later. */ ! 2125: ! 2126: rtx ! 2127: expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp) ! 2128: int rem_flag; ! 2129: enum tree_code code; ! 2130: enum machine_mode mode; ! 2131: register rtx op0, op1, target; ! 2132: int unsignedp; ! 2133: { ! 2134: register rtx result = 0; ! 2135: enum machine_mode compute_mode; ! 2136: int log = -1; ! 2137: int can_clobber_op0; ! 2138: int mod_insn_no_good = 0; ! 2139: rtx adjusted_op0 = op0; ! 2140: optab optab1, optab2; ! 2141: ! 2142: /* Don't use the function value register as a target ! 2143: since we have to read it as well as write it, ! 2144: and function-inlining gets confused by this. */ ! 2145: if (target && REG_P (target) && REG_FUNCTION_VALUE_P (target)) ! 2146: target = 0; ! 2147: ! 2148: /* Don't clobber an operand while doing a multi-step calculation. */ ! 2149: if (target) ! 2150: if ((rem_flag && (reg_mentioned_p (target, op0) ! 2151: || (GET_CODE (op0) == MEM && GET_CODE (target) == MEM))) ! 2152: || reg_mentioned_p (target, op1) ! 2153: || (GET_CODE (op1) == MEM && GET_CODE (target) == MEM)) ! 2154: target = 0; ! 2155: ! 2156: can_clobber_op0 = (GET_CODE (op0) == REG && op0 == target); ! 2157: ! 2158: if (GET_CODE (op1) == CONST_INT) ! 2159: log = exact_log2 (INTVAL (op1)); ! 2160: ! 2161: /* If log is >= 0, we are dividing by 2**log, and will do it by shifting, ! 2162: which is really floor-division. Otherwise we will really do a divide, ! 2163: and we assume that is trunc-division. ! 2164: ! 2165: We must correct the dividend by adding or subtracting something ! 2166: based on the divisor, in order to do the kind of rounding specified ! 2167: by CODE. The correction depends on what kind of rounding is actually ! 2168: available, and that depends on whether we will shift or divide. ! 2169: ! 2170: In many of these cases it is possible to perform the operation by a ! 2171: clever series of logical operations (shifts and/or exclusive-ors). ! 2172: Although avoiding the jump has the advantage that it extends the basic ! 2173: block and allows further optimization, the branch-free code is normally ! 2174: at least one instruction longer in the (most common) case where the ! 2175: dividend is non-negative. Performance measurements of the two ! 2176: alternatives show that the branch-free code is slightly faster on the ! 2177: IBM ROMP but slower on CISC processors (significantly slower on the ! 2178: VAX). Accordingly, the jump code has been retained. ! 2179: ! 2180: On machines where the jump code is slower, the cost of a DIV or MOD ! 2181: operation can be set small (less than twice that of an addition); in ! 2182: that case, we pretend that we don't have a power of two and perform ! 2183: a normal division or modulus operation. */ ! 2184: ! 2185: if ((code == TRUNC_MOD_EXPR || code == TRUNC_DIV_EXPR) ! 2186: && ! unsignedp ! 2187: && (rem_flag ? smod_pow2_cheap : sdiv_pow2_cheap)) ! 2188: log = -1; ! 2189: ! 2190: /* Get the mode in which to perform this computation. Normally it will ! 2191: be MODE, but sometimes we can't do the desired operation in MODE. ! 2192: If so, pick a wider mode in which we can do the operation. Convert ! 2193: to that mode at the start to avoid repeated conversions. ! 2194: ! 2195: First see what operations we need. These depend on the expression ! 2196: we are evaluating. (We assume that divxx3 insns exist under the ! 2197: same conditions that modxx3 insns and that these insns don't normally ! 2198: fail. If these assumptions are not correct, we may generate less ! 2199: efficient code in some cases.) ! 2200: ! 2201: Then see if we find a mode in which we can open-code that operation ! 2202: (either a division, modulus, or shift). Finally, check for the smallest ! 2203: mode for which we can do the operation with a library call. */ ! 2204: ! 2205: optab1 = (log >= 0 ? (unsignedp ? lshr_optab : ashr_optab) ! 2206: : (unsignedp ? udiv_optab : sdiv_optab)); ! 2207: optab2 = (log >= 0 ? optab1 : (unsignedp ? udivmod_optab : sdivmod_optab)); ! 2208: ! 2209: for (compute_mode = mode; compute_mode != VOIDmode; ! 2210: compute_mode = GET_MODE_WIDER_MODE (compute_mode)) ! 2211: if (optab1->handlers[(int) compute_mode].insn_code != CODE_FOR_nothing ! 2212: || optab2->handlers[(int) compute_mode].insn_code != CODE_FOR_nothing) ! 2213: break; ! 2214: ! 2215: if (compute_mode == VOIDmode) ! 2216: for (compute_mode = mode; compute_mode != VOIDmode; ! 2217: compute_mode = GET_MODE_WIDER_MODE (compute_mode)) ! 2218: if (optab1->handlers[(int) compute_mode].libfunc ! 2219: || optab2->handlers[(int) compute_mode].libfunc) ! 2220: break; ! 2221: ! 2222: /* If we still couldn't find a mode, use MODE; we'll probably abort in ! 2223: expand_binop. */ ! 2224: if (compute_mode == VOIDmode) ! 2225: compute_mode = mode; ! 2226: ! 2227: /* Now convert to the best mode to use. Show we made a copy of OP0 ! 2228: and hence we can clobber it (we cannot use a SUBREG to widen ! 2229: something. */ ! 2230: if (compute_mode != mode) ! 2231: { ! 2232: adjusted_op0 = op0 = convert_to_mode (compute_mode, op0, unsignedp); ! 2233: can_clobber_op0 = 1; ! 2234: op1 = convert_to_mode (compute_mode, op1, unsignedp); ! 2235: } ! 2236: ! 2237: if (target == 0 || GET_MODE (target) != compute_mode) ! 2238: target = gen_reg_rtx (compute_mode); ! 2239: ! 2240: switch (code) ! 2241: { ! 2242: case TRUNC_MOD_EXPR: ! 2243: case TRUNC_DIV_EXPR: ! 2244: if (log >= 0 && ! unsignedp) ! 2245: { ! 2246: rtx label = gen_label_rtx (); ! 2247: if (! can_clobber_op0) ! 2248: { ! 2249: adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target); ! 2250: /* Copy op0 to a reg, since emit_cmp_insn will call emit_queue ! 2251: which will screw up mem refs for autoincrements. */ ! 2252: op0 = force_reg (compute_mode, op0); ! 2253: } ! 2254: emit_cmp_insn (adjusted_op0, const0_rtx, GE, 0, compute_mode, 0, 0); ! 2255: emit_jump_insn (gen_bge (label)); ! 2256: expand_inc (adjusted_op0, plus_constant (op1, -1)); ! 2257: emit_label (label); ! 2258: mod_insn_no_good = 1; ! 2259: } ! 2260: break; ! 2261: ! 2262: case FLOOR_DIV_EXPR: ! 2263: case FLOOR_MOD_EXPR: ! 2264: if (log < 0 && ! unsignedp) ! 2265: { ! 2266: rtx label = gen_label_rtx (); ! 2267: if (! can_clobber_op0) ! 2268: { ! 2269: adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target); ! 2270: /* Copy op0 to a reg, since emit_cmp_insn will call emit_queue ! 2271: which will screw up mem refs for autoincrements. */ ! 2272: op0 = force_reg (compute_mode, op0); ! 2273: } ! 2274: emit_cmp_insn (adjusted_op0, const0_rtx, GE, 0, compute_mode, 0, 0); ! 2275: emit_jump_insn (gen_bge (label)); ! 2276: expand_dec (adjusted_op0, op1); ! 2277: expand_inc (adjusted_op0, const1_rtx); ! 2278: emit_label (label); ! 2279: mod_insn_no_good = 1; ! 2280: } ! 2281: break; ! 2282: ! 2283: case CEIL_DIV_EXPR: ! 2284: case CEIL_MOD_EXPR: ! 2285: if (! can_clobber_op0) ! 2286: { ! 2287: adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target); ! 2288: /* Copy op0 to a reg, since emit_cmp_insn will call emit_queue ! 2289: which will screw up mem refs for autoincrements. */ ! 2290: op0 = force_reg (compute_mode, op0); ! 2291: } ! 2292: if (log < 0) ! 2293: { ! 2294: rtx label = 0; ! 2295: if (! unsignedp) ! 2296: { ! 2297: label = gen_label_rtx (); ! 2298: emit_cmp_insn (adjusted_op0, const0_rtx, LE, 0, compute_mode, 0, 0); ! 2299: emit_jump_insn (gen_ble (label)); ! 2300: } ! 2301: expand_inc (adjusted_op0, op1); ! 2302: expand_dec (adjusted_op0, const1_rtx); ! 2303: if (! unsignedp) ! 2304: emit_label (label); ! 2305: } ! 2306: else ! 2307: { ! 2308: adjusted_op0 = expand_binop (compute_mode, add_optab, ! 2309: adjusted_op0, plus_constant (op1, -1), ! 2310: 0, 0, OPTAB_LIB_WIDEN); ! 2311: } ! 2312: mod_insn_no_good = 1; ! 2313: break; ! 2314: ! 2315: case ROUND_DIV_EXPR: ! 2316: case ROUND_MOD_EXPR: ! 2317: if (! can_clobber_op0) ! 2318: { ! 2319: adjusted_op0 = copy_to_suggested_reg (adjusted_op0, target); ! 2320: /* Copy op0 to a reg, since emit_cmp_insn will call emit_queue ! 2321: which will screw up mem refs for autoincrements. */ ! 2322: op0 = force_reg (compute_mode, op0); ! 2323: } ! 2324: if (log < 0) ! 2325: { ! 2326: op1 = expand_shift (RSHIFT_EXPR, compute_mode, op1, ! 2327: integer_one_node, 0, 0); ! 2328: if (! unsignedp) ! 2329: { ! 2330: rtx label = gen_label_rtx (); ! 2331: emit_cmp_insn (adjusted_op0, const0_rtx, GE, 0, compute_mode, 0, 0); ! 2332: emit_jump_insn (gen_bge (label)); ! 2333: expand_unop (compute_mode, neg_optab, op1, op1, 0); ! 2334: emit_label (label); ! 2335: } ! 2336: expand_inc (adjusted_op0, op1); ! 2337: } ! 2338: else ! 2339: { ! 2340: op1 = gen_rtx (CONST_INT, VOIDmode, (1 << log) / 2); ! 2341: expand_inc (adjusted_op0, op1); ! 2342: } ! 2343: mod_insn_no_good = 1; ! 2344: break; ! 2345: } ! 2346: ! 2347: if (rem_flag && !mod_insn_no_good) ! 2348: { ! 2349: /* Try to produce the remainder directly */ ! 2350: if (log >= 0) ! 2351: result = expand_binop (compute_mode, and_optab, adjusted_op0, ! 2352: gen_rtx (CONST_INT, VOIDmode, ! 2353: (1 << log) - 1), ! 2354: target, 1, OPTAB_LIB_WIDEN); ! 2355: else ! 2356: { ! 2357: /* See if we can do remainder without a library call. */ ! 2358: result = sign_expand_binop (mode, umod_optab, smod_optab, ! 2359: adjusted_op0, op1, target, ! 2360: unsignedp, OPTAB_WIDEN); ! 2361: if (result == 0) ! 2362: { ! 2363: /* No luck there. Can we do remainder and divide at once ! 2364: without a library call? */ ! 2365: result = gen_reg_rtx (compute_mode); ! 2366: if (! expand_twoval_binop (unsignedp ! 2367: ? udivmod_optab : sdivmod_optab, ! 2368: adjusted_op0, op1, ! 2369: 0, result, unsignedp)) ! 2370: result = 0; ! 2371: } ! 2372: } ! 2373: } ! 2374: ! 2375: if (result) ! 2376: return gen_lowpart (mode, result); ! 2377: ! 2378: /* Produce the quotient. */ ! 2379: if (log >= 0) ! 2380: result = expand_shift (RSHIFT_EXPR, compute_mode, adjusted_op0, ! 2381: build_int_2 (log, 0), target, unsignedp); ! 2382: else if (rem_flag && !mod_insn_no_good) ! 2383: /* If producing quotient in order to subtract for remainder, ! 2384: and a remainder subroutine would be ok, ! 2385: don't use a divide subroutine. */ ! 2386: result = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, ! 2387: adjusted_op0, op1, 0, unsignedp, OPTAB_WIDEN); ! 2388: else ! 2389: { ! 2390: /* Try a quotient insn, but not a library call. */ ! 2391: result = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, ! 2392: adjusted_op0, op1, rem_flag ? 0 : target, ! 2393: unsignedp, OPTAB_WIDEN); ! 2394: if (result == 0) ! 2395: { ! 2396: /* No luck there. Try a quotient-and-remainder insn, ! 2397: keeping the quotient alone. */ ! 2398: result = gen_reg_rtx (mode); ! 2399: if (! expand_twoval_binop (unsignedp ? udivmod_optab : sdivmod_optab, ! 2400: adjusted_op0, op1, ! 2401: result, 0, unsignedp)) ! 2402: result = 0; ! 2403: } ! 2404: ! 2405: /* If still no luck, use a library call. */ ! 2406: if (result == 0) ! 2407: result = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, ! 2408: adjusted_op0, op1, rem_flag ? 0 : target, ! 2409: unsignedp, OPTAB_LIB_WIDEN); ! 2410: } ! 2411: ! 2412: /* If we really want the remainder, get it by subtraction. */ ! 2413: if (rem_flag) ! 2414: { ! 2415: if (result == 0) ! 2416: /* No divide instruction either. Use library for remainder. */ ! 2417: result = sign_expand_binop (compute_mode, umod_optab, smod_optab, ! 2418: op0, op1, target, ! 2419: unsignedp, OPTAB_LIB_WIDEN); ! 2420: else ! 2421: { ! 2422: /* We divided. Now finish doing X - Y * (X / Y). */ ! 2423: result = expand_mult (compute_mode, result, op1, target, unsignedp); ! 2424: if (! result) abort (); ! 2425: result = expand_binop (compute_mode, sub_optab, op0, ! 2426: result, target, unsignedp, OPTAB_LIB_WIDEN); ! 2427: } ! 2428: } ! 2429: ! 2430: if (result == 0) ! 2431: abort (); ! 2432: ! 2433: return gen_lowpart (mode, result); ! 2434: } ! 2435: ! 2436: /* Return a tree node with data type TYPE, describing the value of X. ! 2437: Usually this is an RTL_EXPR, if there is no obvious better choice. ! 2438: X may be an expression, however we only support those expressions ! 2439: generated by loop.c. */ ! 2440: ! 2441: tree ! 2442: make_tree (type, x) ! 2443: tree type; ! 2444: rtx x; ! 2445: { ! 2446: tree t; ! 2447: ! 2448: switch (GET_CODE (x)) ! 2449: { ! 2450: case CONST_INT: ! 2451: t = build_int_2 (INTVAL (x), ! 2452: ! TREE_UNSIGNED (type) && INTVAL (x) >= 0 ? 0 : -1); ! 2453: TREE_TYPE (t) = type; ! 2454: return t; ! 2455: ! 2456: case CONST_DOUBLE: ! 2457: if (GET_MODE (x) == VOIDmode) ! 2458: { ! 2459: t = build_int_2 (CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x)); ! 2460: TREE_TYPE (t) = type; ! 2461: } ! 2462: else ! 2463: { ! 2464: REAL_VALUE_TYPE d; ! 2465: ! 2466: REAL_VALUE_FROM_CONST_DOUBLE (d, x); ! 2467: t = build_real (type, d); ! 2468: } ! 2469: ! 2470: return t; ! 2471: ! 2472: case PLUS: ! 2473: return fold (build (PLUS_EXPR, type, make_tree (type, XEXP (x, 0)), ! 2474: make_tree (type, XEXP (x, 1)))); ! 2475: ! 2476: case MINUS: ! 2477: return fold (build (MINUS_EXPR, type, make_tree (type, XEXP (x, 0)), ! 2478: make_tree (type, XEXP (x, 1)))); ! 2479: ! 2480: case NEG: ! 2481: return fold (build1 (NEGATE_EXPR, type, make_tree (type, XEXP (x, 0)))); ! 2482: ! 2483: case MULT: ! 2484: return fold (build (MULT_EXPR, type, make_tree (type, XEXP (x, 0)), ! 2485: make_tree (type, XEXP (x, 1)))); ! 2486: ! 2487: case ASHIFT: ! 2488: return fold (build (LSHIFT_EXPR, type, make_tree (type, XEXP (x, 0)), ! 2489: make_tree (type, XEXP (x, 1)))); ! 2490: ! 2491: case LSHIFTRT: ! 2492: return fold (convert (type, ! 2493: build (RSHIFT_EXPR, unsigned_type (type), ! 2494: make_tree (unsigned_type (type), ! 2495: XEXP (x, 0)), ! 2496: make_tree (type, XEXP (x, 1))))); ! 2497: ! 2498: case ASHIFTRT: ! 2499: return fold (convert (type, ! 2500: build (RSHIFT_EXPR, signed_type (type), ! 2501: make_tree (signed_type (type), XEXP (x, 0)), ! 2502: make_tree (type, XEXP (x, 1))))); ! 2503: ! 2504: case DIV: ! 2505: if (TREE_CODE (type) != REAL_TYPE) ! 2506: t = signed_type (type); ! 2507: else ! 2508: t = type; ! 2509: ! 2510: return fold (convert (type, ! 2511: build (TRUNC_DIV_EXPR, t, ! 2512: make_tree (t, XEXP (x, 0)), ! 2513: make_tree (t, XEXP (x, 1))))); ! 2514: case UDIV: ! 2515: t = unsigned_type (type); ! 2516: return fold (convert (type, ! 2517: build (TRUNC_DIV_EXPR, t, ! 2518: make_tree (t, XEXP (x, 0)), ! 2519: make_tree (t, XEXP (x, 1))))); ! 2520: default: ! 2521: t = make_node (RTL_EXPR); ! 2522: TREE_TYPE (t) = type; ! 2523: RTL_EXPR_RTL (t) = x; ! 2524: /* There are no insns to be output ! 2525: when this rtl_expr is used. */ ! 2526: RTL_EXPR_SEQUENCE (t) = 0; ! 2527: return t; ! 2528: } ! 2529: } ! 2530: ! 2531: /* Return an rtx representing the value of X * MULT + ADD. ! 2532: TARGET is a suggestion for where to store the result (an rtx). ! 2533: MODE is the machine mode for the computation. ! 2534: X and MULT must have mode MODE. ADD may have a different mode. ! 2535: So can X (defaults to same as MODE). ! 2536: UNSIGNEDP is non-zero to do unsigned multiplication. ! 2537: This may emit insns. */ ! 2538: ! 2539: rtx ! 2540: expand_mult_add (x, target, mult, add, mode, unsignedp) ! 2541: rtx x, target, mult, add; ! 2542: enum machine_mode mode; ! 2543: int unsignedp; ! 2544: { ! 2545: tree type = type_for_mode (mode, unsignedp); ! 2546: tree add_type = (GET_MODE (add) == VOIDmode ! 2547: ? type : type_for_mode (GET_MODE (add))); ! 2548: tree result = fold (build (PLUS_EXPR, type, ! 2549: fold (build (MULT_EXPR, type, ! 2550: make_tree (type, x), ! 2551: make_tree (type, mult))), ! 2552: make_tree (add_type, add))); ! 2553: ! 2554: return expand_expr (result, target, VOIDmode, 0); ! 2555: } ! 2556: ! 2557: /* Compute the logical-and of OP0 and OP1, storing it in TARGET ! 2558: and returning TARGET. ! 2559: ! 2560: If TARGET is 0, a pseudo-register or constant is returned. */ ! 2561: ! 2562: rtx ! 2563: expand_and (op0, op1, target) ! 2564: rtx op0, op1, target; ! 2565: { ! 2566: enum machine_mode mode = VOIDmode; ! 2567: rtx tem; ! 2568: ! 2569: if (GET_MODE (op0) != VOIDmode) ! 2570: mode = GET_MODE (op0); ! 2571: else if (GET_MODE (op1) != VOIDmode) ! 2572: mode = GET_MODE (op1); ! 2573: ! 2574: if (mode != VOIDmode) ! 2575: tem = expand_binop (mode, and_optab, op0, op1, target, 0, OPTAB_LIB_WIDEN); ! 2576: else if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT) ! 2577: tem = gen_rtx (CONST_INT, VOIDmode, INTVAL (op0) & INTVAL (op1)); ! 2578: else ! 2579: abort (); ! 2580: ! 2581: if (target == 0) ! 2582: target = tem; ! 2583: else if (tem != target) ! 2584: emit_move_insn (target, tem); ! 2585: return target; ! 2586: } ! 2587: ! 2588: /* Emit a store-flags instruction for comparison CODE on OP0 and OP1 ! 2589: and storing in TARGET. Normally return TARGET. ! 2590: Return 0 if that cannot be done. ! 2591: ! 2592: MODE is the mode to use for OP0 and OP1 should they be CONST_INTs. If ! 2593: it is VOIDmode, they cannot both be CONST_INT. ! 2594: ! 2595: UNSIGNEDP is for the case where we have to widen the operands ! 2596: to perform the operation. It says to use zero-extension. ! 2597: ! 2598: NORMALIZEP is 1 if we should convert the result to be either zero ! 2599: or one one. Normalize is -1 if we should convert the result to be ! 2600: either zero or -1. If NORMALIZEP is zero, the result will be left ! 2601: "raw" out of the scc insn. */ ! 2602: ! 2603: rtx ! 2604: emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep) ! 2605: rtx target; ! 2606: enum rtx_code code; ! 2607: rtx op0, op1; ! 2608: enum machine_mode mode; ! 2609: int unsignedp; ! 2610: int normalizep; ! 2611: { ! 2612: rtx subtarget; ! 2613: enum insn_code icode; ! 2614: enum machine_mode compare_mode; ! 2615: enum machine_mode target_mode = GET_MODE (target); ! 2616: rtx tem; ! 2617: rtx last = 0; ! 2618: rtx pattern, comparison; ! 2619: ! 2620: if (mode == VOIDmode) ! 2621: mode = GET_MODE (op0); ! 2622: ! 2623: /* For some comparisons with 1 and -1, we can convert this to ! 2624: comparisons with zero. This will often produce more opportunities for ! 2625: store-flag insns. */ ! 2626: ! 2627: switch (code) ! 2628: { ! 2629: case LT: ! 2630: if (op1 == const1_rtx) ! 2631: op1 = const0_rtx, code = LE; ! 2632: break; ! 2633: case LE: ! 2634: if (op1 == constm1_rtx) ! 2635: op1 = const0_rtx, code = LT; ! 2636: break; ! 2637: case GE: ! 2638: if (op1 == const1_rtx) ! 2639: op1 = const0_rtx, code = GT; ! 2640: break; ! 2641: case GT: ! 2642: if (op1 == constm1_rtx) ! 2643: op1 = const0_rtx, code = GE; ! 2644: break; ! 2645: case GEU: ! 2646: if (op1 == const1_rtx) ! 2647: op1 = const0_rtx, code = NE; ! 2648: break; ! 2649: case LTU: ! 2650: if (op1 == const1_rtx) ! 2651: op1 = const0_rtx, code = EQ; ! 2652: break; ! 2653: } ! 2654: ! 2655: /* From now on, we won't change CODE, so set ICODE now. */ ! 2656: icode = setcc_gen_code[(int) code]; ! 2657: ! 2658: /* If this is A < 0 or A >= 0, we can do this by taking the ones ! 2659: complement of A (for GE) and shifting the sign bit to the low bit. */ ! 2660: if (op1 == const0_rtx && (code == LT || code == GE) ! 2661: && GET_MODE_CLASS (mode) == MODE_INT ! 2662: && (normalizep || STORE_FLAG_VALUE == 1 ! 2663: || (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT ! 2664: && STORE_FLAG_VALUE == 1 << (GET_MODE_BITSIZE (mode) - 1)))) ! 2665: { ! 2666: rtx subtarget = target; ! 2667: ! 2668: /* If the result is to be wider than OP0, it is best to convert it ! 2669: first. If it is to be narrower, it is *incorrect* to convert it ! 2670: first. */ ! 2671: if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (mode)) ! 2672: { ! 2673: op0 = convert_to_mode (target_mode, op0, 0); ! 2674: mode = target_mode; ! 2675: } ! 2676: ! 2677: if (target_mode != mode) ! 2678: subtarget = 0; ! 2679: ! 2680: if (code == GE) ! 2681: op0 = expand_unop (mode, one_cmpl_optab, op0, subtarget, 0); ! 2682: ! 2683: if (normalizep || STORE_FLAG_VALUE == 1) ! 2684: /* If we are supposed to produce a 0/1 value, we want to do ! 2685: a logical shift from the sign bit to the low-order bit; for ! 2686: a -1/0 value, we do an arithmetic shift. */ ! 2687: op0 = expand_shift (RSHIFT_EXPR, mode, op0, ! 2688: size_int (GET_MODE_BITSIZE (mode) - 1), ! 2689: subtarget, normalizep != -1); ! 2690: ! 2691: if (mode != target_mode) ! 2692: op0 = convert_to_mode (target_mode, op0, 0); ! 2693: ! 2694: return op0; ! 2695: } ! 2696: ! 2697: if (icode != CODE_FOR_nothing) ! 2698: { ! 2699: /* We think we may be able to do this with a scc insn. Emit the ! 2700: comparison and then the scc insn. ! 2701: ! 2702: compare_from_rtx may call emit_queue, which would be deleted below ! 2703: if the scc insn fails. So call it ourselves before setting LAST. */ ! 2704: ! 2705: emit_queue (); ! 2706: last = get_last_insn (); ! 2707: ! 2708: comparison = compare_from_rtx (op0, op1, code, unsignedp, mode, 0, 0); ! 2709: if (GET_CODE (comparison) == CONST_INT) ! 2710: return (comparison == const0_rtx ? const0_rtx ! 2711: : normalizep == 1 ? const1_rtx ! 2712: : normalizep == -1 ? constm1_rtx ! 2713: : const_true_rtx); ! 2714: ! 2715: /* Get a reference to the target in the proper mode for this insn. */ ! 2716: compare_mode = insn_operand_mode[(int) icode][0]; ! 2717: subtarget = target; ! 2718: if (preserve_subexpressions_p () ! 2719: || ! (*insn_operand_predicate[(int) icode][0]) (subtarget, compare_mode)) ! 2720: subtarget = gen_reg_rtx (compare_mode); ! 2721: ! 2722: pattern = GEN_FCN (icode) (subtarget); ! 2723: if (pattern) ! 2724: { ! 2725: emit_insn (pattern); ! 2726: ! 2727: /* If we are converting to a wider mode, first convert to ! 2728: TARGET_MODE, then normalize. This produces better combining ! 2729: opportunities on machines that have a SIGN_EXTRACT when we are ! 2730: testing a single bit. This mostly benefits the 68k. ! 2731: ! 2732: If STORE_FLAG_VALUE does not have the sign bit set when ! 2733: interpreted in COMPARE_MODE, we can do this conversion as ! 2734: unsigned, which is usually more efficient. */ ! 2735: if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (compare_mode)) ! 2736: { ! 2737: convert_move (target, subtarget, ! 2738: (GET_MODE_BITSIZE (compare_mode) ! 2739: <= HOST_BITS_PER_INT) ! 2740: && 0 == (STORE_FLAG_VALUE ! 2741: & (1 << (GET_MODE_BITSIZE (compare_mode) -1)))); ! 2742: op0 = target; ! 2743: compare_mode = target_mode; ! 2744: } ! 2745: else ! 2746: op0 = subtarget; ! 2747: ! 2748: /* Now normalize to the proper value in COMPARE_MODE. Sometimes ! 2749: we don't have to do anything. */ ! 2750: if (normalizep == 0 || normalizep == STORE_FLAG_VALUE) ! 2751: ; ! 2752: else if (normalizep == - STORE_FLAG_VALUE) ! 2753: op0 = expand_unop (compare_mode, neg_optab, op0, subtarget, 0); ! 2754: ! 2755: /* We don't want to use STORE_FLAG_VALUE < 0 below since this ! 2756: makes it hard to use a value of just the sign bit due to ! 2757: ANSI integer constant typing rules. */ ! 2758: else if (GET_MODE_BITSIZE (compare_mode) <= HOST_BITS_PER_INT ! 2759: && (STORE_FLAG_VALUE ! 2760: & (1 << (GET_MODE_BITSIZE (compare_mode) - 1)))) ! 2761: op0 = expand_shift (RSHIFT_EXPR, compare_mode, op0, ! 2762: size_int (GET_MODE_BITSIZE (compare_mode) - 1), ! 2763: subtarget, normalizep == 1); ! 2764: else if (STORE_FLAG_VALUE & 1) ! 2765: { ! 2766: op0 = expand_and (op0, const1_rtx, subtarget); ! 2767: if (normalizep == -1) ! 2768: op0 = expand_unop (compare_mode, neg_optab, op0, op0, 0); ! 2769: } ! 2770: else ! 2771: abort (); ! 2772: ! 2773: /* If we were converting to a smaller mode, do the ! 2774: conversion now. */ ! 2775: if (target_mode != compare_mode) ! 2776: { ! 2777: convert_move (target, op0); ! 2778: return target; ! 2779: } ! 2780: else ! 2781: return op0; ! 2782: } ! 2783: } ! 2784: ! 2785: if (last) ! 2786: delete_insns_since (last); ! 2787: ! 2788: subtarget = target_mode == mode ? target : 0; ! 2789: ! 2790: /* If we reached here, we can't do this with a scc insn. However, there ! 2791: are some comparisons that can be done directly. For example, if ! 2792: this is an equality comparison of integers, we can try to exclusive-or ! 2793: (or subtract) the two operands and use a recursive call to try the ! 2794: comparison with zero. Don't do any of these cases if branches are ! 2795: very cheap. */ ! 2796: ! 2797: if (BRANCH_COST >= 0 ! 2798: && GET_MODE_CLASS (mode) == MODE_INT && (code == EQ || code == NE) ! 2799: && op1 != const0_rtx) ! 2800: { ! 2801: tem = expand_binop (mode, xor_optab, op0, op1, subtarget, 1, ! 2802: OPTAB_WIDEN); ! 2803: ! 2804: if (tem == 0) ! 2805: tem = expand_binop (mode, sub_optab, op0, op1, subtarget, 1, ! 2806: OPTAB_WIDEN); ! 2807: if (tem != 0) ! 2808: tem = emit_store_flag (target, code, tem, const0_rtx, ! 2809: mode, unsignedp, normalizep); ! 2810: if (tem == 0) ! 2811: delete_insns_since (last); ! 2812: return tem; ! 2813: } ! 2814: ! 2815: /* Some other cases we can do are EQ, NE, LE, and GT comparisons with ! 2816: the constant zero. Reject all other comparisons at this point. Only ! 2817: do LE and GT if branches are expensive since they are expensive on ! 2818: 2-operand machines. */ ! 2819: ! 2820: if (BRANCH_COST == 0 ! 2821: || GET_MODE_CLASS (mode) != MODE_INT || op1 != const0_rtx ! 2822: || (code != EQ && code != NE ! 2823: && (BRANCH_COST <= 1 || (code != LE && code != GT)))) ! 2824: return 0; ! 2825: ! 2826: /* See what we need to return. We can only return a 1, -1, or the ! 2827: sign bit. */ ! 2828: ! 2829: if (normalizep == 0) ! 2830: { ! 2831: if (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1) ! 2832: normalizep = STORE_FLAG_VALUE; ! 2833: ! 2834: else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT ! 2835: && STORE_FLAG_VALUE == 1 << (GET_MODE_BITSIZE (mode) - 1)) ! 2836: ; ! 2837: else ! 2838: return 0; ! 2839: } ! 2840: ! 2841: /* Try to put the result of the comparison in the sign bit. Assume we can't ! 2842: do the necessary operation below. */ ! 2843: ! 2844: tem = 0; ! 2845: ! 2846: /* To see if A <= 0, compute (A | (A - 1)). A <= 0 iff that result has ! 2847: the sign bit set. */ ! 2848: ! 2849: if (code == LE) ! 2850: { ! 2851: /* This is destructive, so SUBTARGET can't be OP0. */ ! 2852: if (rtx_equal_p (subtarget, op0)) ! 2853: subtarget = 0; ! 2854: ! 2855: tem = expand_binop (mode, sub_optab, op0, const1_rtx, subtarget, 0, ! 2856: OPTAB_WIDEN); ! 2857: if (tem) ! 2858: tem = expand_binop (mode, ior_optab, op0, tem, subtarget, 0, ! 2859: OPTAB_WIDEN); ! 2860: } ! 2861: ! 2862: /* To see if A > 0, compute (((signed) A) << BITS) - A, where BITS is the ! 2863: number of bits in the mode of OP0, minus one. */ ! 2864: ! 2865: if (code == GT) ! 2866: { ! 2867: if (rtx_equal_p (subtarget, op0)) ! 2868: subtarget = 0; ! 2869: ! 2870: tem = expand_shift (RSHIFT_EXPR, mode, op0, ! 2871: size_int (GET_MODE_BITSIZE (mode) - 1), ! 2872: subtarget, 0); ! 2873: tem = expand_binop (mode, sub_optab, tem, op0, subtarget, 0, ! 2874: OPTAB_WIDEN); ! 2875: } ! 2876: ! 2877: if (code == EQ || code == NE) ! 2878: { ! 2879: /* For EQ or NE, one way to do the comparison is to apply an operation ! 2880: that converts the operand into a positive number if it is non-zero ! 2881: or zero if it was originally zero. Then, for EQ, we subtract 1 and ! 2882: for NE we negate. This puts the result in the sign bit. Then we ! 2883: normalize with a shift, if needed. ! 2884: ! 2885: Two operations that can do the above actions are ABS and FFS, so try ! 2886: them. If that doesn't work, and MODE is smaller than a full word, ! 2887: we can use zero-extention to the wider mode (an unsigned conversion) ! 2888: as the operation. */ ! 2889: ! 2890: if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 2891: tem = expand_unop (mode, abs_optab, op0, subtarget, 1); ! 2892: else if (ffs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 2893: tem = expand_unop (mode, ffs_optab, op0, subtarget, 1); ! 2894: else if (GET_MODE_SIZE (mode) < UNITS_PER_WORD) ! 2895: { ! 2896: mode = word_mode; ! 2897: tem = convert_to_mode (mode, op0, 1); ! 2898: } ! 2899: ! 2900: if (tem != 0) ! 2901: { ! 2902: if (code == EQ) ! 2903: tem = expand_binop (mode, sub_optab, tem, const1_rtx, subtarget, ! 2904: 0, OPTAB_WIDEN); ! 2905: else ! 2906: tem = expand_unop (mode, neg_optab, tem, subtarget, 0); ! 2907: } ! 2908: ! 2909: /* If we couldn't do it that way, for NE we can "or" the two's complement ! 2910: of the value with itself. For EQ, we take the one's complement of ! 2911: that "or", which is an extra insn, so we only handle EQ if branches ! 2912: are expensive. */ ! 2913: ! 2914: if (tem == 0 && (code == NE || BRANCH_COST > 1)) ! 2915: { ! 2916: tem = expand_unop (mode, neg_optab, op0, subtarget, 0); ! 2917: tem = expand_binop (mode, ior_optab, tem, op0, subtarget, 0, ! 2918: OPTAB_WIDEN); ! 2919: ! 2920: if (tem && code == EQ) ! 2921: tem = expand_unop (mode, one_cmpl_optab, tem, subtarget, 0); ! 2922: } ! 2923: } ! 2924: ! 2925: if (tem && normalizep) ! 2926: tem = expand_shift (RSHIFT_EXPR, mode, tem, ! 2927: size_int (GET_MODE_BITSIZE (mode) - 1), ! 2928: tem, normalizep == 1); ! 2929: ! 2930: if (tem && GET_MODE (tem) != target_mode) ! 2931: { ! 2932: convert_move (target, tem, 0); ! 2933: tem = target; ! 2934: } ! 2935: ! 2936: if (tem == 0) ! 2937: delete_insns_since (last); ! 2938: ! 2939: return tem; ! 2940: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.