|
|
1.1 ! root 1: /* Expand the basic unary and binary arithmetic operations, for GNU compiler. ! 2: Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: #include "config.h" ! 22: #include "rtl.h" ! 23: #include "tree.h" ! 24: #include "flags.h" ! 25: #include "insn-flags.h" ! 26: #include "insn-codes.h" ! 27: #include "expr.h" ! 28: #include "insn-config.h" ! 29: #include "recog.h" ! 30: ! 31: /* Each optab contains info on how this target machine ! 32: can perform a particular operation ! 33: for all sizes and kinds of operands. ! 34: ! 35: The operation to be performed is often specified ! 36: by passing one of these optabs as an argument. ! 37: ! 38: See expr.h for documentation of these optabs. */ ! 39: ! 40: optab add_optab; ! 41: optab sub_optab; ! 42: optab smul_optab; ! 43: optab smul_widen_optab; ! 44: optab umul_widen_optab; ! 45: optab sdiv_optab; ! 46: optab sdivmod_optab; ! 47: optab udiv_optab; ! 48: optab udivmod_optab; ! 49: optab smod_optab; ! 50: optab umod_optab; ! 51: optab flodiv_optab; ! 52: optab ftrunc_optab; ! 53: optab and_optab; ! 54: optab ior_optab; ! 55: optab xor_optab; ! 56: optab ashl_optab; ! 57: optab lshr_optab; ! 58: optab lshl_optab; ! 59: optab ashr_optab; ! 60: optab rotl_optab; ! 61: optab rotr_optab; ! 62: optab smin_optab; ! 63: optab smax_optab; ! 64: optab umin_optab; ! 65: optab umax_optab; ! 66: ! 67: optab mov_optab; ! 68: optab movstrict_optab; ! 69: ! 70: optab neg_optab; ! 71: optab abs_optab; ! 72: optab one_cmpl_optab; ! 73: optab ffs_optab; ! 74: ! 75: optab cmp_optab; ! 76: optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */ ! 77: optab tst_optab; ! 78: ! 79: /* SYMBOL_REF rtx's for the library functions that are called ! 80: implicitly and not via optabs. */ ! 81: ! 82: rtx extendsfdf2_libfunc; ! 83: rtx truncdfsf2_libfunc; ! 84: rtx memcpy_libfunc; ! 85: rtx bcopy_libfunc; ! 86: rtx memcmp_libfunc; ! 87: rtx bcmp_libfunc; ! 88: rtx memset_libfunc; ! 89: rtx bzero_libfunc; ! 90: rtx eqsf2_libfunc; ! 91: rtx nesf2_libfunc; ! 92: rtx gtsf2_libfunc; ! 93: rtx gesf2_libfunc; ! 94: rtx ltsf2_libfunc; ! 95: rtx lesf2_libfunc; ! 96: rtx eqdf2_libfunc; ! 97: rtx nedf2_libfunc; ! 98: rtx gtdf2_libfunc; ! 99: rtx gedf2_libfunc; ! 100: rtx ltdf2_libfunc; ! 101: rtx ledf2_libfunc; ! 102: rtx floatdisf_libfunc; ! 103: rtx floatsisf_libfunc; ! 104: rtx floatdidf_libfunc; ! 105: rtx floatsidf_libfunc; ! 106: rtx fixsfsi_libfunc; ! 107: rtx fixsfdi_libfunc; ! 108: rtx fixdfsi_libfunc; ! 109: rtx fixdfdi_libfunc; ! 110: rtx fixunssfsi_libfunc; ! 111: rtx fixunssfdi_libfunc; ! 112: rtx fixunsdfsi_libfunc; ! 113: rtx fixunsdfdi_libfunc; ! 114: ! 115: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) ! 116: gives the gen_function to make a branch to test that condition. */ ! 117: ! 118: rtxfun bcc_gen_fctn[NUM_RTX_CODE]; ! 119: ! 120: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) ! 121: gives the insn code to make a store-condition insn ! 122: to test that condition. */ ! 123: ! 124: enum insn_code setcc_gen_code[NUM_RTX_CODE]; ! 125: ! 126: static void emit_float_lib_cmp (); ! 127: ! 128: /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to ! 129: the result of operation CODE applied to OP0 (and OP1 if it is a binary ! 130: operation). ! 131: ! 132: If the last insn does not set TARGET, don't do anything, but return 1. ! 133: ! 134: If a previous insn sets TARGET and TARGET is one of OP0 or OP1, ! 135: don't add the REG_EQUAL note but return 0. Our caller can then try ! 136: again, ensuring that TARGET is not one of the operands. */ ! 137: ! 138: static int ! 139: add_equal_note (seq, target, code, op0, op1) ! 140: rtx seq; ! 141: rtx target; ! 142: enum rtx_code code; ! 143: rtx op0, op1; ! 144: { ! 145: rtx set; ! 146: int i; ! 147: rtx note; ! 148: ! 149: if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2' ! 150: && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<') ! 151: || GET_CODE (seq) != SEQUENCE ! 152: || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0 ! 153: || GET_CODE (target) == ZERO_EXTRACT ! 154: || (! rtx_equal_p (SET_DEST (set), target) ! 155: /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the ! 156: SUBREG. */ ! 157: && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART ! 158: || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)), ! 159: target)))) ! 160: return 1; ! 161: ! 162: /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET ! 163: besides the last insn. */ ! 164: if (reg_overlap_mentioned_p (target, op0) ! 165: || (op1 && reg_overlap_mentioned_p (target, op1))) ! 166: for (i = XVECLEN (seq, 0) - 2; i >= 0; i--) ! 167: if (reg_set_p (target, XVECEXP (seq, 0, i))) ! 168: return 0; ! 169: ! 170: if (GET_RTX_CLASS (code) == '1') ! 171: note = gen_rtx (code, GET_MODE (target), op0); ! 172: else ! 173: note = gen_rtx (code, GET_MODE (target), op0, op1); ! 174: ! 175: REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)) ! 176: = gen_rtx (EXPR_LIST, REG_EQUAL, note, ! 177: REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))); ! 178: ! 179: return 1; ! 180: } ! 181: ! 182: /* Generate code to perform an operation specified by BINOPTAB ! 183: on operands OP0 and OP1, with result having machine-mode MODE. ! 184: ! 185: UNSIGNEDP is for the case where we have to widen the operands ! 186: to perform the operation. It says to use zero-extension. ! 187: ! 188: If TARGET is nonzero, the value ! 189: is generated there, if it is convenient to do so. ! 190: In all cases an rtx is returned for the locus of the value; ! 191: this may or may not be TARGET. */ ! 192: ! 193: rtx ! 194: expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) ! 195: enum machine_mode mode; ! 196: optab binoptab; ! 197: rtx op0, op1; ! 198: rtx target; ! 199: int unsignedp; ! 200: enum optab_methods methods; ! 201: { ! 202: enum mode_class class; ! 203: enum machine_mode wider_mode; ! 204: register rtx temp; ! 205: int commutative_op = 0; ! 206: int shift_op = (binoptab->code == ASHIFT ! 207: || binoptab->code == ASHIFTRT ! 208: || binoptab->code == LSHIFT ! 209: || binoptab->code == LSHIFTRT ! 210: || binoptab->code == ROTATE ! 211: || binoptab->code == ROTATERT); ! 212: rtx last; ! 213: ! 214: class = GET_MODE_CLASS (mode); ! 215: ! 216: op0 = protect_from_queue (op0, 0); ! 217: op1 = protect_from_queue (op1, 0); ! 218: if (target) ! 219: target = protect_from_queue (target, 1); ! 220: ! 221: if (flag_force_mem) ! 222: { ! 223: op0 = force_not_mem (op0); ! 224: op1 = force_not_mem (op1); ! 225: } ! 226: ! 227: /* If we are inside an appropriately-short loop and one operand is an ! 228: expensive constant, force it into a register. */ ! 229: if (CONSTANT_P (op0) && preserve_subexpressions_p () && rtx_cost (op0) > 2) ! 230: op0 = force_reg (mode, op0); ! 231: ! 232: if (CONSTANT_P (op1) && preserve_subexpressions_p () && rtx_cost (op1) > 2) ! 233: op1 = force_reg (shift_op ? word_mode : mode, op1); ! 234: ! 235: #if 0 /* Turned off because it seems to be a kludgy method. */ ! 236: /* If subtracting integer from pointer, and the pointer has a special mode, ! 237: then change it to an add. We use the add insn of Pmode for combining ! 238: integers with pointers, and the sub insn to subtract two pointers. */ ! 239: ! 240: if (binoptab == sub_optab ! 241: && GET_MODE (op0) == Pmode && GET_MODE (op1) != Pmode) ! 242: { ! 243: op1 = negate_rtx (GET_MODE(op1), op1); ! 244: binoptab = add_optab; ! 245: } ! 246: #endif /* 0 */ ! 247: ! 248: /* Record where to delete back to if we backtrack. */ ! 249: last = get_last_insn (); ! 250: ! 251: /* If operation is commutative, ! 252: try to make the first operand a register. ! 253: Even better, try to make it the same as the target. ! 254: Also try to make the last operand a constant. */ ! 255: if (GET_RTX_CLASS (binoptab->code) == 'c' ! 256: || binoptab == smul_widen_optab ! 257: || binoptab == umul_widen_optab) ! 258: { ! 259: commutative_op = 1; ! 260: ! 261: if (((target == 0 || GET_CODE (target) == REG) ! 262: ? ((GET_CODE (op1) == REG ! 263: && GET_CODE (op0) != REG) ! 264: || target == op1) ! 265: : rtx_equal_p (op1, target)) ! 266: || GET_CODE (op0) == CONST_INT) ! 267: { ! 268: temp = op1; ! 269: op1 = op0; ! 270: op0 = temp; ! 271: } ! 272: } ! 273: ! 274: /* If we can do it with a three-operand insn, do so. */ ! 275: ! 276: if (methods != OPTAB_MUST_WIDEN ! 277: && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 278: { ! 279: int icode = (int) binoptab->handlers[(int) mode].insn_code; ! 280: enum machine_mode mode0 = insn_operand_mode[icode][1]; ! 281: enum machine_mode mode1 = insn_operand_mode[icode][2]; ! 282: rtx pat; ! 283: rtx xop0 = op0, xop1 = op1; ! 284: ! 285: if (target) ! 286: temp = target; ! 287: else ! 288: temp = gen_reg_rtx (mode); ! 289: ! 290: /* If it is a commutative operator and the modes would match ! 291: if we would swap the operands, we can save the conversions. */ ! 292: if (commutative_op) ! 293: { ! 294: if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1 ! 295: && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0) ! 296: { ! 297: register rtx tmp; ! 298: ! 299: tmp = op0; op0 = op1; op1 = tmp; ! 300: tmp = xop0; xop0 = xop1; xop1 = tmp; ! 301: } ! 302: } ! 303: ! 304: /* In case the insn wants input operands in modes different from ! 305: the result, convert the operands. */ ! 306: ! 307: if (GET_MODE (op0) != VOIDmode ! 308: && GET_MODE (op0) != mode0) ! 309: xop0 = convert_to_mode (mode0, xop0, unsignedp); ! 310: ! 311: if (GET_MODE (xop1) != VOIDmode ! 312: && GET_MODE (xop1) != mode1) ! 313: xop1 = convert_to_mode (mode1, xop1, unsignedp); ! 314: ! 315: /* Now, if insn's predicates don't allow our operands, put them into ! 316: pseudo regs. */ ! 317: ! 318: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) ! 319: xop0 = copy_to_mode_reg (mode0, xop0); ! 320: ! 321: if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)) ! 322: xop1 = copy_to_mode_reg (mode1, xop1); ! 323: ! 324: if (! (*insn_operand_predicate[icode][0]) (temp, mode)) ! 325: temp = gen_reg_rtx (mode); ! 326: ! 327: pat = GEN_FCN (icode) (temp, xop0, xop1); ! 328: if (pat) ! 329: { ! 330: /* If PAT is a multi-insn sequence, try to add an appropriate ! 331: REG_EQUAL note to it. If we can't because TEMP conflicts with an ! 332: operand, call ourselves again, this time without a target. */ ! 333: if (GET_CODE (pat) == SEQUENCE ! 334: && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1)) ! 335: { ! 336: delete_insns_since (last); ! 337: return expand_binop (mode, binoptab, op0, op1, 0, unsignedp, ! 338: methods); ! 339: } ! 340: ! 341: emit_insn (pat); ! 342: return temp; ! 343: } ! 344: else ! 345: delete_insns_since (last); ! 346: } ! 347: ! 348: /* These can be done a word at a time. */ ! 349: if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab) ! 350: && class == MODE_INT ! 351: && GET_MODE_SIZE (mode) > UNITS_PER_WORD ! 352: && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) ! 353: { ! 354: int i; ! 355: rtx insns; ! 356: rtx equiv_value; ! 357: ! 358: /* If TARGET is the same as one of the operands, the REG_EQUAL note ! 359: won't be accurate, so use a new target. */ ! 360: if (target == 0 || target == op0 || target == op1) ! 361: target = gen_reg_rtx (mode); ! 362: ! 363: start_sequence (); ! 364: ! 365: /* Do the actual arithmetic. */ ! 366: for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++) ! 367: { ! 368: rtx target_piece = operand_subword (target, i, 1, mode); ! 369: rtx x = expand_binop (word_mode, binoptab, ! 370: operand_subword_force (op0, i, mode), ! 371: operand_subword_force (op1, i, mode), ! 372: target_piece, unsignedp, methods); ! 373: if (target_piece != x) ! 374: emit_move_insn (target_piece, x); ! 375: } ! 376: ! 377: insns = get_insns (); ! 378: end_sequence (); ! 379: ! 380: if (binoptab->code != UNKNOWN) ! 381: equiv_value = gen_rtx (binoptab->code, mode, op0, op1); ! 382: else ! 383: equiv_value = 0; ! 384: ! 385: emit_no_conflict_block (insns, target, op0, op1, equiv_value); ! 386: return target; ! 387: } ! 388: ! 389: /* These can be done a word at a time by propagating carries. */ ! 390: if ((binoptab == add_optab || binoptab == sub_optab) ! 391: && class == MODE_INT ! 392: && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD ! 393: && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) ! 394: { ! 395: int i; ! 396: rtx carry_tmp = gen_reg_rtx (word_mode); ! 397: optab otheroptab = binoptab == add_optab ? sub_optab : add_optab; ! 398: int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; ! 399: rtx carry_in, carry_out; ! 400: ! 401: /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG ! 402: value is one of those, use it. Otherwise, use 1 since it is the ! 403: one easiest to get. */ ! 404: #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1 ! 405: int normalizep = STORE_FLAG_VALUE; ! 406: #else ! 407: int normalizep = 1; ! 408: #endif ! 409: ! 410: /* Prepare the operands. */ ! 411: op0 = force_reg (mode, op0); ! 412: op1 = force_reg (mode, op1); ! 413: ! 414: if (target == 0 || GET_CODE (target) != REG ! 415: || target == op0 || target == op1) ! 416: target = gen_reg_rtx (mode); ! 417: ! 418: /* Do the actual arithmetic. */ ! 419: for (i = 0; i < nwords; i++) ! 420: { ! 421: int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); ! 422: rtx target_piece = operand_subword (target, index, 1, mode); ! 423: rtx op0_piece = operand_subword_force (op0, index, mode); ! 424: rtx op1_piece = operand_subword_force (op1, index, mode); ! 425: rtx x; ! 426: ! 427: /* Main add/subtract of the input operands. */ ! 428: x = expand_binop (word_mode, binoptab, ! 429: op0_piece, op1_piece, ! 430: target_piece, unsignedp, methods); ! 431: if (x == 0) ! 432: break; ! 433: ! 434: if (i + 1 < nwords) ! 435: { ! 436: /* Store carry from main add/subtract. */ ! 437: carry_out = gen_reg_rtx (word_mode); ! 438: carry_out = emit_store_flag (carry_out, ! 439: binoptab == add_optab ? LTU : GTU, ! 440: x, op0_piece, ! 441: word_mode, 1, normalizep); ! 442: if (!carry_out) ! 443: break; ! 444: } ! 445: ! 446: if (i > 0) ! 447: { ! 448: /* Add/subtract previous carry to main result. */ ! 449: x = expand_binop (word_mode, ! 450: normalizep == 1 ? binoptab : otheroptab, ! 451: x, carry_in, ! 452: target_piece, 1, methods); ! 453: if (target_piece != x) ! 454: emit_move_insn (target_piece, x); ! 455: ! 456: if (i + 1 < nwords) ! 457: { ! 458: /* THIS CODE HAS NOT BEEN TESTED. */ ! 459: /* Get out carry from adding/subtracting carry in. */ ! 460: carry_tmp = emit_store_flag (carry_tmp, ! 461: binoptab == add_optab ! 462: ? LTU : GTU, ! 463: x, carry_in, ! 464: word_mode, 1, normalizep); ! 465: /* Logical-ior the two poss. carry together. */ ! 466: carry_out = expand_binop (word_mode, ior_optab, ! 467: carry_out, carry_tmp, ! 468: carry_out, 0, methods); ! 469: if (!carry_out) ! 470: break; ! 471: } ! 472: } ! 473: ! 474: carry_in = carry_out; ! 475: } ! 476: ! 477: if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD) ! 478: { ! 479: rtx temp; ! 480: ! 481: temp = emit_move_insn (target, target); ! 482: REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL, ! 483: gen_rtx (binoptab->code, mode, op0, op1), ! 484: REG_NOTES (temp)); ! 485: return target; ! 486: } ! 487: else ! 488: delete_insns_since (last); ! 489: } ! 490: ! 491: /* If we want to multiply two two-word values and have normal and widening ! 492: multiplies of single-word values, we can do this with three smaller ! 493: multiplications. Note that we do not make a REG_NO_CONFLICT block here ! 494: because we are not operating on one word at a time. ! 495: ! 496: The multiplication proceeds as follows: ! 497: _______________________ ! 498: [__op0_high_|__op0_low__] ! 499: _______________________ ! 500: * [__op1_high_|__op1_low__] ! 501: _______________________________________________ ! 502: _______________________ ! 503: (1) [__op0_low__*__op1_low__] ! 504: _______________________ ! 505: (2a) [__op0_low__*__op1_high_] ! 506: _______________________ ! 507: (2b) [__op0_high_*__op1_low__] ! 508: _______________________ ! 509: (3) [__op0_high_*__op1_high_] ! 510: ! 511: ! 512: This gives a 4-word result. Since we are only interested in the ! 513: lower 2 words, partial result (3) and the upper words of (2a) and ! 514: (2b) don't need to be calculated. Hence (2a) and (2b) can be ! 515: calculated using non-widening multiplication. ! 516: ! 517: (1), however, needs to be calculated with an unsigned widening ! 518: multiplication. If this operation is not directly supported we ! 519: try using a signed widening multiplication and adjust the result. ! 520: This adjustment works as follows: ! 521: ! 522: If both operands are positive then no adjustment is needed. ! 523: ! 524: If the operands have different signs, for example op0_low < 0 and ! 525: op1_low >= 0, the instruction treats the most significant bit of ! 526: op0_low as a sign bit instead of a bit with significance ! 527: 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low ! 528: with 2**BITS_PER_WORD - op0_low, and two's complements the ! 529: result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to ! 530: the result. ! 531: ! 532: Similarly, if both operands are negative, we need to add ! 533: (op0_low + op1_low) * 2**BITS_PER_WORD. ! 534: ! 535: We use a trick to adjust quickly. We logically shift op0_low right ! 536: (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to ! 537: op0_high (op1_high) before it is used to calculate 2b (2a). If no ! 538: logical shift exists, we do an arithmetic right shift and subtract ! 539: the 0 or -1. */ ! 540: ! 541: if (binoptab == smul_optab ! 542: && class == MODE_INT ! 543: && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD ! 544: && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing ! 545: && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing ! 546: && ((umul_widen_optab->handlers[(int) mode].insn_code ! 547: != CODE_FOR_nothing) ! 548: || (smul_widen_optab->handlers[(int) mode].insn_code ! 549: != CODE_FOR_nothing))) ! 550: { ! 551: int low = (WORDS_BIG_ENDIAN ? 1 : 0); ! 552: int high = (WORDS_BIG_ENDIAN ? 0 : 1); ! 553: rtx op0_high = operand_subword_force (op0, high, mode); ! 554: rtx op0_low = operand_subword_force (op0, low, mode); ! 555: rtx op1_high = operand_subword_force (op1, high, mode); ! 556: rtx op1_low = operand_subword_force (op1, low, mode); ! 557: rtx product = 0; ! 558: rtx op0_xhigh; ! 559: rtx op1_xhigh; ! 560: ! 561: /* If the target is the same as one of the inputs, don't use it. This ! 562: prevents problems with the REG_EQUAL note. */ ! 563: if (target == op0 || target == op1) ! 564: target = 0; ! 565: ! 566: /* Multiply the two lower words to get a double-word product. ! 567: If unsigned widening multiplication is available, use that; ! 568: otherwise use the signed form and compensate. */ ! 569: ! 570: if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 571: { ! 572: product = expand_binop (mode, umul_widen_optab, op0_low, op1_low, ! 573: target, 1, OPTAB_DIRECT); ! 574: ! 575: /* If we didn't succeed, delete everything we did so far. */ ! 576: if (product == 0) ! 577: delete_insns_since (last); ! 578: else ! 579: op0_xhigh = op0_high, op1_xhigh = op1_high; ! 580: } ! 581: ! 582: if (product == 0 ! 583: && smul_widen_optab->handlers[(int) mode].insn_code ! 584: != CODE_FOR_nothing) ! 585: { ! 586: rtx wordm1 = gen_rtx (CONST_INT, VOIDmode, BITS_PER_WORD - 1); ! 587: product = expand_binop (mode, smul_widen_optab, op0_low, op1_low, ! 588: target, 1, OPTAB_DIRECT); ! 589: op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1, ! 590: 0, 1, OPTAB_DIRECT); ! 591: if (op0_xhigh) ! 592: op0_xhigh = expand_binop (word_mode, add_optab, op0_high, ! 593: op0_xhigh, op0_xhigh, 0, OPTAB_DIRECT); ! 594: else ! 595: { ! 596: op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1, ! 597: 0, 0, OPTAB_DIRECT); ! 598: if (op0_xhigh) ! 599: op0_xhigh = expand_binop (word_mode, sub_optab, op0_high, ! 600: op0_xhigh, op0_xhigh, 0, ! 601: OPTAB_DIRECT); ! 602: } ! 603: ! 604: op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1, ! 605: 0, 1, OPTAB_DIRECT); ! 606: if (op1_xhigh) ! 607: op1_xhigh = expand_binop (word_mode, add_optab, op1_high, ! 608: op1_xhigh, op1_xhigh, 0, OPTAB_DIRECT); ! 609: else ! 610: { ! 611: op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1, ! 612: 0, 0, OPTAB_DIRECT); ! 613: if (op1_xhigh) ! 614: op1_xhigh = expand_binop (word_mode, sub_optab, op1_high, ! 615: op1_xhigh, op1_xhigh, 0, ! 616: OPTAB_DIRECT); ! 617: } ! 618: } ! 619: ! 620: /* If we have been able to directly compute the product of the ! 621: low-order words of the operands and perform any required adjustments ! 622: of the operands, we proceed by trying two more multiplications ! 623: and then computing the appropriate sum. ! 624: ! 625: We have checked above that the required addition is provided. ! 626: Full-word addition will normally always succeed, especially if ! 627: it is provided at all, so we don't worry about its failure. The ! 628: multiplication may well fail, however, so we do handle that. */ ! 629: ! 630: if (product && op0_xhigh && op1_xhigh) ! 631: { ! 632: rtx product_piece; ! 633: rtx product_high = operand_subword (product, high, 1, mode); ! 634: rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh, 0, ! 635: 0, OPTAB_DIRECT); ! 636: ! 637: if (temp) ! 638: { ! 639: product_piece = expand_binop (word_mode, add_optab, temp, ! 640: product_high, product_high, ! 641: 0, OPTAB_LIB_WIDEN); ! 642: if (product_piece != product_high) ! 643: emit_move_insn (product_high, product_piece); ! 644: ! 645: temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh, 0, ! 646: 0, OPTAB_DIRECT); ! 647: ! 648: product_piece = expand_binop (word_mode, add_optab, temp, ! 649: product_high, product_high, ! 650: 0, OPTAB_LIB_WIDEN); ! 651: if (product_piece != product_high) ! 652: emit_move_insn (product_high, product_piece); ! 653: ! 654: temp = emit_move_insn (product, product); ! 655: REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL, ! 656: gen_rtx (MULT, mode, op0, op1), ! 657: REG_NOTES (temp)); ! 658: ! 659: return product; ! 660: } ! 661: } ! 662: ! 663: /* If we get here, we couldn't do it for some reason even though we ! 664: originally thought we could. Delete anything we've emitted in ! 665: trying to do it. */ ! 666: ! 667: delete_insns_since (last); ! 668: } ! 669: ! 670: /* It can't be open-coded in this mode. ! 671: Use a library call if one is available and caller says that's ok. */ ! 672: ! 673: if (binoptab->handlers[(int) mode].libfunc ! 674: && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN)) ! 675: { ! 676: rtx insns; ! 677: rtx funexp = binoptab->handlers[(int) mode].libfunc; ! 678: ! 679: start_sequence (); ! 680: ! 681: /* Pass 1 for NO_QUEUE so we don't lose any increments ! 682: if the libcall is cse'd or moved. */ ! 683: emit_library_call (binoptab->handlers[(int) mode].libfunc, ! 684: 1, mode, 2, op0, mode, op1, ! 685: (shift_op ? word_mode : mode)); ! 686: ! 687: insns = get_insns (); ! 688: end_sequence (); ! 689: ! 690: target = gen_reg_rtx (mode); ! 691: emit_libcall_block (insns, target, hard_libcall_value (mode), ! 692: gen_rtx (binoptab->code, mode, op0, op1)); ! 693: ! 694: return target; ! 695: } ! 696: ! 697: delete_insns_since (last); ! 698: ! 699: /* It can't be done in this mode. Can we do it in a wider mode? */ ! 700: ! 701: if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN ! 702: || methods == OPTAB_MUST_WIDEN)) ! 703: return 0; /* Caller says, don't even try. */ ! 704: ! 705: /* Compute the value of METHODS to pass to recursive calls. ! 706: Don't allow widening to be tried recursively. */ ! 707: ! 708: methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT); ! 709: ! 710: /* Look for a wider mode of the same class for which it appears we can do ! 711: the operation. */ ! 712: ! 713: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) ! 714: { ! 715: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; ! 716: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) ! 717: { ! 718: if ((binoptab->handlers[(int) wider_mode].insn_code ! 719: != CODE_FOR_nothing) ! 720: || (methods == OPTAB_LIB ! 721: && binoptab->handlers[(int) wider_mode].libfunc)) ! 722: { ! 723: rtx xop0 = op0, xop1 = op1; ! 724: int no_extend = 0; ! 725: ! 726: /* For certain integer operations, we need not actually extend ! 727: the narrow operands, as long as we will truncate ! 728: the results to the same narrowness. */ ! 729: ! 730: if ((binoptab == ior_optab || binoptab == and_optab ! 731: || binoptab == xor_optab ! 732: || binoptab == add_optab || binoptab == sub_optab ! 733: || binoptab == smul_optab ! 734: || binoptab == ashl_optab || binoptab == lshl_optab) ! 735: && class == MODE_INT) ! 736: no_extend = 1; ! 737: ! 738: /* If an operand is a constant integer, we might as well ! 739: convert it since that is more efficient than using a SUBREG, ! 740: unlike the case for other operands. */ ! 741: ! 742: if (no_extend && GET_MODE (xop0) != VOIDmode) ! 743: xop0 = gen_rtx (SUBREG, wider_mode, ! 744: force_reg (GET_MODE (xop0), xop0), 0); ! 745: else ! 746: xop0 = convert_to_mode (wider_mode, xop0, unsignedp); ! 747: ! 748: if (no_extend && GET_MODE (xop1) != VOIDmode) ! 749: xop1 = gen_rtx (SUBREG, wider_mode, ! 750: force_reg (GET_MODE (xop1), xop1), 0); ! 751: else ! 752: xop1 = convert_to_mode (wider_mode, xop1, unsignedp); ! 753: ! 754: temp = expand_binop (wider_mode, binoptab, xop0, xop1, 0, ! 755: unsignedp, methods); ! 756: if (temp) ! 757: { ! 758: if (class != MODE_INT) ! 759: { ! 760: if (target == 0) ! 761: target = gen_reg_rtx (mode); ! 762: convert_move (target, temp, 0); ! 763: return target; ! 764: } ! 765: else ! 766: return gen_lowpart (mode, temp); ! 767: } ! 768: else ! 769: delete_insns_since (last); ! 770: } ! 771: } ! 772: } ! 773: ! 774: return 0; ! 775: } ! 776: ! 777: /* Expand a binary operator which has both signed and unsigned forms. ! 778: UOPTAB is the optab for unsigned operations, and SOPTAB is for ! 779: signed operations. ! 780: ! 781: If we widen unsigned operands, we may use a signed wider operation instead ! 782: of an unsigned wider operation, since the result would be the same. */ ! 783: ! 784: rtx ! 785: sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods) ! 786: enum machine_mode mode; ! 787: optab uoptab, soptab; ! 788: rtx op0, op1, target; ! 789: int unsignedp; ! 790: enum optab_methods methods; ! 791: { ! 792: register rtx temp; ! 793: optab direct_optab = unsignedp ? uoptab : soptab; ! 794: struct optab wide_soptab; ! 795: ! 796: /* Do it without widening, if possible. */ ! 797: temp = expand_binop (mode, direct_optab, op0, op1, target, ! 798: unsignedp, OPTAB_DIRECT); ! 799: if (temp || methods == OPTAB_DIRECT) ! 800: return temp; ! 801: ! 802: /* Try widening to a signed int. Make a fake signed optab that ! 803: hides any signed insn for direct use. */ ! 804: wide_soptab = *soptab; ! 805: wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing; ! 806: wide_soptab.handlers[(int) mode].libfunc = 0; ! 807: ! 808: temp = expand_binop (mode, &wide_soptab, op0, op1, target, ! 809: unsignedp, OPTAB_WIDEN); ! 810: ! 811: /* For unsigned operands, try widening to an unsigned int. */ ! 812: if (temp == 0 && unsignedp) ! 813: temp = expand_binop (mode, uoptab, op0, op1, target, ! 814: unsignedp, OPTAB_WIDEN); ! 815: if (temp || methods == OPTAB_WIDEN) ! 816: return temp; ! 817: ! 818: /* Use the right width lib call if that exists. */ ! 819: temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB); ! 820: if (temp || methods == OPTAB_LIB) ! 821: return temp; ! 822: ! 823: /* Must widen and use a lib call, use either signed or unsigned. */ ! 824: temp = expand_binop (mode, &wide_soptab, op0, op1, target, ! 825: unsignedp, methods); ! 826: if (temp != 0) ! 827: return temp; ! 828: if (unsignedp) ! 829: return expand_binop (mode, uoptab, op0, op1, target, ! 830: unsignedp, methods); ! 831: return 0; ! 832: } ! 833: ! 834: /* Generate code to perform an operation specified by BINOPTAB ! 835: on operands OP0 and OP1, with two results to TARG1 and TARG2. ! 836: We assume that the order of the operands for the instruction ! 837: is TARG0, OP0, OP1, TARG1, which would fit a pattern like ! 838: [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))]. ! 839: ! 840: Either TARG0 or TARG1 may be zero, but what that means is that ! 841: that result is not actually wanted. We will generate it into ! 842: a dummy pseudo-reg and discard it. They may not both be zero. ! 843: ! 844: Returns 1 if this operation can be performed; 0 if not. */ ! 845: ! 846: int ! 847: expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp) ! 848: optab binoptab; ! 849: rtx op0, op1; ! 850: rtx targ0, targ1; ! 851: int unsignedp; ! 852: { ! 853: enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1); ! 854: enum mode_class class; ! 855: enum machine_mode wider_mode; ! 856: rtx last; ! 857: ! 858: class = GET_MODE_CLASS (mode); ! 859: ! 860: op0 = protect_from_queue (op0, 0); ! 861: op1 = protect_from_queue (op1, 0); ! 862: ! 863: if (flag_force_mem) ! 864: { ! 865: op0 = force_not_mem (op0); ! 866: op1 = force_not_mem (op1); ! 867: } ! 868: ! 869: /* If we are inside an appropriately-short loop and one operand is an ! 870: expensive constant, force it into a register. */ ! 871: if (CONSTANT_P (op0) && preserve_subexpressions_p () && rtx_cost (op0) > 2) ! 872: op0 = force_reg (mode, op0); ! 873: ! 874: if (CONSTANT_P (op1) && preserve_subexpressions_p () && rtx_cost (op1) > 2) ! 875: op1 = force_reg (mode, op1); ! 876: ! 877: if (targ0) ! 878: targ0 = protect_from_queue (targ0, 1); ! 879: else ! 880: targ0 = gen_reg_rtx (mode); ! 881: if (targ1) ! 882: targ1 = protect_from_queue (targ1, 1); ! 883: else ! 884: targ1 = gen_reg_rtx (mode); ! 885: ! 886: /* Record where to go back to if we fail. */ ! 887: last = get_last_insn (); ! 888: ! 889: if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 890: { ! 891: int icode = (int) binoptab->handlers[(int) mode].insn_code; ! 892: enum machine_mode mode0 = insn_operand_mode[icode][1]; ! 893: enum machine_mode mode1 = insn_operand_mode[icode][2]; ! 894: rtx pat; ! 895: rtx xop0 = op0, xop1 = op1; ! 896: ! 897: /* In case this insn wants input operands in modes different from the ! 898: result, convert the operands. */ ! 899: if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0) ! 900: xop0 = convert_to_mode (mode0, xop0, unsignedp); ! 901: ! 902: if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1) ! 903: xop1 = convert_to_mode (mode1, xop1, unsignedp); ! 904: ! 905: /* Now, if insn doesn't accept these operands, put them into pseudos. */ ! 906: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) ! 907: xop0 = copy_to_mode_reg (mode0, xop0); ! 908: ! 909: if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)) ! 910: xop1 = copy_to_mode_reg (mode1, xop1); ! 911: ! 912: /* We could handle this, but we should always be called with a pseudo ! 913: for our targets and all insns should take them as outputs. */ ! 914: if (! (*insn_operand_predicate[icode][0]) (targ0, mode) ! 915: || ! (*insn_operand_predicate[icode][3]) (targ1, mode)) ! 916: abort (); ! 917: ! 918: pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1); ! 919: if (pat) ! 920: { ! 921: emit_insn (pat); ! 922: return 1; ! 923: } ! 924: else ! 925: delete_insns_since (last); ! 926: } ! 927: ! 928: /* It can't be done in this mode. Can we do it in a wider mode? */ ! 929: ! 930: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) ! 931: { ! 932: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; ! 933: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) ! 934: { ! 935: if (binoptab->handlers[(int) wider_mode].insn_code ! 936: != CODE_FOR_nothing) ! 937: { ! 938: register rtx t0 = gen_reg_rtx (wider_mode); ! 939: register rtx t1 = gen_reg_rtx (wider_mode); ! 940: ! 941: if (expand_twoval_binop (binoptab, ! 942: convert_to_mode (wider_mode, op0, ! 943: unsignedp), ! 944: convert_to_mode (wider_mode, op1, ! 945: unsignedp), ! 946: t0, t1, unsignedp)) ! 947: { ! 948: convert_move (targ0, t0, unsignedp); ! 949: convert_move (targ1, t1, unsignedp); ! 950: return 1; ! 951: } ! 952: else ! 953: delete_insns_since (last); ! 954: } ! 955: } ! 956: } ! 957: ! 958: return 0; ! 959: } ! 960: ! 961: /* Generate code to perform an operation specified by UNOPTAB ! 962: on operand OP0, with result having machine-mode MODE. ! 963: ! 964: UNSIGNEDP is for the case where we have to widen the operands ! 965: to perform the operation. It says to use zero-extension. ! 966: ! 967: If TARGET is nonzero, the value ! 968: is generated there, if it is convenient to do so. ! 969: In all cases an rtx is returned for the locus of the value; ! 970: this may or may not be TARGET. */ ! 971: ! 972: rtx ! 973: expand_unop (mode, unoptab, op0, target, unsignedp) ! 974: enum machine_mode mode; ! 975: optab unoptab; ! 976: rtx op0; ! 977: rtx target; ! 978: int unsignedp; ! 979: { ! 980: enum mode_class class; ! 981: enum machine_mode wider_mode; ! 982: register rtx temp; ! 983: rtx last = get_last_insn (); ! 984: rtx pat; ! 985: ! 986: class = GET_MODE_CLASS (mode); ! 987: ! 988: op0 = protect_from_queue (op0, 0); ! 989: ! 990: if (flag_force_mem) ! 991: { ! 992: op0 = force_not_mem (op0); ! 993: } ! 994: ! 995: if (target) ! 996: target = protect_from_queue (target, 1); ! 997: ! 998: if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 999: { ! 1000: int icode = (int) unoptab->handlers[(int) mode].insn_code; ! 1001: enum machine_mode mode0 = insn_operand_mode[icode][1]; ! 1002: rtx xop0 = op0; ! 1003: ! 1004: if (target) ! 1005: temp = target; ! 1006: else ! 1007: temp = gen_reg_rtx (mode); ! 1008: ! 1009: if (GET_MODE (xop0) != VOIDmode ! 1010: && GET_MODE (xop0) != mode0) ! 1011: xop0 = convert_to_mode (mode0, xop0, unsignedp); ! 1012: ! 1013: /* Now, if insn doesn't accept our operand, put it into a pseudo. */ ! 1014: ! 1015: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) ! 1016: xop0 = copy_to_mode_reg (mode0, xop0); ! 1017: ! 1018: if (! (*insn_operand_predicate[icode][0]) (temp, mode)) ! 1019: temp = gen_reg_rtx (mode); ! 1020: ! 1021: pat = GEN_FCN (icode) (temp, xop0); ! 1022: if (pat) ! 1023: { ! 1024: if (GET_CODE (pat) == SEQUENCE ! 1025: && ! add_equal_note (pat, temp, unoptab->code, xop0, 0)) ! 1026: { ! 1027: delete_insns_since (last); ! 1028: return expand_unop (mode, unoptab, op0, 0, unsignedp); ! 1029: } ! 1030: ! 1031: emit_insn (pat); ! 1032: ! 1033: return temp; ! 1034: } ! 1035: else ! 1036: delete_insns_since (last); ! 1037: } ! 1038: ! 1039: /* These can be done a word at a time. */ ! 1040: if (unoptab == one_cmpl_optab ! 1041: && class == MODE_INT ! 1042: && GET_MODE_SIZE (mode) > UNITS_PER_WORD ! 1043: && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) ! 1044: { ! 1045: int i; ! 1046: rtx insns; ! 1047: ! 1048: if (target == 0 || target == op0) ! 1049: target = gen_reg_rtx (mode); ! 1050: ! 1051: start_sequence (); ! 1052: ! 1053: /* Do the actual arithmetic. */ ! 1054: for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++) ! 1055: { ! 1056: rtx target_piece = operand_subword (target, i, 1, mode); ! 1057: rtx x = expand_unop (word_mode, unoptab, ! 1058: operand_subword_force (op0, i, mode), ! 1059: target_piece, unsignedp); ! 1060: if (target_piece != x) ! 1061: emit_move_insn (target_piece, x); ! 1062: } ! 1063: ! 1064: insns = get_insns (); ! 1065: end_sequence (); ! 1066: ! 1067: emit_no_conflict_block (insns, target, op0, 0, ! 1068: gen_rtx (unoptab->code, mode, op0)); ! 1069: return target; ! 1070: } ! 1071: ! 1072: if (unoptab->handlers[(int) mode].libfunc) ! 1073: { ! 1074: rtx insns; ! 1075: rtx funexp = unoptab->handlers[(int) mode].libfunc; ! 1076: ! 1077: start_sequence (); ! 1078: ! 1079: /* Pass 1 for NO_QUEUE so we don't lose any increments ! 1080: if the libcall is cse'd or moved. */ ! 1081: emit_library_call (unoptab->handlers[(int) mode].libfunc, ! 1082: 1, mode, 1, op0, mode); ! 1083: insns = get_insns (); ! 1084: end_sequence (); ! 1085: ! 1086: target = gen_reg_rtx (mode); ! 1087: emit_libcall_block (insns, target, hard_libcall_value (mode), ! 1088: gen_rtx (unoptab->code, mode, op0)); ! 1089: ! 1090: return target; ! 1091: } ! 1092: ! 1093: /* It can't be done in this mode. Can we do it in a wider mode? */ ! 1094: ! 1095: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) ! 1096: { ! 1097: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; ! 1098: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) ! 1099: { ! 1100: if ((unoptab->handlers[(int) wider_mode].insn_code ! 1101: != CODE_FOR_nothing) ! 1102: || unoptab->handlers[(int) wider_mode].libfunc) ! 1103: { ! 1104: rtx xop0 = op0; ! 1105: ! 1106: /* For certain operations, we need not actually extend ! 1107: the narrow operand, as long as we will truncate the ! 1108: results to the same narrowness. */ ! 1109: ! 1110: if ((unoptab == neg_optab || unoptab == one_cmpl_optab) ! 1111: && class == MODE_INT) ! 1112: xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0); ! 1113: else ! 1114: xop0 = convert_to_mode (wider_mode, xop0, unsignedp); ! 1115: ! 1116: temp = expand_unop (wider_mode, unoptab, xop0, 0, unsignedp); ! 1117: ! 1118: if (temp) ! 1119: { ! 1120: if (class != MODE_INT) ! 1121: { ! 1122: if (target == 0) ! 1123: target = gen_reg_rtx (mode); ! 1124: convert_move (target, temp, 0); ! 1125: return target; ! 1126: } ! 1127: else ! 1128: return gen_lowpart (mode, temp); ! 1129: } ! 1130: else ! 1131: delete_insns_since (last); ! 1132: } ! 1133: } ! 1134: } ! 1135: ! 1136: return 0; ! 1137: } ! 1138: ! 1139: /* Generate an instruction whose insn-code is INSN_CODE, ! 1140: with two operands: an output TARGET and an input OP0. ! 1141: TARGET *must* be nonzero, and the output is always stored there. ! 1142: CODE is an rtx code such that (CODE OP0) is an rtx that describes ! 1143: the value that is stored into TARGET. */ ! 1144: ! 1145: void ! 1146: emit_unop_insn (icode, target, op0, code) ! 1147: int icode; ! 1148: rtx target; ! 1149: rtx op0; ! 1150: enum rtx_code code; ! 1151: { ! 1152: register rtx temp; ! 1153: enum machine_mode mode0 = insn_operand_mode[icode][1]; ! 1154: rtx pat; ! 1155: ! 1156: temp = target = protect_from_queue (target, 1); ! 1157: ! 1158: op0 = protect_from_queue (op0, 0); ! 1159: ! 1160: if (flag_force_mem) ! 1161: op0 = force_not_mem (op0); ! 1162: ! 1163: /* Now, if insn does not accept our operands, put them into pseudos. */ ! 1164: ! 1165: if (! (*insn_operand_predicate[icode][1]) (op0, mode0)) ! 1166: op0 = copy_to_mode_reg (mode0, op0); ! 1167: ! 1168: if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp)) ! 1169: || (flag_force_mem && GET_CODE (temp) == MEM)) ! 1170: temp = gen_reg_rtx (GET_MODE (temp)); ! 1171: ! 1172: pat = GEN_FCN (icode) (temp, op0); ! 1173: ! 1174: if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN) ! 1175: add_equal_note (pat, temp, code, op0, 0); ! 1176: ! 1177: emit_insn (pat); ! 1178: ! 1179: if (temp != target) ! 1180: emit_move_insn (target, temp); ! 1181: } ! 1182: ! 1183: /* Emit code to perform a series of operations on a multi-word quantity, one ! 1184: word at a time. ! 1185: ! 1186: Such a block is preceeded by a CLOBBER of the output, consists of multiple ! 1187: insns, each setting one word of the output, and followed by a SET copying ! 1188: the output to itself. ! 1189: ! 1190: Each of the insns setting words of the output receives a REG_NO_CONFLICT ! 1191: note indicating that it doesn't conflict with the (also multi-word) ! 1192: inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL ! 1193: notes. ! 1194: ! 1195: INSNS is a block of code generated to perform the operation, not including ! 1196: the CLOBBER and final copy. All insns that compute intermediate values ! 1197: are first emitted, followed by the block as described above. Only ! 1198: INSNs are allowed in the block; no library calls or jumps may be ! 1199: present. ! 1200: ! 1201: TARGET, OP0, and OP1 are the output and inputs of the operations, ! 1202: respectively. OP1 may be zero for a unary operation. ! 1203: ! 1204: EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note ! 1205: on the last insn. ! 1206: ! 1207: If TARGET is not a register, INSNS is simply emitted with no special ! 1208: processing. ! 1209: ! 1210: The final insn emitted is returned. */ ! 1211: ! 1212: rtx ! 1213: emit_no_conflict_block (insns, target, op0, op1, equiv) ! 1214: rtx insns; ! 1215: rtx target; ! 1216: rtx op0, op1; ! 1217: rtx equiv; ! 1218: { ! 1219: rtx prev, next, first, last, insn; ! 1220: ! 1221: if (GET_CODE (target) != REG || reload_in_progress) ! 1222: return emit_insns (insns); ! 1223: ! 1224: /* First emit all insns that do not store into words of the output and remove ! 1225: these from the list. */ ! 1226: for (insn = insns; insn; insn = next) ! 1227: { ! 1228: rtx set = 0; ! 1229: int i; ! 1230: ! 1231: next = NEXT_INSN (insn); ! 1232: ! 1233: if (GET_CODE (insn) != INSN) ! 1234: abort (); ! 1235: ! 1236: if (GET_CODE (PATTERN (insn)) == SET) ! 1237: set = PATTERN (insn); ! 1238: else if (GET_CODE (PATTERN (insn)) == PARALLEL) ! 1239: { ! 1240: for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) ! 1241: if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET) ! 1242: { ! 1243: set = XVECEXP (PATTERN (insn), 0, i); ! 1244: break; ! 1245: } ! 1246: } ! 1247: ! 1248: if (set == 0) ! 1249: abort (); ! 1250: ! 1251: if (! reg_overlap_mentioned_p (target, SET_DEST (set))) ! 1252: { ! 1253: if (PREV_INSN (insn)) ! 1254: NEXT_INSN (PREV_INSN (insn)) = next; ! 1255: else ! 1256: insns = next; ! 1257: ! 1258: if (next) ! 1259: PREV_INSN (next) = PREV_INSN (insn); ! 1260: ! 1261: add_insn (insn); ! 1262: } ! 1263: } ! 1264: ! 1265: prev = get_last_insn (); ! 1266: ! 1267: /* Now write the CLOBBER of the output, followed by the setting of each ! 1268: of the words, followed by the final copy. */ ! 1269: if (target != op0 && target != op1) ! 1270: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); ! 1271: ! 1272: for (insn = insns; insn; insn = next) ! 1273: { ! 1274: next = NEXT_INSN (insn); ! 1275: add_insn (insn); ! 1276: ! 1277: if (op1 && GET_CODE (op1) == REG) ! 1278: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op1, ! 1279: REG_NOTES (insn)); ! 1280: ! 1281: if (op0 && GET_CODE (op0) == REG) ! 1282: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op0, ! 1283: REG_NOTES (insn)); ! 1284: } ! 1285: ! 1286: last = emit_move_insn (target, target); ! 1287: if (equiv) ! 1288: REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last)); ! 1289: ! 1290: if (prev == 0) ! 1291: first = get_insns (); ! 1292: else ! 1293: first = NEXT_INSN (prev); ! 1294: ! 1295: /* Encapsulate the block so it gets manipulated as a unit. */ ! 1296: REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last, ! 1297: REG_NOTES (first)); ! 1298: REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last)); ! 1299: ! 1300: return last; ! 1301: } ! 1302: ! 1303: /* Emit code to make a call to a constant function or a library call. ! 1304: ! 1305: INSNS is a list containing all insns emitted in the call. ! 1306: These insns leave the result in RESULT. Our block is to copy RESULT ! 1307: to TARGET, which is logically equivalent to EQUIV. ! 1308: ! 1309: We first emit any insns that set a pseudo on the assumption that these are ! 1310: loading constants into registers; doing so allows them to be safely cse'ed ! 1311: between blocks. Then we emit all the other insns in the block, followed by ! 1312: an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL ! 1313: note with an operand of EQUIV. ! 1314: ! 1315: Except for the first group of insns (the ones setting pseudos), the ! 1316: block is delimited by REG_RETVAL and REG_LIBCALL notes. */ ! 1317: ! 1318: void ! 1319: emit_libcall_block (insns, target, result, equiv) ! 1320: rtx insns; ! 1321: rtx target; ! 1322: rtx result; ! 1323: rtx equiv; ! 1324: { ! 1325: rtx prev, next, first, last, insn; ! 1326: ! 1327: /* First emit all insns that set pseudos. Remove them from the list as ! 1328: we go. */ ! 1329: ! 1330: for (insn = insns; insn; insn = next) ! 1331: { ! 1332: rtx set = single_set (insn); ! 1333: ! 1334: next = NEXT_INSN (insn); ! 1335: ! 1336: if (set != 0 && GET_CODE (SET_DEST (set)) == REG ! 1337: && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER) ! 1338: { ! 1339: if (PREV_INSN (insn)) ! 1340: NEXT_INSN (PREV_INSN (insn)) = next; ! 1341: else ! 1342: insns = next; ! 1343: ! 1344: if (next) ! 1345: PREV_INSN (next) = PREV_INSN (insn); ! 1346: ! 1347: add_insn (insn); ! 1348: } ! 1349: } ! 1350: ! 1351: prev = get_last_insn (); ! 1352: ! 1353: /* Write the remaining insns followed by the final copy. */ ! 1354: ! 1355: for (insn = insns; insn; insn = next) ! 1356: { ! 1357: next = NEXT_INSN (insn); ! 1358: ! 1359: add_insn (insn); ! 1360: } ! 1361: ! 1362: last = emit_move_insn (target, result); ! 1363: REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last)); ! 1364: ! 1365: if (prev == 0) ! 1366: first = get_insns (); ! 1367: else ! 1368: first = NEXT_INSN (prev); ! 1369: ! 1370: /* Encapsulate the block so it gets manipulated as a unit. */ ! 1371: REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last, ! 1372: REG_NOTES (first)); ! 1373: REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last)); ! 1374: } ! 1375: ! 1376: /* Generate code to store zero in X. */ ! 1377: ! 1378: void ! 1379: emit_clr_insn (x) ! 1380: rtx x; ! 1381: { ! 1382: emit_move_insn (x, const0_rtx); ! 1383: } ! 1384: ! 1385: /* Generate code to store 1 in X ! 1386: assuming it contains zero beforehand. */ ! 1387: ! 1388: void ! 1389: emit_0_to_1_insn (x) ! 1390: rtx x; ! 1391: { ! 1392: emit_move_insn (x, const1_rtx); ! 1393: } ! 1394: ! 1395: /* Generate code to compare X with Y ! 1396: so that the condition codes are set. ! 1397: ! 1398: MODE is the mode of the inputs (in case they are const_int). ! 1399: UNSIGNEDP nonzero says that X and Y are unsigned; ! 1400: this matters if they need to be widened. ! 1401: ! 1402: If they have mode BLKmode, then SIZE specifies the size of both X and Y, ! 1403: and ALIGN specifies the known shared alignment of X and Y. ! 1404: ! 1405: COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). ! 1406: It is ignored for fixed-point and block comparisons; ! 1407: it is used only for floating-point comparisons. */ ! 1408: ! 1409: void ! 1410: emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align) ! 1411: rtx x, y; ! 1412: enum rtx_code comparison; ! 1413: rtx size; ! 1414: int unsignedp; ! 1415: int align; ! 1416: { ! 1417: enum mode_class class; ! 1418: enum machine_mode wider_mode; ! 1419: ! 1420: class = GET_MODE_CLASS (mode); ! 1421: ! 1422: /* They could both be VOIDmode if both args are immediate constants, ! 1423: but we should fold that at an earlier stage. ! 1424: With no special code here, this will call abort, ! 1425: reminding the programmer to implement such folding. */ ! 1426: ! 1427: if (mode != BLKmode && flag_force_mem) ! 1428: { ! 1429: x = force_not_mem (x); ! 1430: y = force_not_mem (y); ! 1431: } ! 1432: ! 1433: /* If we are inside an appropriately-short loop and one operand is an ! 1434: expensive constant, force it into a register. */ ! 1435: if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x) > 2) ! 1436: x = force_reg (mode, x); ! 1437: ! 1438: if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y) > 2) ! 1439: y = force_reg (mode, y); ! 1440: ! 1441: /* Don't let both operands fail to indicate the mode. */ ! 1442: if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode) ! 1443: x = force_reg (mode, x); ! 1444: ! 1445: /* Handle all BLKmode compares. */ ! 1446: ! 1447: if (mode == BLKmode) ! 1448: { ! 1449: emit_queue (); ! 1450: x = protect_from_queue (x, 0); ! 1451: y = protect_from_queue (y, 0); ! 1452: ! 1453: if (size == 0) ! 1454: abort (); ! 1455: #ifdef HAVE_cmpstrqi ! 1456: if (HAVE_cmpstrqi ! 1457: && GET_CODE (size) == CONST_INT ! 1458: && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode))) ! 1459: { ! 1460: enum machine_mode result_mode ! 1461: = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0]; ! 1462: rtx result = gen_reg_rtx (result_mode); ! 1463: emit_insn (gen_cmpstrqi (result, x, y, size, ! 1464: gen_rtx (CONST_INT, VOIDmode, align))); ! 1465: emit_cmp_insn (result, const0_rtx, comparison, 0, result_mode, 0, 0); ! 1466: } ! 1467: else ! 1468: #endif ! 1469: #ifdef HAVE_cmpstrhi ! 1470: if (HAVE_cmpstrhi ! 1471: && GET_CODE (size) == CONST_INT ! 1472: && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode))) ! 1473: { ! 1474: enum machine_mode result_mode ! 1475: = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0]; ! 1476: rtx result = gen_reg_rtx (result_mode); ! 1477: emit_insn (gen_cmpstrhi (result, x, y, size, ! 1478: gen_rtx (CONST_INT, VOIDmode, align))); ! 1479: emit_cmp_insn (result, const0_rtx, comparison, 0, result_mode, 0, 0); ! 1480: } ! 1481: else ! 1482: #endif ! 1483: #ifdef HAVE_cmpstrsi ! 1484: if (HAVE_cmpstrsi) ! 1485: { ! 1486: enum machine_mode result_mode ! 1487: = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0]; ! 1488: rtx result = gen_reg_rtx (result_mode); ! 1489: emit_insn (gen_cmpstrsi (result, x, y, ! 1490: convert_to_mode (SImode, size, 1), ! 1491: gen_rtx (CONST_INT, VOIDmode, align))); ! 1492: emit_cmp_insn (result, const0_rtx, comparison, 0, result_mode, 0, 0); ! 1493: } ! 1494: else ! 1495: #endif ! 1496: { ! 1497: #ifdef TARGET_MEM_FUNCTIONS ! 1498: emit_library_call (memcmp_libfunc, 0, ! 1499: TYPE_MODE (integer_type_node), 3, ! 1500: XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, ! 1501: size, Pmode); ! 1502: #else ! 1503: emit_library_call (bcmp_libfunc, 0, ! 1504: TYPE_MODE (integer_type_node), 3, ! 1505: XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, ! 1506: size, Pmode); ! 1507: #endif ! 1508: emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)), ! 1509: const0_rtx, comparison, 0, ! 1510: TYPE_MODE (integer_type_node), 0, 0); ! 1511: } ! 1512: return; ! 1513: } ! 1514: ! 1515: /* Handle some compares against zero. */ ! 1516: ! 1517: if (y == CONST0_RTX (mode) ! 1518: && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 1519: { ! 1520: int icode = (int) tst_optab->handlers[(int) mode].insn_code; ! 1521: ! 1522: emit_queue (); ! 1523: x = protect_from_queue (x, 0); ! 1524: y = protect_from_queue (y, 0); ! 1525: ! 1526: /* Now, if insn does accept these operands, put them into pseudos. */ ! 1527: if (! (*insn_operand_predicate[icode][0]) ! 1528: (x, insn_operand_mode[icode][0])) ! 1529: x = copy_to_mode_reg (insn_operand_mode[icode][0], x); ! 1530: ! 1531: emit_insn (GEN_FCN (icode) (x)); ! 1532: return; ! 1533: } ! 1534: ! 1535: /* Handle compares for which there is a directly suitable insn. */ ! 1536: ! 1537: if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) ! 1538: { ! 1539: int icode = (int) cmp_optab->handlers[(int) mode].insn_code; ! 1540: ! 1541: emit_queue (); ! 1542: x = protect_from_queue (x, 0); ! 1543: y = protect_from_queue (y, 0); ! 1544: ! 1545: /* Now, if insn doesn't accept these operands, put them into pseudos. */ ! 1546: if (! (*insn_operand_predicate[icode][0]) ! 1547: (x, insn_operand_mode[icode][0])) ! 1548: x = copy_to_mode_reg (insn_operand_mode[icode][0], x); ! 1549: ! 1550: if (! (*insn_operand_predicate[icode][1]) ! 1551: (y, insn_operand_mode[icode][1])) ! 1552: y = copy_to_mode_reg (insn_operand_mode[icode][1], y); ! 1553: ! 1554: emit_insn (GEN_FCN (icode) (x, y)); ! 1555: return; ! 1556: } ! 1557: ! 1558: /* Try widening if we can find a direct insn that way. */ ! 1559: ! 1560: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) ! 1561: { ! 1562: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; ! 1563: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) ! 1564: { ! 1565: if (cmp_optab->handlers[(int) wider_mode].insn_code ! 1566: != CODE_FOR_nothing) ! 1567: { ! 1568: x = convert_to_mode (wider_mode, x, unsignedp); ! 1569: y = convert_to_mode (wider_mode, y, unsignedp); ! 1570: emit_cmp_insn (x, y, comparison, 0, ! 1571: wider_mode, unsignedp, align); ! 1572: return; ! 1573: } ! 1574: } ! 1575: } ! 1576: ! 1577: /* Handle a lib call just for the mode we are using. */ ! 1578: ! 1579: if (cmp_optab->handlers[(int) mode].libfunc ! 1580: && class != MODE_FLOAT) ! 1581: { ! 1582: rtx libfunc = cmp_optab->handlers[(int) mode].libfunc; ! 1583: /* If we want unsigned, and this mode has a distinct unsigned ! 1584: comparison routine, use that. */ ! 1585: if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc) ! 1586: libfunc = ucmp_optab->handlers[(int) mode].libfunc; ! 1587: ! 1588: emit_library_call (libfunc, 0, ! 1589: SImode, 2, x, mode, y, mode); ! 1590: ! 1591: /* Integer comparison returns a result that must be compared against 1, ! 1592: so that even if we do an unsigned compare afterward, ! 1593: there is still a value that can represent the result "less than". */ ! 1594: ! 1595: emit_cmp_insn (hard_libcall_value (SImode), const1_rtx, ! 1596: comparison, 0, SImode, unsignedp, 0); ! 1597: return; ! 1598: } ! 1599: ! 1600: if (class == MODE_FLOAT) ! 1601: emit_float_lib_cmp (x, y, comparison); ! 1602: ! 1603: else ! 1604: abort (); ! 1605: } ! 1606: ! 1607: /* Nonzero if a compare of mode MODE can be done straightforwardly ! 1608: (without splitting it into pieces). */ ! 1609: ! 1610: int ! 1611: can_compare_p (mode) ! 1612: enum machine_mode mode; ! 1613: { ! 1614: do ! 1615: { ! 1616: if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing) ! 1617: return 1; ! 1618: mode = GET_MODE_WIDER_MODE (mode); ! 1619: } while (mode != VOIDmode); ! 1620: ! 1621: return 0; ! 1622: } ! 1623: ! 1624: /* Emit a library call comparison between floating point X and Y. ! 1625: COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */ ! 1626: ! 1627: static void ! 1628: emit_float_lib_cmp (x, y, comparison) ! 1629: rtx x, y; ! 1630: enum rtx_code comparison; ! 1631: { ! 1632: enum machine_mode mode = GET_MODE (x); ! 1633: rtx libfunc; ! 1634: ! 1635: if (mode == SFmode) ! 1636: switch (comparison) ! 1637: { ! 1638: case EQ: ! 1639: libfunc = eqsf2_libfunc; ! 1640: break; ! 1641: ! 1642: case NE: ! 1643: libfunc = nesf2_libfunc; ! 1644: break; ! 1645: ! 1646: case GT: ! 1647: libfunc = gtsf2_libfunc; ! 1648: break; ! 1649: ! 1650: case GE: ! 1651: libfunc = gesf2_libfunc; ! 1652: break; ! 1653: ! 1654: case LT: ! 1655: libfunc = ltsf2_libfunc; ! 1656: break; ! 1657: ! 1658: case LE: ! 1659: libfunc = lesf2_libfunc; ! 1660: break; ! 1661: } ! 1662: else if (mode == DFmode) ! 1663: switch (comparison) ! 1664: { ! 1665: case EQ: ! 1666: libfunc = eqdf2_libfunc; ! 1667: break; ! 1668: ! 1669: case NE: ! 1670: libfunc = nedf2_libfunc; ! 1671: break; ! 1672: ! 1673: case GT: ! 1674: libfunc = gtdf2_libfunc; ! 1675: break; ! 1676: ! 1677: case GE: ! 1678: libfunc = gedf2_libfunc; ! 1679: break; ! 1680: ! 1681: case LT: ! 1682: libfunc = ltdf2_libfunc; ! 1683: break; ! 1684: ! 1685: case LE: ! 1686: libfunc = ledf2_libfunc; ! 1687: break; ! 1688: } ! 1689: else ! 1690: { ! 1691: enum machine_mode wider_mode; ! 1692: ! 1693: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; ! 1694: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) ! 1695: { ! 1696: if ((cmp_optab->handlers[(int) wider_mode].insn_code ! 1697: != CODE_FOR_nothing) ! 1698: || (cmp_optab->handlers[(int) wider_mode].libfunc != 0)) ! 1699: { ! 1700: x = convert_to_mode (wider_mode, x, 0); ! 1701: y = convert_to_mode (wider_mode, y, 0); ! 1702: emit_float_lib_cmp (x, y, comparison); ! 1703: return; ! 1704: } ! 1705: } ! 1706: abort (); ! 1707: } ! 1708: ! 1709: emit_library_call (libfunc, 0, ! 1710: SImode, 2, x, mode, y, mode); ! 1711: ! 1712: emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, comparison, ! 1713: 0, SImode, 0, 0); ! 1714: } ! 1715: ! 1716: /* Generate code to indirectly jump to a location given in the rtx LOC. */ ! 1717: ! 1718: void ! 1719: emit_indirect_jump (loc) ! 1720: rtx loc; ! 1721: { ! 1722: if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0]) ! 1723: (loc, VOIDmode))) ! 1724: loc = copy_to_mode_reg (insn_operand_mode[(int)CODE_FOR_indirect_jump][0], ! 1725: loc); ! 1726: ! 1727: emit_jump_insn (gen_indirect_jump (loc)); ! 1728: } ! 1729: ! 1730: /* These three functions generate an insn body and return it ! 1731: rather than emitting the insn. ! 1732: ! 1733: They do not protect from queued increments, ! 1734: because they may be used 1) in protect_from_queue itself ! 1735: and 2) in other passes where there is no queue. */ ! 1736: ! 1737: /* Generate and return an insn body to add Y to X. */ ! 1738: ! 1739: rtx ! 1740: gen_add2_insn (x, y) ! 1741: rtx x, y; ! 1742: { ! 1743: int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; ! 1744: ! 1745: if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0]) ! 1746: || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1]) ! 1747: || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2])) ! 1748: abort (); ! 1749: ! 1750: return (GEN_FCN (icode) (x, x, y)); ! 1751: } ! 1752: ! 1753: int ! 1754: have_add2_insn (mode) ! 1755: enum machine_mode mode; ! 1756: { ! 1757: return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; ! 1758: } ! 1759: ! 1760: /* Generate and return an insn body to subtract Y from X. */ ! 1761: ! 1762: rtx ! 1763: gen_sub2_insn (x, y) ! 1764: rtx x, y; ! 1765: { ! 1766: int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; ! 1767: ! 1768: if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0]) ! 1769: || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1]) ! 1770: || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2])) ! 1771: abort (); ! 1772: ! 1773: return (GEN_FCN (icode) (x, x, y)); ! 1774: } ! 1775: ! 1776: int ! 1777: have_sub2_insn (mode) ! 1778: enum machine_mode mode; ! 1779: { ! 1780: return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; ! 1781: } ! 1782: ! 1783: /* Generate the body of an instruction to copy Y into X. */ ! 1784: ! 1785: rtx ! 1786: gen_move_insn (x, y) ! 1787: rtx x, y; ! 1788: { ! 1789: register enum machine_mode mode = GET_MODE (x); ! 1790: enum insn_code insn_code; ! 1791: ! 1792: if (mode == VOIDmode) ! 1793: mode = GET_MODE (y); ! 1794: ! 1795: insn_code = mov_optab->handlers[(int) mode].insn_code; ! 1796: ! 1797: /* Handle MODE_CC modes: If we don't have a special move insn for this mode, ! 1798: find a mode to do it in. If we have a movcc, use it. Otherwise, ! 1799: find the MODE_INT mode of the same width. */ ! 1800: ! 1801: if (insn_code == CODE_FOR_nothing) ! 1802: { ! 1803: enum machine_mode tmode = VOIDmode; ! 1804: rtx x1 = x, y1 = y; ! 1805: ! 1806: if (GET_MODE_CLASS (mode) == MODE_CC && mode != CCmode ! 1807: && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing) ! 1808: tmode = CCmode; ! 1809: else if (GET_MODE_CLASS (mode) == MODE_CC) ! 1810: for (tmode = QImode; tmode != VOIDmode; ! 1811: tmode = GET_MODE_WIDER_MODE (tmode)) ! 1812: if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode)) ! 1813: break; ! 1814: ! 1815: if (tmode == VOIDmode) ! 1816: abort (); ! 1817: ! 1818: /* Get X and Y in TMODE. We can't use gen_lowpart here because it ! 1819: may call change_address which is not appropriate if we were ! 1820: called when a reload was in progress. We don't have to worry ! 1821: about changing the address since the size in bytes is supposed to ! 1822: be the same. Copy the MEM to change the mode and move any ! 1823: substitutions from the old MEM to the new one. */ ! 1824: ! 1825: if (reload_in_progress) ! 1826: { ! 1827: x = gen_lowpart_common (tmode, x1); ! 1828: if (x == 0 && GET_CODE (x1) == MEM) ! 1829: { ! 1830: x = gen_rtx (MEM, tmode, XEXP (x1, 0)); ! 1831: RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1); ! 1832: MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1); ! 1833: MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1); ! 1834: copy_replacements (x1, x); ! 1835: } ! 1836: ! 1837: y = gen_lowpart_common (tmode, y1); ! 1838: if (y == 0 && GET_CODE (y1) == MEM) ! 1839: { ! 1840: y = gen_rtx (MEM, tmode, XEXP (y1, 0)); ! 1841: RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1); ! 1842: MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1); ! 1843: MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1); ! 1844: copy_replacements (y1, y); ! 1845: } ! 1846: } ! 1847: else ! 1848: { ! 1849: x = gen_lowpart (tmode, x); ! 1850: y = gen_lowpart (tmode, y); ! 1851: } ! 1852: ! 1853: insn_code = mov_optab->handlers[(int) tmode].insn_code; ! 1854: } ! 1855: ! 1856: return (GEN_FCN (insn_code) (x, y)); ! 1857: } ! 1858: ! 1859: /* Tables of patterns for extending one integer mode to another. */ ! 1860: static enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2]; ! 1861: ! 1862: /* Return the insn code used to extend FROM_MODE to TO_MODE. ! 1863: UNSIGNEDP specifies zero-extension instead of sign-extension. If ! 1864: no such operation exists, CODE_FOR_nothing will be returned. */ ! 1865: ! 1866: enum insn_code ! 1867: can_extend_p (to_mode, from_mode, unsignedp) ! 1868: enum machine_mode to_mode, from_mode; ! 1869: int unsignedp; ! 1870: { ! 1871: return extendtab[(int) to_mode][(int) from_mode][unsignedp]; ! 1872: } ! 1873: ! 1874: /* Generate the body of an insn to extend Y (with mode MFROM) ! 1875: into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */ ! 1876: ! 1877: rtx ! 1878: gen_extend_insn (x, y, mto, mfrom, unsignedp) ! 1879: rtx x, y; ! 1880: enum machine_mode mto, mfrom; ! 1881: int unsignedp; ! 1882: { ! 1883: return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y)); ! 1884: } ! 1885: ! 1886: static void ! 1887: init_extends () ! 1888: { ! 1889: enum insn_code *p; ! 1890: ! 1891: for (p = extendtab[0][0]; ! 1892: p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0]; ! 1893: p++) ! 1894: *p = CODE_FOR_nothing; ! 1895: ! 1896: #ifdef HAVE_extendditi2 ! 1897: if (HAVE_extendditi2) ! 1898: extendtab[(int) TImode][(int) DImode][0] = CODE_FOR_extendditi2; ! 1899: #endif ! 1900: #ifdef HAVE_extendsiti2 ! 1901: if (HAVE_extendsiti2) ! 1902: extendtab[(int) TImode][(int) SImode][0] = CODE_FOR_extendsiti2; ! 1903: #endif ! 1904: #ifdef HAVE_extendhiti2 ! 1905: if (HAVE_extendhiti2) ! 1906: extendtab[(int) TImode][(int) HImode][0] = CODE_FOR_extendhiti2; ! 1907: #endif ! 1908: #ifdef HAVE_extendqiti2 ! 1909: if (HAVE_extendqiti2) ! 1910: extendtab[(int) TImode][(int) QImode][0] = CODE_FOR_extendqiti2; ! 1911: #endif ! 1912: #ifdef HAVE_extendsidi2 ! 1913: if (HAVE_extendsidi2) ! 1914: extendtab[(int) DImode][(int) SImode][0] = CODE_FOR_extendsidi2; ! 1915: #endif ! 1916: #ifdef HAVE_extendhidi2 ! 1917: if (HAVE_extendhidi2) ! 1918: extendtab[(int) DImode][(int) HImode][0] = CODE_FOR_extendhidi2; ! 1919: #endif ! 1920: #ifdef HAVE_extendqidi2 ! 1921: if (HAVE_extendqidi2) ! 1922: extendtab[(int) DImode][(int) QImode][0] = CODE_FOR_extendqidi2; ! 1923: #endif ! 1924: #ifdef HAVE_extendhisi2 ! 1925: if (HAVE_extendhisi2) ! 1926: extendtab[(int) SImode][(int) HImode][0] = CODE_FOR_extendhisi2; ! 1927: #endif ! 1928: #ifdef HAVE_extendqisi2 ! 1929: if (HAVE_extendqisi2) ! 1930: extendtab[(int) SImode][(int) QImode][0] = CODE_FOR_extendqisi2; ! 1931: #endif ! 1932: #ifdef HAVE_extendqihi2 ! 1933: if (HAVE_extendqihi2) ! 1934: extendtab[(int) HImode][(int) QImode][0] = CODE_FOR_extendqihi2; ! 1935: #endif ! 1936: ! 1937: #ifdef HAVE_zero_extendditi2 ! 1938: if (HAVE_zero_extendsiti2) ! 1939: extendtab[(int) TImode][(int) DImode][1] = CODE_FOR_zero_extendditi2; ! 1940: #endif ! 1941: #ifdef HAVE_zero_extendsiti2 ! 1942: if (HAVE_zero_extendsiti2) ! 1943: extendtab[(int) TImode][(int) SImode][1] = CODE_FOR_zero_extendsiti2; ! 1944: #endif ! 1945: #ifdef HAVE_zero_extendhiti2 ! 1946: if (HAVE_zero_extendhiti2) ! 1947: extendtab[(int) TImode][(int) HImode][1] = CODE_FOR_zero_extendhiti2; ! 1948: #endif ! 1949: #ifdef HAVE_zero_extendqiti2 ! 1950: if (HAVE_zero_extendqiti2) ! 1951: extendtab[(int) TImode][(int) QImode][1] = CODE_FOR_zero_extendqiti2; ! 1952: #endif ! 1953: #ifdef HAVE_zero_extendsidi2 ! 1954: if (HAVE_zero_extendsidi2) ! 1955: extendtab[(int) DImode][(int) SImode][1] = CODE_FOR_zero_extendsidi2; ! 1956: #endif ! 1957: #ifdef HAVE_zero_extendhidi2 ! 1958: if (HAVE_zero_extendhidi2) ! 1959: extendtab[(int) DImode][(int) HImode][1] = CODE_FOR_zero_extendhidi2; ! 1960: #endif ! 1961: #ifdef HAVE_zero_extendqidi2 ! 1962: if (HAVE_zero_extendqidi2) ! 1963: extendtab[(int) DImode][(int) QImode][1] = CODE_FOR_zero_extendqidi2; ! 1964: #endif ! 1965: #ifdef HAVE_zero_extendhisi2 ! 1966: if (HAVE_zero_extendhisi2) ! 1967: extendtab[(int) SImode][(int) HImode][1] = CODE_FOR_zero_extendhisi2; ! 1968: #endif ! 1969: #ifdef HAVE_zero_extendqisi2 ! 1970: if (HAVE_zero_extendqisi2) ! 1971: extendtab[(int) SImode][(int) QImode][1] = CODE_FOR_zero_extendqisi2; ! 1972: #endif ! 1973: #ifdef HAVE_zero_extendqihi2 ! 1974: if (HAVE_zero_extendqihi2) ! 1975: extendtab[(int) HImode][(int) QImode][1] = CODE_FOR_zero_extendqihi2; ! 1976: #endif ! 1977: } ! 1978: ! 1979: /* can_fix_p and can_float_p say whether the target machine ! 1980: can directly convert a given fixed point type to ! 1981: a given floating point type, or vice versa. ! 1982: The returned value is the CODE_FOR_... value to use, ! 1983: or CODE_FOR_nothing if these modes cannot be directly converted. */ ! 1984: ! 1985: static enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; ! 1986: static enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; ! 1987: static enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; ! 1988: ! 1989: /* *TRUNCP_PTR is set to 1 if it is necessary to output ! 1990: an explicit FTRUNC insn before the fix insn; otherwise 0. */ ! 1991: ! 1992: static enum insn_code ! 1993: can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr) ! 1994: enum machine_mode fltmode, fixmode; ! 1995: int unsignedp; ! 1996: int *truncp_ptr; ! 1997: { ! 1998: *truncp_ptr = 0; ! 1999: if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing) ! 2000: return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp]; ! 2001: ! 2002: if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing) ! 2003: { ! 2004: *truncp_ptr = 1; ! 2005: return fixtab[(int) fltmode][(int) fixmode][unsignedp]; ! 2006: } ! 2007: return CODE_FOR_nothing; ! 2008: } ! 2009: ! 2010: static enum insn_code ! 2011: can_float_p (fltmode, fixmode, unsignedp) ! 2012: enum machine_mode fixmode, fltmode; ! 2013: int unsignedp; ! 2014: { ! 2015: return floattab[(int) fltmode][(int) fixmode][unsignedp]; ! 2016: } ! 2017: ! 2018: void ! 2019: init_fixtab () ! 2020: { ! 2021: enum insn_code *p; ! 2022: for (p = fixtab[0][0]; ! 2023: p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); ! 2024: p++) ! 2025: *p = CODE_FOR_nothing; ! 2026: for (p = fixtrunctab[0][0]; ! 2027: p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); ! 2028: p++) ! 2029: *p = CODE_FOR_nothing; ! 2030: ! 2031: #ifdef HAVE_fixsfqi2 ! 2032: if (HAVE_fixsfqi2) ! 2033: fixtab[(int) SFmode][(int) QImode][0] = CODE_FOR_fixsfqi2; ! 2034: #endif ! 2035: #ifdef HAVE_fixsfhi2 ! 2036: if (HAVE_fixsfhi2) ! 2037: fixtab[(int) SFmode][(int) HImode][0] = CODE_FOR_fixsfhi2; ! 2038: #endif ! 2039: #ifdef HAVE_fixsfsi2 ! 2040: if (HAVE_fixsfsi2) ! 2041: fixtab[(int) SFmode][(int) SImode][0] = CODE_FOR_fixsfsi2; ! 2042: #endif ! 2043: #ifdef HAVE_fixsfdi2 ! 2044: if (HAVE_fixsfdi2) ! 2045: fixtab[(int) SFmode][(int) DImode][0] = CODE_FOR_fixsfdi2; ! 2046: #endif ! 2047: ! 2048: #ifdef HAVE_fixdfqi2 ! 2049: if (HAVE_fixdfqi2) ! 2050: fixtab[(int) DFmode][(int) QImode][0] = CODE_FOR_fixdfqi2; ! 2051: #endif ! 2052: #ifdef HAVE_fixdfhi2 ! 2053: if (HAVE_fixdfhi2) ! 2054: fixtab[(int) DFmode][(int) HImode][0] = CODE_FOR_fixdfhi2; ! 2055: #endif ! 2056: #ifdef HAVE_fixdfsi2 ! 2057: if (HAVE_fixdfsi2) ! 2058: fixtab[(int) DFmode][(int) SImode][0] = CODE_FOR_fixdfsi2; ! 2059: #endif ! 2060: #ifdef HAVE_fixdfdi2 ! 2061: if (HAVE_fixdfdi2) ! 2062: fixtab[(int) DFmode][(int) DImode][0] = CODE_FOR_fixdfdi2; ! 2063: #endif ! 2064: #ifdef HAVE_fixdfti2 ! 2065: if (HAVE_fixdfti2) ! 2066: fixtab[(int) DFmode][(int) TImode][0] = CODE_FOR_fixdfti2; ! 2067: #endif ! 2068: ! 2069: #ifdef HAVE_fixtfqi2 ! 2070: if (HAVE_fixtfqi2) ! 2071: fixtab[(int) TFmode][(int) QImode][0] = CODE_FOR_fixtfqi2; ! 2072: #endif ! 2073: #ifdef HAVE_fixtfhi2 ! 2074: if (HAVE_fixtfhi2) ! 2075: fixtab[(int) TFmode][(int) HImode][0] = CODE_FOR_fixtfhi2; ! 2076: #endif ! 2077: #ifdef HAVE_fixtfsi2 ! 2078: if (HAVE_fixtfsi2) ! 2079: fixtab[(int) TFmode][(int) SImode][0] = CODE_FOR_fixtfsi2; ! 2080: #endif ! 2081: #ifdef HAVE_fixtfdi2 ! 2082: if (HAVE_fixtfdi2) ! 2083: fixtab[(int) TFmode][(int) DImode][0] = CODE_FOR_fixtfdi2; ! 2084: #endif ! 2085: #ifdef HAVE_fixtfti2 ! 2086: if (HAVE_fixtfti2) ! 2087: fixtab[(int) TFmode][(int) TImode][0] = CODE_FOR_fixtfti2; ! 2088: #endif ! 2089: ! 2090: #ifdef HAVE_fixunssfqi2 ! 2091: if (HAVE_fixunssfqi2) ! 2092: fixtab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixunssfqi2; ! 2093: #endif ! 2094: #ifdef HAVE_fixunssfhi2 ! 2095: if (HAVE_fixunssfhi2) ! 2096: fixtab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixunssfhi2; ! 2097: #endif ! 2098: #ifdef HAVE_fixunssfsi2 ! 2099: if (HAVE_fixunssfsi2) ! 2100: fixtab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixunssfsi2; ! 2101: #endif ! 2102: #ifdef HAVE_fixunssfdi2 ! 2103: if (HAVE_fixunssfdi2) ! 2104: fixtab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixunssfdi2; ! 2105: #endif ! 2106: ! 2107: #ifdef HAVE_fixunsdfqi2 ! 2108: if (HAVE_fixunsdfqi2) ! 2109: fixtab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixunsdfqi2; ! 2110: #endif ! 2111: #ifdef HAVE_fixunsdfhi2 ! 2112: if (HAVE_fixunsdfhi2) ! 2113: fixtab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixunsdfhi2; ! 2114: #endif ! 2115: #ifdef HAVE_fixunsdfsi2 ! 2116: if (HAVE_fixunsdfsi2) ! 2117: fixtab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixunsdfsi2; ! 2118: #endif ! 2119: #ifdef HAVE_fixunsdfdi2 ! 2120: if (HAVE_fixunsdfdi2) ! 2121: fixtab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixunsdfdi2; ! 2122: #endif ! 2123: #ifdef HAVE_fixunsdfti2 ! 2124: if (HAVE_fixunsdfti2) ! 2125: fixtab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixunsdfti2; ! 2126: #endif ! 2127: ! 2128: #ifdef HAVE_fixunstfqi2 ! 2129: if (HAVE_fixunstfqi2) ! 2130: fixtab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixunstfqi2; ! 2131: #endif ! 2132: #ifdef HAVE_fixunstfhi2 ! 2133: if (HAVE_fixunstfhi2) ! 2134: fixtab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixunstfhi2; ! 2135: #endif ! 2136: #ifdef HAVE_fixunstfsi2 ! 2137: if (HAVE_fixunstfsi2) ! 2138: fixtab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixunstfsi2; ! 2139: #endif ! 2140: #ifdef HAVE_fixunstfdi2 ! 2141: if (HAVE_fixunstfdi2) ! 2142: fixtab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixunstfdi2; ! 2143: #endif ! 2144: #ifdef HAVE_fixunstfti2 ! 2145: if (HAVE_fixunstfti2) ! 2146: fixtab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixunstfti2; ! 2147: #endif ! 2148: ! 2149: #ifdef HAVE_fix_truncsfqi2 ! 2150: if (HAVE_fix_truncsfqi2) ! 2151: fixtrunctab[(int) SFmode][(int) QImode][0] = CODE_FOR_fix_truncsfqi2; ! 2152: #endif ! 2153: #ifdef HAVE_fix_truncsfhi2 ! 2154: if (HAVE_fix_truncsfhi2) ! 2155: fixtrunctab[(int) SFmode][(int) HImode][0] = CODE_FOR_fix_truncsfhi2; ! 2156: #endif ! 2157: #ifdef HAVE_fix_truncsfsi2 ! 2158: if (HAVE_fix_truncsfsi2) ! 2159: fixtrunctab[(int) SFmode][(int) SImode][0] = CODE_FOR_fix_truncsfsi2; ! 2160: #endif ! 2161: #ifdef HAVE_fix_truncsfdi2 ! 2162: if (HAVE_fix_truncsfdi2) ! 2163: fixtrunctab[(int) SFmode][(int) DImode][0] = CODE_FOR_fix_truncsfdi2; ! 2164: #endif ! 2165: ! 2166: #ifdef HAVE_fix_truncdfqi2 ! 2167: if (HAVE_fix_truncdfsi2) ! 2168: fixtrunctab[(int) DFmode][(int) QImode][0] = CODE_FOR_fix_truncdfqi2; ! 2169: #endif ! 2170: #ifdef HAVE_fix_truncdfhi2 ! 2171: if (HAVE_fix_truncdfhi2) ! 2172: fixtrunctab[(int) DFmode][(int) HImode][0] = CODE_FOR_fix_truncdfhi2; ! 2173: #endif ! 2174: #ifdef HAVE_fix_truncdfsi2 ! 2175: if (HAVE_fix_truncdfsi2) ! 2176: fixtrunctab[(int) DFmode][(int) SImode][0] = CODE_FOR_fix_truncdfsi2; ! 2177: #endif ! 2178: #ifdef HAVE_fix_truncdfdi2 ! 2179: if (HAVE_fix_truncdfdi2) ! 2180: fixtrunctab[(int) DFmode][(int) DImode][0] = CODE_FOR_fix_truncdfdi2; ! 2181: #endif ! 2182: #ifdef HAVE_fix_truncdfti2 ! 2183: if (HAVE_fix_truncdfti2) ! 2184: fixtrunctab[(int) DFmode][(int) TImode][0] = CODE_FOR_fix_truncdfti2; ! 2185: #endif ! 2186: ! 2187: #ifdef HAVE_fix_trunctfqi2 ! 2188: if (HAVE_fix_trunctfqi2) ! 2189: fixtrunctab[(int) TFmode][(int) QImode][0] = CODE_FOR_fix_trunctfqi2; ! 2190: #endif ! 2191: #ifdef HAVE_fix_trunctfhi2 ! 2192: if (HAVE_fix_trunctfhi2) ! 2193: fixtrunctab[(int) TFmode][(int) HImode][0] = CODE_FOR_fix_trunctfhi2; ! 2194: #endif ! 2195: #ifdef HAVE_fix_trunctfsi2 ! 2196: if (HAVE_fix_trunctfsi2) ! 2197: fixtrunctab[(int) TFmode][(int) SImode][0] = CODE_FOR_fix_trunctfsi2; ! 2198: #endif ! 2199: #ifdef HAVE_fix_trunctfdi2 ! 2200: if (HAVE_fix_trunctfdi2) ! 2201: fixtrunctab[(int) TFmode][(int) DImode][0] = CODE_FOR_fix_trunctfdi2; ! 2202: #endif ! 2203: #ifdef HAVE_fix_trunctfti2 ! 2204: if (HAVE_fix_trunctfti2) ! 2205: fixtrunctab[(int) TFmode][(int) TImode][0] = CODE_FOR_fix_trunctfti2; ! 2206: #endif ! 2207: ! 2208: #ifdef HAVE_fixuns_truncsfqi2 ! 2209: if (HAVE_fixuns_truncsfqi2) ! 2210: fixtrunctab[(int) SFmode][(int) QImode][1] = CODE_FOR_fixuns_truncsfqi2; ! 2211: #endif ! 2212: #ifdef HAVE_fixuns_truncsfhi2 ! 2213: if (HAVE_fixuns_truncsfhi2) ! 2214: fixtrunctab[(int) SFmode][(int) HImode][1] = CODE_FOR_fixuns_truncsfhi2; ! 2215: #endif ! 2216: #ifdef HAVE_fixuns_truncsfsi2 ! 2217: if (HAVE_fixuns_truncsfsi2) ! 2218: fixtrunctab[(int) SFmode][(int) SImode][1] = CODE_FOR_fixuns_truncsfsi2; ! 2219: #endif ! 2220: #ifdef HAVE_fixuns_truncsfdi2 ! 2221: if (HAVE_fixuns_truncsfdi2) ! 2222: fixtrunctab[(int) SFmode][(int) DImode][1] = CODE_FOR_fixuns_truncsfdi2; ! 2223: #endif ! 2224: ! 2225: #ifdef HAVE_fixuns_truncdfqi2 ! 2226: if (HAVE_fixuns_truncdfqi2) ! 2227: fixtrunctab[(int) DFmode][(int) QImode][1] = CODE_FOR_fixuns_truncdfqi2; ! 2228: #endif ! 2229: #ifdef HAVE_fixuns_truncdfhi2 ! 2230: if (HAVE_fixuns_truncdfhi2) ! 2231: fixtrunctab[(int) DFmode][(int) HImode][1] = CODE_FOR_fixuns_truncdfhi2; ! 2232: #endif ! 2233: #ifdef HAVE_fixuns_truncdfsi2 ! 2234: if (HAVE_fixuns_truncdfsi2) ! 2235: fixtrunctab[(int) DFmode][(int) SImode][1] = CODE_FOR_fixuns_truncdfsi2; ! 2236: #endif ! 2237: #ifdef HAVE_fixuns_truncdfdi2 ! 2238: if (HAVE_fixuns_truncdfdi2) ! 2239: fixtrunctab[(int) DFmode][(int) DImode][1] = CODE_FOR_fixuns_truncdfdi2; ! 2240: #endif ! 2241: #ifdef HAVE_fixuns_truncdfti2 ! 2242: if (HAVE_fixuns_truncdfti2) ! 2243: fixtrunctab[(int) DFmode][(int) TImode][1] = CODE_FOR_fixuns_truncdfti2; ! 2244: #endif ! 2245: ! 2246: #ifdef HAVE_fixuns_trunctfqi2 ! 2247: if (HAVE_fixuns_trunctfqi2) ! 2248: fixtrunctab[(int) TFmode][(int) QImode][1] = CODE_FOR_fixuns_trunctfqi2; ! 2249: #endif ! 2250: #ifdef HAVE_fixuns_trunctfhi2 ! 2251: if (HAVE_fixuns_trunctfhi2) ! 2252: fixtrunctab[(int) TFmode][(int) HImode][1] = CODE_FOR_fixuns_trunctfhi2; ! 2253: #endif ! 2254: #ifdef HAVE_fixuns_trunctfsi2 ! 2255: if (HAVE_fixuns_trunctfsi2) ! 2256: fixtrunctab[(int) TFmode][(int) SImode][1] = CODE_FOR_fixuns_trunctfsi2; ! 2257: #endif ! 2258: #ifdef HAVE_fixuns_trunctfdi2 ! 2259: if (HAVE_fixuns_trunctfdi2) ! 2260: fixtrunctab[(int) TFmode][(int) DImode][1] = CODE_FOR_fixuns_trunctfdi2; ! 2261: #endif ! 2262: #ifdef HAVE_fixuns_trunctfti2 ! 2263: if (HAVE_fixuns_trunctfti2) ! 2264: fixtrunctab[(int) TFmode][(int) TImode][1] = CODE_FOR_fixuns_trunctfti2; ! 2265: #endif ! 2266: ! 2267: #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC ! 2268: /* This flag says the same insns that convert to a signed fixnum ! 2269: also convert validly to an unsigned one. */ ! 2270: { ! 2271: int i; ! 2272: int j; ! 2273: for (i = 0; i < NUM_MACHINE_MODES; i++) ! 2274: for (j = 0; j < NUM_MACHINE_MODES; j++) ! 2275: fixtrunctab[i][j][1] = fixtrunctab[i][j][0]; ! 2276: } ! 2277: #endif ! 2278: } ! 2279: ! 2280: void ! 2281: init_floattab () ! 2282: { ! 2283: enum insn_code *p; ! 2284: for (p = floattab[0][0]; ! 2285: p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); ! 2286: p++) ! 2287: *p = CODE_FOR_nothing; ! 2288: ! 2289: #ifdef HAVE_floatqisf2 ! 2290: if (HAVE_floatqisf2) ! 2291: floattab[(int) SFmode][(int) QImode][0] = CODE_FOR_floatqisf2; ! 2292: #endif ! 2293: #ifdef HAVE_floathisf2 ! 2294: if (HAVE_floathisf2) ! 2295: floattab[(int) SFmode][(int) HImode][0] = CODE_FOR_floathisf2; ! 2296: #endif ! 2297: #ifdef HAVE_floatsisf2 ! 2298: if (HAVE_floatsisf2) ! 2299: floattab[(int) SFmode][(int) SImode][0] = CODE_FOR_floatsisf2; ! 2300: #endif ! 2301: #ifdef HAVE_floatdisf2 ! 2302: if (HAVE_floatdisf2) ! 2303: floattab[(int) SFmode][(int) DImode][0] = CODE_FOR_floatdisf2; ! 2304: #endif ! 2305: #ifdef HAVE_floattisf2 ! 2306: if (HAVE_floattisf2) ! 2307: floattab[(int) SFmode][(int) TImode][0] = CODE_FOR_floattisf2; ! 2308: #endif ! 2309: ! 2310: #ifdef HAVE_floatqidf2 ! 2311: if (HAVE_floatqidf2) ! 2312: floattab[(int) DFmode][(int) QImode][0] = CODE_FOR_floatqidf2; ! 2313: #endif ! 2314: #ifdef HAVE_floathidf2 ! 2315: if (HAVE_floathidf2) ! 2316: floattab[(int) DFmode][(int) HImode][0] = CODE_FOR_floathidf2; ! 2317: #endif ! 2318: #ifdef HAVE_floatsidf2 ! 2319: if (HAVE_floatsidf2) ! 2320: floattab[(int) DFmode][(int) SImode][0] = CODE_FOR_floatsidf2; ! 2321: #endif ! 2322: #ifdef HAVE_floatdidf2 ! 2323: if (HAVE_floatdidf2) ! 2324: floattab[(int) DFmode][(int) DImode][0] = CODE_FOR_floatdidf2; ! 2325: #endif ! 2326: #ifdef HAVE_floattidf2 ! 2327: if (HAVE_floattidf2) ! 2328: floattab[(int) DFmode][(int) TImode][0] = CODE_FOR_floattidf2; ! 2329: #endif ! 2330: ! 2331: #ifdef HAVE_floatqitf2 ! 2332: if (HAVE_floatqitf2) ! 2333: floattab[(int) TFmode][(int) QImode][0] = CODE_FOR_floatqitf2; ! 2334: #endif ! 2335: #ifdef HAVE_floathitf2 ! 2336: if (HAVE_floathitf2) ! 2337: floattab[(int) TFmode][(int) HImode][0] = CODE_FOR_floathitf2; ! 2338: #endif ! 2339: #ifdef HAVE_floatsitf2 ! 2340: if (HAVE_floatsitf2) ! 2341: floattab[(int) TFmode][(int) SImode][0] = CODE_FOR_floatsitf2; ! 2342: #endif ! 2343: #ifdef HAVE_floatditf2 ! 2344: if (HAVE_floatditf2) ! 2345: floattab[(int) TFmode][(int) DImode][0] = CODE_FOR_floatditf2; ! 2346: #endif ! 2347: #ifdef HAVE_floattitf2 ! 2348: if (HAVE_floattitf2) ! 2349: floattab[(int) TFmode][(int) TImode][0] = CODE_FOR_floattitf2; ! 2350: #endif ! 2351: ! 2352: #ifdef HAVE_floatunsqisf2 ! 2353: if (HAVE_floatunsqisf2) ! 2354: floattab[(int) SFmode][(int) QImode][1] = CODE_FOR_floatunsqisf2; ! 2355: #endif ! 2356: #ifdef HAVE_floatunshisf2 ! 2357: if (HAVE_floatunshisf2) ! 2358: floattab[(int) SFmode][(int) HImode][1] = CODE_FOR_floatunshisf2; ! 2359: #endif ! 2360: #ifdef HAVE_floatunssisf2 ! 2361: if (HAVE_floatunssisf2) ! 2362: floattab[(int) SFmode][(int) SImode][1] = CODE_FOR_floatunssisf2; ! 2363: #endif ! 2364: #ifdef HAVE_floatunsdisf2 ! 2365: if (HAVE_floatunsdisf2) ! 2366: floattab[(int) SFmode][(int) DImode][1] = CODE_FOR_floatunsdisf2; ! 2367: #endif ! 2368: #ifdef HAVE_floatunstisf2 ! 2369: if (HAVE_floatunstisf2) ! 2370: floattab[(int) SFmode][(int) TImode][1] = CODE_FOR_floatunstisf2; ! 2371: #endif ! 2372: ! 2373: #ifdef HAVE_floatunsqidf2 ! 2374: if (HAVE_floatunsqidf2) ! 2375: floattab[(int) DFmode][(int) QImode][1] = CODE_FOR_floatunsqidf2; ! 2376: #endif ! 2377: #ifdef HAVE_floatunshidf2 ! 2378: if (HAVE_floatunshidf2) ! 2379: floattab[(int) DFmode][(int) HImode][1] = CODE_FOR_floatunshidf2; ! 2380: #endif ! 2381: #ifdef HAVE_floatunssidf2 ! 2382: if (HAVE_floatunssidf2) ! 2383: floattab[(int) DFmode][(int) SImode][1] = CODE_FOR_floatunssidf2; ! 2384: #endif ! 2385: #ifdef HAVE_floatunsdidf2 ! 2386: if (HAVE_floatunsdidf2) ! 2387: floattab[(int) DFmode][(int) DImode][1] = CODE_FOR_floatunsdidf2; ! 2388: #endif ! 2389: #ifdef HAVE_floatunstidf2 ! 2390: if (HAVE_floatunstidf2) ! 2391: floattab[(int) DFmode][(int) TImode][1] = CODE_FOR_floatunstidf2; ! 2392: #endif ! 2393: ! 2394: #ifdef HAVE_floatunsqitf2 ! 2395: if (HAVE_floatunsqitf2) ! 2396: floattab[(int) TFmode][(int) QImode][1] = CODE_FOR_floatunsqitf2; ! 2397: #endif ! 2398: #ifdef HAVE_floatunshitf2 ! 2399: if (HAVE_floatunshitf2) ! 2400: floattab[(int) TFmode][(int) HImode][1] = CODE_FOR_floatunshitf2; ! 2401: #endif ! 2402: #ifdef HAVE_floatunssitf2 ! 2403: if (HAVE_floatunssitf2) ! 2404: floattab[(int) TFmode][(int) SImode][1] = CODE_FOR_floatunssitf2; ! 2405: #endif ! 2406: #ifdef HAVE_floatunsditf2 ! 2407: if (HAVE_floatunsditf2) ! 2408: floattab[(int) TFmode][(int) DImode][1] = CODE_FOR_floatunsditf2; ! 2409: #endif ! 2410: #ifdef HAVE_floatunstitf2 ! 2411: if (HAVE_floatunstitf2) ! 2412: floattab[(int) TFmode][(int) TImode][1] = CODE_FOR_floatunstitf2; ! 2413: #endif ! 2414: } ! 2415: ! 2416: /* Generate code to convert FROM to floating point ! 2417: and store in TO. FROM must be fixed point and not VOIDmode. ! 2418: UNSIGNEDP nonzero means regard FROM as unsigned. ! 2419: Normally this is done by correcting the final value ! 2420: if it is negative. */ ! 2421: ! 2422: void ! 2423: expand_float (to, from, unsignedp) ! 2424: rtx to, from; ! 2425: int unsignedp; ! 2426: { ! 2427: enum insn_code icode; ! 2428: register rtx target = to; ! 2429: enum machine_mode fmode, imode; ! 2430: ! 2431: /* Crash now, because we won't be able to decide which mode to use. */ ! 2432: if (GET_MODE (from) == VOIDmode) ! 2433: abort (); ! 2434: ! 2435: /* Look for an insn to do the conversion. Do it in the specified ! 2436: modes if possible; otherwise convert either input, output or both to ! 2437: wider mode. If the integer mode is wider than the mode of FROM, ! 2438: we can do the conversion signed even if the input is unsigned. */ ! 2439: ! 2440: for (imode = GET_MODE (from); imode != VOIDmode; ! 2441: imode = GET_MODE_WIDER_MODE (imode)) ! 2442: for (fmode = GET_MODE (to); fmode != VOIDmode; ! 2443: fmode = GET_MODE_WIDER_MODE (fmode)) ! 2444: { ! 2445: int doing_unsigned = unsignedp; ! 2446: ! 2447: icode = can_float_p (fmode, imode, unsignedp); ! 2448: if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp) ! 2449: icode = can_float_p (fmode, imode, 0), doing_unsigned = 0; ! 2450: ! 2451: if (icode != CODE_FOR_nothing) ! 2452: { ! 2453: to = protect_from_queue (to, 1); ! 2454: ! 2455: if (imode != GET_MODE (from)) ! 2456: from = convert_to_mode (imode, from, unsignedp); ! 2457: else ! 2458: from = protect_from_queue (from, 0); ! 2459: ! 2460: if (fmode != GET_MODE (to)) ! 2461: target = gen_reg_rtx (fmode); ! 2462: ! 2463: emit_unop_insn (icode, target, from, ! 2464: doing_unsigned ? UNSIGNED_FLOAT : FLOAT); ! 2465: ! 2466: if (target != to) ! 2467: convert_move (to, target, 0); ! 2468: return; ! 2469: } ! 2470: } ! 2471: ! 2472: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) ! 2473: ! 2474: /* Unsigned integer, and no way to convert directly. ! 2475: Convert as signed, then conditionally adjust the result. */ ! 2476: if (unsignedp) ! 2477: { ! 2478: rtx label = gen_label_rtx (); ! 2479: rtx temp; ! 2480: REAL_VALUE_TYPE offset; ! 2481: ! 2482: emit_queue (); ! 2483: ! 2484: to = protect_from_queue (to, 1); ! 2485: from = protect_from_queue (from, 0); ! 2486: ! 2487: if (flag_force_mem) ! 2488: from = force_not_mem (from); ! 2489: ! 2490: /* If we are about to do some arithmetic to correct for an ! 2491: unsigned operand, do it in a pseudo-register. */ ! 2492: ! 2493: if (GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER) ! 2494: target = gen_reg_rtx (GET_MODE (to)); ! 2495: ! 2496: /* Convert as signed integer to floating. */ ! 2497: expand_float (target, from, 0); ! 2498: ! 2499: /* If FROM is negative (and therefore TO is negative), ! 2500: correct its value by 2**bitwidth. */ ! 2501: ! 2502: do_pending_stack_adjust (); ! 2503: emit_cmp_insn (from, const0_rtx, GE, 0, GET_MODE (from), 0, 0); ! 2504: emit_jump_insn (gen_bge (label)); ! 2505: /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1). ! 2506: Rather than setting up a dconst_dot_5, let's hope SCO ! 2507: fixes the bug. */ ! 2508: offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from))); ! 2509: temp = expand_binop (GET_MODE (to), add_optab, target, ! 2510: immed_real_const_1 (offset, GET_MODE (to)), ! 2511: target, 0, OPTAB_LIB_WIDEN); ! 2512: if (temp != target) ! 2513: emit_move_insn (target, temp); ! 2514: do_pending_stack_adjust (); ! 2515: emit_label (label); ! 2516: } ! 2517: else ! 2518: #endif ! 2519: ! 2520: /* No hardware instruction available; call a library ! 2521: to convert from SImode or DImode into SFmode or DFmode. */ ! 2522: { ! 2523: rtx libfcn; ! 2524: rtx insns; ! 2525: ! 2526: to = protect_from_queue (to, 1); ! 2527: ! 2528: if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode)) ! 2529: from = convert_to_mode (SImode, from, unsignedp); ! 2530: else ! 2531: from = protect_from_queue (from, 0); ! 2532: ! 2533: if (flag_force_mem) ! 2534: from = force_not_mem (from); ! 2535: ! 2536: if (GET_MODE (to) == SFmode) ! 2537: { ! 2538: if (GET_MODE (from) == SImode) ! 2539: libfcn = floatsisf_libfunc; ! 2540: else if (GET_MODE (from) == DImode) ! 2541: libfcn = floatdisf_libfunc; ! 2542: else ! 2543: abort (); ! 2544: } ! 2545: else if (GET_MODE (to) == DFmode) ! 2546: { ! 2547: if (GET_MODE (from) == SImode) ! 2548: libfcn = floatsidf_libfunc; ! 2549: else if (GET_MODE (from) == DImode) ! 2550: libfcn = floatdidf_libfunc; ! 2551: else ! 2552: abort (); ! 2553: } ! 2554: else ! 2555: abort (); ! 2556: ! 2557: start_sequence (); ! 2558: ! 2559: emit_library_call (libfcn, 0, GET_MODE (to), 1, from, GET_MODE (from)); ! 2560: insns = get_insns (); ! 2561: end_sequence (); ! 2562: ! 2563: emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)), ! 2564: gen_rtx (FLOAT, GET_MODE (to), from)); ! 2565: } ! 2566: ! 2567: /* Copy result to requested destination ! 2568: if we have been computing in a temp location. */ ! 2569: ! 2570: if (target != to) ! 2571: { ! 2572: if (GET_MODE (target) == GET_MODE (to)) ! 2573: emit_move_insn (to, target); ! 2574: else ! 2575: convert_move (to, target, 0); ! 2576: } ! 2577: } ! 2578: ! 2579: /* expand_fix: generate code to convert FROM to fixed point ! 2580: and store in TO. FROM must be floating point. */ ! 2581: ! 2582: static rtx ! 2583: ftruncify (x) ! 2584: rtx x; ! 2585: { ! 2586: rtx temp = gen_reg_rtx (GET_MODE (x)); ! 2587: return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0); ! 2588: } ! 2589: ! 2590: void ! 2591: expand_fix (to, from, unsignedp) ! 2592: register rtx to, from; ! 2593: int unsignedp; ! 2594: { ! 2595: enum insn_code icode; ! 2596: register rtx target = to; ! 2597: enum machine_mode fmode, imode; ! 2598: int must_trunc = 0; ! 2599: rtx libfcn = 0; ! 2600: ! 2601: /* We first try to find a pair of modes, one real and one integer, at ! 2602: least as wide as FROM and TO, respectively, in which we can open-code ! 2603: this conversion. If the integer mode is wider than the mode of TO, ! 2604: we can do the conversion either signed or unsigned. */ ! 2605: ! 2606: for (imode = GET_MODE (to); imode != VOIDmode; ! 2607: imode = GET_MODE_WIDER_MODE (imode)) ! 2608: for (fmode = GET_MODE (from); fmode != VOIDmode; ! 2609: fmode = GET_MODE_WIDER_MODE (fmode)) ! 2610: { ! 2611: int doing_unsigned = unsignedp; ! 2612: ! 2613: icode = can_fix_p (imode, fmode, unsignedp, &must_trunc); ! 2614: if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp) ! 2615: icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0; ! 2616: ! 2617: if (icode != CODE_FOR_nothing) ! 2618: { ! 2619: to = protect_from_queue (to, 1); ! 2620: ! 2621: if (fmode != GET_MODE (from)) ! 2622: from = convert_to_mode (fmode, from, 0); ! 2623: else ! 2624: from = protect_from_queue (from, 0); ! 2625: ! 2626: if (must_trunc) ! 2627: from = ftruncify (from); ! 2628: ! 2629: if (imode != GET_MODE (to)) ! 2630: target = gen_reg_rtx (imode); ! 2631: ! 2632: emit_unop_insn (icode, target, from, ! 2633: doing_unsigned ? UNSIGNED_FIX : FIX); ! 2634: if (target != to) ! 2635: convert_move (to, target, unsignedp); ! 2636: return; ! 2637: } ! 2638: } ! 2639: ! 2640: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) ! 2641: /* For an unsigned conversion, there is one more way to do it. ! 2642: If we have a signed conversion, we generate code that compares ! 2643: the real value to the largest representable positive number. If if ! 2644: is smaller, the conversion is done normally. Otherwise, subtract ! 2645: one plus the highest signed number, convert, and add it back. ! 2646: ! 2647: We only need to check all real modes, since we know we didn't find ! 2648: anything with a wider inetger mode. */ ! 2649: ! 2650: if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_INT) ! 2651: for (fmode = GET_MODE (from); fmode != VOIDmode; ! 2652: fmode = GET_MODE_WIDER_MODE (fmode)) ! 2653: /* Make sure we won't lose significant bits doing this. */ ! 2654: if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to)) ! 2655: && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, ! 2656: &must_trunc)) ! 2657: { ! 2658: int bitsize = GET_MODE_BITSIZE (GET_MODE (to)); ! 2659: REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1); ! 2660: rtx limit = immed_real_const_1 (offset, fmode); ! 2661: rtx lab1 = gen_label_rtx (); ! 2662: rtx lab2 = gen_label_rtx (); ! 2663: rtx insn; ! 2664: ! 2665: emit_queue (); ! 2666: to = protect_from_queue (to, 1); ! 2667: from = protect_from_queue (from, 0); ! 2668: ! 2669: if (flag_force_mem) ! 2670: from = force_not_mem (from); ! 2671: ! 2672: if (fmode != GET_MODE (from)) ! 2673: from = convert_to_mode (fmode, from, 0); ! 2674: ! 2675: /* See if we need to do the subtraction. */ ! 2676: do_pending_stack_adjust (); ! 2677: emit_cmp_insn (from, limit, GE, 0, GET_MODE (from), 0, 0); ! 2678: emit_jump_insn (gen_bge (lab1)); ! 2679: ! 2680: /* If not, do the signed "fix" and branch around fixup code. */ ! 2681: expand_fix (to, from, 0); ! 2682: emit_jump_insn (gen_jump (lab2)); ! 2683: emit_barrier (); ! 2684: ! 2685: /* Otherwise, subtract 2**(N-1), convert to signed number, ! 2686: then add 2**(N-1). Do the addition using XOR since this ! 2687: will often generate better code. */ ! 2688: emit_label (lab1); ! 2689: target = expand_binop (GET_MODE (from), sub_optab, from, limit, ! 2690: 0, 0, OPTAB_LIB_WIDEN); ! 2691: expand_fix (to, target, 0); ! 2692: target = expand_binop (GET_MODE (to), xor_optab, to, ! 2693: gen_rtx (CONST_INT, VOIDmode, ! 2694: 1 << (bitsize - 1)), ! 2695: to, 1, OPTAB_LIB_WIDEN); ! 2696: ! 2697: if (target != to) ! 2698: emit_move_insn (to, target); ! 2699: ! 2700: emit_label (lab2); ! 2701: ! 2702: /* Make a place for a REG_NOTE and add it. */ ! 2703: insn = emit_move_insn (to, to); ! 2704: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, ! 2705: gen_rtx (UNSIGNED_FIX, GET_MODE (to), ! 2706: from), REG_NOTES (insn)); ! 2707: ! 2708: return; ! 2709: } ! 2710: #endif ! 2711: ! 2712: /* We can't do it with an insn, so use a library call. But first ensure ! 2713: that the mode of TO is at least as wide as SImode, since those are the ! 2714: only library calls we know about. */ ! 2715: ! 2716: if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode)) ! 2717: { ! 2718: target = gen_reg_rtx (SImode); ! 2719: ! 2720: expand_fix (target, from, unsignedp); ! 2721: } ! 2722: else if (GET_MODE (from) == SFmode) ! 2723: { ! 2724: if (GET_MODE (to) == SImode) ! 2725: libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc; ! 2726: else if (GET_MODE (to) == DImode) ! 2727: libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc; ! 2728: else ! 2729: abort (); ! 2730: } ! 2731: else if (GET_MODE (from) == DFmode) ! 2732: { ! 2733: if (GET_MODE (to) == SImode) ! 2734: libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc; ! 2735: else if (GET_MODE (to) == DImode) ! 2736: libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc; ! 2737: else ! 2738: abort (); ! 2739: } ! 2740: else ! 2741: abort (); ! 2742: ! 2743: if (libfcn) ! 2744: { ! 2745: rtx insns; ! 2746: ! 2747: to = protect_from_queue (to, 1); ! 2748: from = protect_from_queue (from, 0); ! 2749: ! 2750: if (flag_force_mem) ! 2751: from = force_not_mem (from); ! 2752: ! 2753: start_sequence (); ! 2754: ! 2755: emit_library_call (libfcn, 0, GET_MODE (to), 1, from, GET_MODE (from)); ! 2756: insns = get_insns (); ! 2757: end_sequence (); ! 2758: ! 2759: emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)), ! 2760: gen_rtx (unsignedp ? FIX : UNSIGNED_FIX, ! 2761: GET_MODE (to), from)); ! 2762: } ! 2763: ! 2764: if (GET_MODE (to) == GET_MODE (target)) ! 2765: emit_move_insn (to, target); ! 2766: else ! 2767: convert_move (to, target, 0); ! 2768: } ! 2769: ! 2770: static optab ! 2771: init_optab (code) ! 2772: enum rtx_code code; ! 2773: { ! 2774: int i; ! 2775: optab op = (optab) xmalloc (sizeof (struct optab)); ! 2776: op->code = code; ! 2777: for (i = 0; i < NUM_MACHINE_MODES; i++) ! 2778: { ! 2779: op->handlers[i].insn_code = CODE_FOR_nothing; ! 2780: op->handlers[i].libfunc = 0; ! 2781: } ! 2782: return op; ! 2783: } ! 2784: ! 2785: /* Call this once to initialize the contents of the optabs ! 2786: appropriately for the current target machine. */ ! 2787: ! 2788: void ! 2789: init_optabs () ! 2790: { ! 2791: int i; ! 2792: ! 2793: init_fixtab (); ! 2794: init_floattab (); ! 2795: init_extends (); ! 2796: ! 2797: add_optab = init_optab (PLUS); ! 2798: sub_optab = init_optab (MINUS); ! 2799: smul_optab = init_optab (MULT); ! 2800: smul_widen_optab = init_optab (UNKNOWN); ! 2801: umul_widen_optab = init_optab (UNKNOWN); ! 2802: sdiv_optab = init_optab (DIV); ! 2803: sdivmod_optab = init_optab (UNKNOWN); ! 2804: udiv_optab = init_optab (UDIV); ! 2805: udivmod_optab = init_optab (UNKNOWN); ! 2806: smod_optab = init_optab (MOD); ! 2807: umod_optab = init_optab (UMOD); ! 2808: flodiv_optab = init_optab (DIV); ! 2809: ftrunc_optab = init_optab (UNKNOWN); ! 2810: and_optab = init_optab (AND); ! 2811: ior_optab = init_optab (IOR); ! 2812: xor_optab = init_optab (XOR); ! 2813: ashl_optab = init_optab (ASHIFT); ! 2814: ashr_optab = init_optab (ASHIFTRT); ! 2815: lshl_optab = init_optab (LSHIFT); ! 2816: lshr_optab = init_optab (LSHIFTRT); ! 2817: rotl_optab = init_optab (ROTATE); ! 2818: rotr_optab = init_optab (ROTATERT); ! 2819: smin_optab = init_optab (SMIN); ! 2820: smax_optab = init_optab (SMAX); ! 2821: umin_optab = init_optab (UMIN); ! 2822: umax_optab = init_optab (UMAX); ! 2823: mov_optab = init_optab (UNKNOWN); ! 2824: movstrict_optab = init_optab (UNKNOWN); ! 2825: cmp_optab = init_optab (UNKNOWN); ! 2826: ucmp_optab = init_optab (UNKNOWN); ! 2827: tst_optab = init_optab (UNKNOWN); ! 2828: neg_optab = init_optab (NEG); ! 2829: abs_optab = init_optab (ABS); ! 2830: one_cmpl_optab = init_optab (NOT); ! 2831: ffs_optab = init_optab (FFS); ! 2832: ! 2833: #ifdef HAVE_addqi3 ! 2834: if (HAVE_addqi3) ! 2835: add_optab->handlers[(int) QImode].insn_code = CODE_FOR_addqi3; ! 2836: #endif ! 2837: #ifdef HAVE_addhi3 ! 2838: if (HAVE_addhi3) ! 2839: add_optab->handlers[(int) HImode].insn_code = CODE_FOR_addhi3; ! 2840: #endif ! 2841: #ifdef HAVE_addpsi3 ! 2842: if (HAVE_addpsi3) ! 2843: add_optab->handlers[(int) PSImode].insn_code = CODE_FOR_addpsi3; ! 2844: #endif ! 2845: #ifdef HAVE_addsi3 ! 2846: if (HAVE_addsi3) ! 2847: add_optab->handlers[(int) SImode].insn_code = CODE_FOR_addsi3; ! 2848: #endif ! 2849: #ifdef HAVE_adddi3 ! 2850: if (HAVE_adddi3) ! 2851: add_optab->handlers[(int) DImode].insn_code = CODE_FOR_adddi3; ! 2852: #endif ! 2853: #ifdef HAVE_addti3 ! 2854: if (HAVE_addti3) ! 2855: add_optab->handlers[(int) TImode].insn_code = CODE_FOR_addti3; ! 2856: #endif ! 2857: #ifdef HAVE_addsf3 ! 2858: if (HAVE_addsf3) ! 2859: add_optab->handlers[(int) SFmode].insn_code = CODE_FOR_addsf3; ! 2860: #endif ! 2861: #ifdef HAVE_adddf3 ! 2862: if (HAVE_adddf3) ! 2863: add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3; ! 2864: #endif ! 2865: #ifdef HAVE_addtf3 ! 2866: if (HAVE_addtf3) ! 2867: add_optab->handlers[(int) TFmode].insn_code = CODE_FOR_addtf3; ! 2868: #endif ! 2869: add_optab->handlers[(int) SFmode].libfunc ! 2870: = gen_rtx (SYMBOL_REF, Pmode, "__addsf3"); ! 2871: add_optab->handlers[(int) DFmode].libfunc ! 2872: = gen_rtx (SYMBOL_REF, Pmode, "__adddf3"); ! 2873: ! 2874: #ifdef HAVE_subqi3 ! 2875: if (HAVE_subqi3) ! 2876: sub_optab->handlers[(int) QImode].insn_code = CODE_FOR_subqi3; ! 2877: #endif ! 2878: #ifdef HAVE_subhi3 ! 2879: if (HAVE_subhi3) ! 2880: sub_optab->handlers[(int) HImode].insn_code = CODE_FOR_subhi3; ! 2881: #endif ! 2882: #ifdef HAVE_subpsi3 ! 2883: if (HAVE_subpsi3) ! 2884: sub_optab->handlers[(int) PSImode].insn_code = CODE_FOR_subpsi3; ! 2885: #endif ! 2886: #ifdef HAVE_subsi3 ! 2887: if (HAVE_subsi3) ! 2888: sub_optab->handlers[(int) SImode].insn_code = CODE_FOR_subsi3; ! 2889: #endif ! 2890: #ifdef HAVE_subdi3 ! 2891: if (HAVE_subdi3) ! 2892: sub_optab->handlers[(int) DImode].insn_code = CODE_FOR_subdi3; ! 2893: #endif ! 2894: #ifdef HAVE_subti3 ! 2895: if (HAVE_subti3) ! 2896: sub_optab->handlers[(int) Imode].insn_code = CODE_FOR_subti3; ! 2897: #endif ! 2898: #ifdef HAVE_subsf3 ! 2899: if (HAVE_subsf3) ! 2900: sub_optab->handlers[(int) SFmode].insn_code = CODE_FOR_subsf3; ! 2901: #endif ! 2902: #ifdef HAVE_subdf3 ! 2903: if (HAVE_subdf3) ! 2904: sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3; ! 2905: #endif ! 2906: #ifdef HAVE_subtf3 ! 2907: if (HAVE_subtf3) ! 2908: sub_optab->handlers[(int) TFmode].insn_code = CODE_FOR_subtf3; ! 2909: #endif ! 2910: sub_optab->handlers[(int) SFmode].libfunc ! 2911: = gen_rtx (SYMBOL_REF, Pmode, "__subsf3"); ! 2912: sub_optab->handlers[(int) DFmode].libfunc ! 2913: = gen_rtx (SYMBOL_REF, Pmode, "__subdf3"); ! 2914: ! 2915: #ifdef HAVE_mulqi3 ! 2916: if (HAVE_mulqi3) ! 2917: smul_optab->handlers[(int) QImode].insn_code = CODE_FOR_mulqi3; ! 2918: #endif ! 2919: #ifdef HAVE_mulhi3 ! 2920: if (HAVE_mulhi3) ! 2921: smul_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulhi3; ! 2922: #endif ! 2923: #ifdef HAVE_mulpsi3 ! 2924: if (HAVE_mulpsi3) ! 2925: smul_optab->handlers[(int) PSImode].insn_code = CODE_FOR_mulpsi3; ! 2926: #endif ! 2927: #ifdef HAVE_mulsi3 ! 2928: if (HAVE_mulsi3) ! 2929: smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3; ! 2930: #endif ! 2931: #ifdef HAVE_muldi3 ! 2932: if (HAVE_muldi3) ! 2933: smul_optab->handlers[(int) DImode].insn_code = CODE_FOR_muldi3; ! 2934: #endif ! 2935: #ifdef HAVE_multi3 ! 2936: if (HAVE_multi3) ! 2937: smul_optab->handlers[(int) TImode].insn_code = CODE_FOR_multi3; ! 2938: #endif ! 2939: #ifdef HAVE_mulsf3 ! 2940: if (HAVE_mulsf3) ! 2941: smul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_mulsf3; ! 2942: #endif ! 2943: #ifdef HAVE_muldf3 ! 2944: if (HAVE_muldf3) ! 2945: smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3; ! 2946: #endif ! 2947: #ifdef HAVE_multf3 ! 2948: if (HAVE_multf3) ! 2949: smul_optab->handlers[(int) TFmode].insn_code = CODE_FOR_multf3; ! 2950: #endif ! 2951: ! 2952: #ifdef MULSI3_LIBCALL ! 2953: smul_optab->handlers[(int) SImode].libfunc ! 2954: = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL); ! 2955: #else ! 2956: smul_optab->handlers[(int) SImode].libfunc ! 2957: = gen_rtx (SYMBOL_REF, Pmode, "__mulsi3"); ! 2958: #endif ! 2959: #ifdef MULDI3_LIBCALL ! 2960: smul_optab->handlers[(int) DImode].libfunc ! 2961: = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL); ! 2962: #else ! 2963: smul_optab->handlers[(int) DImode].libfunc ! 2964: = gen_rtx (SYMBOL_REF, Pmode, "__muldi3"); ! 2965: #endif ! 2966: smul_optab->handlers[(int) SFmode].libfunc ! 2967: = gen_rtx (SYMBOL_REF, Pmode, "__mulsf3"); ! 2968: smul_optab->handlers[(int) DFmode].libfunc ! 2969: = gen_rtx (SYMBOL_REF, Pmode, "__muldf3"); ! 2970: ! 2971: #ifdef HAVE_mulqihi3 ! 2972: if (HAVE_mulqihi3) ! 2973: smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3; ! 2974: #endif ! 2975: #ifdef HAVE_mulhisi3 ! 2976: if (HAVE_mulhisi3) ! 2977: smul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulhisi3; ! 2978: #endif ! 2979: #ifdef HAVE_mulsidi3 ! 2980: if (HAVE_mulsidi3) ! 2981: smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3; ! 2982: #endif ! 2983: #ifdef HAVE_mulditi3 ! 2984: if (HAVE_mulditi3) ! 2985: smul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_mulditi3; ! 2986: #endif ! 2987: ! 2988: #ifdef HAVE_umulqihi3 ! 2989: if (HAVE_umulqihi3) ! 2990: umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3; ! 2991: #endif ! 2992: #ifdef HAVE_umulhisi3 ! 2993: if (HAVE_umulhisi3) ! 2994: umul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulhisi3; ! 2995: #endif ! 2996: #ifdef HAVE_umulsidi3 ! 2997: if (HAVE_umulsidi3) ! 2998: umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3; ! 2999: #endif ! 3000: #ifdef HAVE_umulditi3 ! 3001: if (HAVE_umulditi3) ! 3002: umul_widen_optab->handlers[(int) TImode].insn_code = CODE_FOR_umulditi3; ! 3003: #endif ! 3004: ! 3005: #ifdef HAVE_divqi3 ! 3006: if (HAVE_divqi3) ! 3007: sdiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_divqi3; ! 3008: #endif ! 3009: #ifdef HAVE_divhi3 ! 3010: if (HAVE_divhi3) ! 3011: sdiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_divhi3; ! 3012: #endif ! 3013: #ifdef HAVE_divpsi3 ! 3014: if (HAVE_divpsi3) ! 3015: sdiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_divpsi3; ! 3016: #endif ! 3017: #ifdef HAVE_divsi3 ! 3018: if (HAVE_divsi3) ! 3019: sdiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_divsi3; ! 3020: #endif ! 3021: #ifdef HAVE_divdi3 ! 3022: if (HAVE_divdi3) ! 3023: sdiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_divdi3; ! 3024: #endif ! 3025: #ifdef HAVE_divti3 ! 3026: if (HAVE_divti3) ! 3027: sdiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_divti3; ! 3028: #endif ! 3029: ! 3030: #ifdef DIVSI3_LIBCALL ! 3031: sdiv_optab->handlers[(int) SImode].libfunc ! 3032: = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL); ! 3033: #else ! 3034: sdiv_optab->handlers[(int) SImode].libfunc ! 3035: = gen_rtx (SYMBOL_REF, Pmode, "__divsi3"); ! 3036: #endif ! 3037: #ifdef DIVDI3_LIBCALL ! 3038: sdiv_optab->handlers[(int) DImode].libfunc ! 3039: = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL); ! 3040: #else ! 3041: sdiv_optab->handlers[(int) DImode].libfunc ! 3042: = gen_rtx (SYMBOL_REF, Pmode, "__divdi3"); ! 3043: #endif ! 3044: ! 3045: #ifdef HAVE_udivqi3 ! 3046: if (HAVE_udivqi3) ! 3047: udiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivqi3; ! 3048: #endif ! 3049: #ifdef HAVE_udivhi3 ! 3050: if (HAVE_udivhi3) ! 3051: udiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivhi3; ! 3052: #endif ! 3053: #ifdef HAVE_udivpsi3 ! 3054: if (HAVE_udivpsi3) ! 3055: udiv_optab->handlers[(int) PSImode].insn_code = CODE_FOR_udivpsi3; ! 3056: #endif ! 3057: #ifdef HAVE_udivsi3 ! 3058: if (HAVE_udivsi3) ! 3059: udiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivsi3; ! 3060: #endif ! 3061: #ifdef HAVE_udivdi3 ! 3062: if (HAVE_udivdi3) ! 3063: udiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivdi3; ! 3064: #endif ! 3065: #ifdef HAVE_udivti3 ! 3066: if (HAVE_udivti3) ! 3067: udiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivti3; ! 3068: #endif ! 3069: ! 3070: #ifdef UDIVSI3_LIBCALL ! 3071: udiv_optab->handlers[(int) SImode].libfunc ! 3072: = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL); ! 3073: #else ! 3074: udiv_optab->handlers[(int) SImode].libfunc ! 3075: = gen_rtx (SYMBOL_REF, Pmode, "__udivsi3"); ! 3076: #endif ! 3077: #ifdef UDIVDI3_LIBCALL ! 3078: udiv_optab->handlers[(int) DImode].libfunc ! 3079: = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL); ! 3080: #else ! 3081: udiv_optab->handlers[(int) DImode].libfunc ! 3082: = gen_rtx (SYMBOL_REF, Pmode, "__udivdi3"); ! 3083: #endif ! 3084: ! 3085: #ifdef HAVE_divmodqi4 ! 3086: if (HAVE_divmodqi4) ! 3087: sdivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_divmodqi4; ! 3088: #endif ! 3089: #ifdef HAVE_divmodhi4 ! 3090: if (HAVE_divmodhi4) ! 3091: sdivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_divmodhi4; ! 3092: #endif ! 3093: #ifdef HAVE_divmodsi4 ! 3094: if (HAVE_divmodsi4) ! 3095: sdivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_divmodsi4; ! 3096: #endif ! 3097: #ifdef HAVE_divmoddi4 ! 3098: if (HAVE_divmoddi4) ! 3099: sdivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_divmoddi4; ! 3100: #endif ! 3101: #ifdef HAVE_divmodti4 ! 3102: if (HAVE_divmodti4) ! 3103: sdivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_divmodti4; ! 3104: #endif ! 3105: ! 3106: #ifdef HAVE_udivmodqi4 ! 3107: if (HAVE_udivmodqi4) ! 3108: udivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivmodqi4; ! 3109: #endif ! 3110: #ifdef HAVE_udivmodhi4 ! 3111: if (HAVE_udivmodhi4) ! 3112: udivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivmodhi4; ! 3113: #endif ! 3114: #ifdef HAVE_udivmodsi4 ! 3115: if (HAVE_udivmodsi4) ! 3116: udivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivmodsi4; ! 3117: #endif ! 3118: #ifdef HAVE_udivmoddi4 ! 3119: if (HAVE_udivmoddi4) ! 3120: udivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivmoddi4; ! 3121: #endif ! 3122: #ifdef HAVE_udivmodti4 ! 3123: if (HAVE_udivmodti4) ! 3124: udivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivmodti4; ! 3125: #endif ! 3126: ! 3127: #ifdef HAVE_modqi3 ! 3128: if (HAVE_modqi3) ! 3129: smod_optab->handlers[(int) QImode].insn_code = CODE_FOR_modqi3; ! 3130: #endif ! 3131: #ifdef HAVE_modhi3 ! 3132: if (HAVE_modhi3) ! 3133: smod_optab->handlers[(int) HImode].insn_code = CODE_FOR_modhi3; ! 3134: #endif ! 3135: #ifdef HAVE_modpsi3 ! 3136: if (HAVE_modpsi3) ! 3137: smod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_modpsi3; ! 3138: #endif ! 3139: #ifdef HAVE_modsi3 ! 3140: if (HAVE_modsi3) ! 3141: smod_optab->handlers[(int) SImode].insn_code = CODE_FOR_modsi3; ! 3142: #endif ! 3143: #ifdef HAVE_moddi3 ! 3144: if (HAVE_moddi3) ! 3145: smod_optab->handlers[(int) DImode].insn_code = CODE_FOR_moddi3; ! 3146: #endif ! 3147: #ifdef HAVE_modti3 ! 3148: if (HAVE_modti3) ! 3149: smod_optab->handlers[(int) TImode].insn_code = CODE_FOR_modti3; ! 3150: #endif ! 3151: ! 3152: #ifdef MODSI3_LIBCALL ! 3153: smod_optab->handlers[(int) SImode].libfunc ! 3154: = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL); ! 3155: #else ! 3156: smod_optab->handlers[(int) SImode].libfunc ! 3157: = gen_rtx (SYMBOL_REF, Pmode, "__modsi3"); ! 3158: #endif ! 3159: #ifdef MODDI3_LIBCALL ! 3160: smod_optab->handlers[(int) DImode].libfunc ! 3161: = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL); ! 3162: #else ! 3163: smod_optab->handlers[(int) DImode].libfunc ! 3164: = gen_rtx (SYMBOL_REF, Pmode, "__moddi3"); ! 3165: #endif ! 3166: ! 3167: #ifdef HAVE_umodqi3 ! 3168: if (HAVE_umodqi3) ! 3169: umod_optab->handlers[(int) QImode].insn_code = CODE_FOR_umodqi3; ! 3170: #endif ! 3171: #ifdef HAVE_umodhi3 ! 3172: if (HAVE_umodhi3) ! 3173: umod_optab->handlers[(int) HImode].insn_code = CODE_FOR_umodhi3; ! 3174: #endif ! 3175: #ifdef HAVE_umodpsi3 ! 3176: if (HAVE_umodpsi3) ! 3177: umod_optab->handlers[(int) PSImode].insn_code = CODE_FOR_umodpsi3; ! 3178: #endif ! 3179: #ifdef HAVE_umodsi3 ! 3180: if (HAVE_umodsi3) ! 3181: umod_optab->handlers[(int) SImode].insn_code = CODE_FOR_umodsi3; ! 3182: #endif ! 3183: #ifdef HAVE_umoddi3 ! 3184: if (HAVE_umoddi3) ! 3185: umod_optab->handlers[(int) DImode].insn_code = CODE_FOR_umoddi3; ! 3186: #endif ! 3187: #ifdef HAVE_umodti3 ! 3188: if (HAVE_umodti3) ! 3189: umod_optab->handlers[(int) TImode].insn_code = CODE_FOR_umodti3; ! 3190: #endif ! 3191: ! 3192: #ifdef UMODSI3_LIBCALL ! 3193: umod_optab->handlers[(int) SImode].libfunc ! 3194: = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL); ! 3195: #else ! 3196: umod_optab->handlers[(int) SImode].libfunc ! 3197: = gen_rtx (SYMBOL_REF, Pmode, "__umodsi3"); ! 3198: #endif ! 3199: #ifdef UMODDI3_LIBCALL ! 3200: umod_optab->handlers[(int) DImode].libfunc ! 3201: = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL); ! 3202: #else ! 3203: umod_optab->handlers[(int) DImode].libfunc ! 3204: = gen_rtx (SYMBOL_REF, Pmode, "__umoddi3"); ! 3205: #endif ! 3206: ! 3207: #ifdef HAVE_divsf3 ! 3208: if (HAVE_divsf3) ! 3209: flodiv_optab->handlers[(int) SFmode].insn_code = CODE_FOR_divsf3; ! 3210: #endif ! 3211: #ifdef HAVE_divdf3 ! 3212: if (HAVE_divdf3) ! 3213: flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3; ! 3214: #endif ! 3215: #ifdef HAVE_divtf3 ! 3216: if (HAVE_divtf3) ! 3217: flodiv_optab->handlers[(int) TFmode].insn_code = CODE_FOR_divtf3; ! 3218: #endif ! 3219: flodiv_optab->handlers[(int) SFmode].libfunc ! 3220: = gen_rtx (SYMBOL_REF, Pmode, "__divsf3"); ! 3221: flodiv_optab->handlers[(int) DFmode].libfunc ! 3222: = gen_rtx (SYMBOL_REF, Pmode, "__divdf3"); ! 3223: ! 3224: #ifdef HAVE_ftruncsf2 ! 3225: if (HAVE_ftruncsf2) ! 3226: ftrunc_optab->handlers[(int) SFmode].insn_code = CODE_FOR_ftruncsf2; ! 3227: #endif ! 3228: #ifdef HAVE_ftruncdf2 ! 3229: if (HAVE_ftruncdf2) ! 3230: ftrunc_optab->handlers[(int) DFmode].insn_code = CODE_FOR_ftruncdf2; ! 3231: #endif ! 3232: #ifdef HAVE_ftrunctf2 ! 3233: if (HAVE_ftrunctf2) ! 3234: ftrunc_optab->handlers[(int) TFmode].insn_code = CODE_FOR_ftrunctf2; ! 3235: #endif ! 3236: ! 3237: #ifdef HAVE_andqi3 ! 3238: if (HAVE_andqi3) ! 3239: and_optab->handlers[(int) QImode].insn_code = CODE_FOR_andqi3; ! 3240: #endif ! 3241: #ifdef HAVE_andhi3 ! 3242: if (HAVE_andhi3) ! 3243: and_optab->handlers[(int) HImode].insn_code = CODE_FOR_andhi3; ! 3244: #endif ! 3245: #ifdef HAVE_andpsi3 ! 3246: if (HAVE_andpsi3) ! 3247: and_optab->handlers[(int) PSImode].insn_code = CODE_FOR_andpsi3; ! 3248: #endif ! 3249: #ifdef HAVE_andsi3 ! 3250: if (HAVE_andsi3) ! 3251: and_optab->handlers[(int) SImode].insn_code = CODE_FOR_andsi3; ! 3252: #endif ! 3253: #ifdef HAVE_anddi3 ! 3254: if (HAVE_anddi3) ! 3255: and_optab->handlers[(int) DImode].insn_code = CODE_FOR_anddi3; ! 3256: #endif ! 3257: #ifdef HAVE_andti3 ! 3258: if (HAVE_andti3) ! 3259: and_optab->handlers[(int) TImode].insn_code = CODE_FOR_andti3; ! 3260: #endif ! 3261: ! 3262: #ifdef HAVE_iorqi3 ! 3263: if (HAVE_iorqi3) ! 3264: ior_optab->handlers[(int) QImode].insn_code = CODE_FOR_iorqi3; ! 3265: #endif ! 3266: #ifdef HAVE_iorhi3 ! 3267: if (HAVE_iorhi3) ! 3268: ior_optab->handlers[(int) HImode].insn_code = CODE_FOR_iorhi3; ! 3269: #endif ! 3270: #ifdef HAVE_iorpsi3 ! 3271: if (HAVE_iorpsi3) ! 3272: ior_optab->handlers[(int) PSImode].insn_code = CODE_FOR_iorpsi3; ! 3273: #endif ! 3274: #ifdef HAVE_iorsi3 ! 3275: if (HAVE_iorsi3) ! 3276: ior_optab->handlers[(int) SImode].insn_code = CODE_FOR_iorsi3; ! 3277: #endif ! 3278: #ifdef HAVE_iordi3 ! 3279: if (HAVE_iordi3) ! 3280: ior_optab->handlers[(int) DImode].insn_code = CODE_FOR_iordi3; ! 3281: #endif ! 3282: #ifdef HAVE_iorti3 ! 3283: if (HAVE_iorti3) ! 3284: ior_optab->handlers[(int) TImode].insn_code = CODE_FOR_iorti3; ! 3285: #endif ! 3286: ! 3287: #ifdef HAVE_xorqi3 ! 3288: if (HAVE_xorqi3) ! 3289: xor_optab->handlers[(int) QImode].insn_code = CODE_FOR_xorqi3; ! 3290: #endif ! 3291: #ifdef HAVE_xorhi3 ! 3292: if (HAVE_xorhi3) ! 3293: xor_optab->handlers[(int) HImode].insn_code = CODE_FOR_xorhi3; ! 3294: #endif ! 3295: #ifdef HAVE_xorpsi3 ! 3296: if (HAVE_xorpsi3) ! 3297: xor_optab->handlers[(int) PSImode].insn_code = CODE_FOR_xorpsi3; ! 3298: #endif ! 3299: #ifdef HAVE_xorsi3 ! 3300: if (HAVE_xorsi3) ! 3301: xor_optab->handlers[(int) SImode].insn_code = CODE_FOR_xorsi3; ! 3302: #endif ! 3303: #ifdef HAVE_xordi3 ! 3304: if (HAVE_xordi3) ! 3305: xor_optab->handlers[(int) DImode].insn_code = CODE_FOR_xordi3; ! 3306: #endif ! 3307: #ifdef HAVE_xorti3 ! 3308: if (HAVE_xorti3) ! 3309: xor_optab->handlers[(int) TImode].insn_code = CODE_FOR_xorti3; ! 3310: #endif ! 3311: ! 3312: #ifdef HAVE_ashlqi3 ! 3313: if (HAVE_ashlqi3) ! 3314: ashl_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashlqi3; ! 3315: #endif ! 3316: #ifdef HAVE_ashlhi3 ! 3317: if (HAVE_ashlhi3) ! 3318: ashl_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashlhi3; ! 3319: #endif ! 3320: #ifdef HAVE_ashlpsi3 ! 3321: if (HAVE_ashlpsi3) ! 3322: ashl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashlpsi3; ! 3323: #endif ! 3324: #ifdef HAVE_ashlsi3 ! 3325: if (HAVE_ashlsi3) ! 3326: ashl_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashlsi3; ! 3327: #endif ! 3328: #ifdef HAVE_ashldi3 ! 3329: if (HAVE_ashldi3) ! 3330: ashl_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashldi3; ! 3331: #endif ! 3332: #ifdef HAVE_ashlti3 ! 3333: if (HAVE_ashlti3) ! 3334: ashl_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashlti3; ! 3335: #endif ! 3336: ashl_optab->handlers[(int) SImode].libfunc ! 3337: = gen_rtx (SYMBOL_REF, Pmode, "__ashlsi3"); ! 3338: ashl_optab->handlers[(int) DImode].libfunc ! 3339: = gen_rtx (SYMBOL_REF, Pmode, "__ashldi3"); ! 3340: ! 3341: #ifdef HAVE_ashrqi3 ! 3342: if (HAVE_ashrqi3) ! 3343: ashr_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashrqi3; ! 3344: #endif ! 3345: #ifdef HAVE_ashrhi3 ! 3346: if (HAVE_ashrhi3) ! 3347: ashr_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashrhi3; ! 3348: #endif ! 3349: #ifdef HAVE_ashrpsi3 ! 3350: if (HAVE_ashrpsi3) ! 3351: ashr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ashrpsi3; ! 3352: #endif ! 3353: #ifdef HAVE_ashrsi3 ! 3354: if (HAVE_ashrsi3) ! 3355: ashr_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashrsi3; ! 3356: #endif ! 3357: #ifdef HAVE_ashrdi3 ! 3358: if (HAVE_ashrdi3) ! 3359: ashr_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashrdi3; ! 3360: #endif ! 3361: #ifdef HAVE_ashrti3 ! 3362: if (HAVE_ashrti3) ! 3363: ashr_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashrti3; ! 3364: #endif ! 3365: ashr_optab->handlers[(int) SImode].libfunc ! 3366: = gen_rtx (SYMBOL_REF, Pmode, "__ashrsi3"); ! 3367: ashr_optab->handlers[(int) DImode].libfunc ! 3368: = gen_rtx (SYMBOL_REF, Pmode, "__ashrdi3"); ! 3369: ! 3370: #ifdef HAVE_lshlqi3 ! 3371: if (HAVE_lshlqi3) ! 3372: lshl_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshlqi3; ! 3373: #endif ! 3374: #ifdef HAVE_lshlhi3 ! 3375: if (HAVE_lshlhi3) ! 3376: lshl_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshlhi3; ! 3377: #endif ! 3378: #ifdef HAVE_lshlpsi3 ! 3379: if (HAVE_lshlpsi3) ! 3380: lshl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshlpsi3; ! 3381: #endif ! 3382: #ifdef HAVE_lshlsi3 ! 3383: if (HAVE_lshlsi3) ! 3384: lshl_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshlsi3; ! 3385: #endif ! 3386: #ifdef HAVE_lshldi3 ! 3387: if (HAVE_lshldi3) ! 3388: lshl_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshldi3; ! 3389: #endif ! 3390: #ifdef HAVE_lshlti3 ! 3391: if (HAVE_lshlti3) ! 3392: lshl_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshlti3; ! 3393: #endif ! 3394: lshl_optab->handlers[(int) SImode].libfunc ! 3395: = gen_rtx (SYMBOL_REF, Pmode, "__lshlsi3"); ! 3396: lshl_optab->handlers[(int) DImode].libfunc ! 3397: = gen_rtx (SYMBOL_REF, Pmode, "__lshldi3"); ! 3398: ! 3399: #ifdef HAVE_lshrqi3 ! 3400: if (HAVE_lshrqi3) ! 3401: lshr_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshrqi3; ! 3402: #endif ! 3403: #ifdef HAVE_lshrhi3 ! 3404: if (HAVE_lshrhi3) ! 3405: lshr_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshrhi3; ! 3406: #endif ! 3407: #ifdef HAVE_lshrpsi3 ! 3408: if (HAVE_lshrpsi3) ! 3409: lshr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_lshrpsi3; ! 3410: #endif ! 3411: #ifdef HAVE_lshrsi3 ! 3412: if (HAVE_lshrsi3) ! 3413: lshr_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshrsi3; ! 3414: #endif ! 3415: #ifdef HAVE_lshrdi3 ! 3416: if (HAVE_lshrdi3) ! 3417: lshr_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshrdi3; ! 3418: #endif ! 3419: #ifdef HAVE_lshrti3 ! 3420: if (HAVE_lshrti3) ! 3421: lshr_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshrti3; ! 3422: #endif ! 3423: lshr_optab->handlers[(int) SImode].libfunc ! 3424: = gen_rtx (SYMBOL_REF, Pmode, "__lshrsi3"); ! 3425: lshr_optab->handlers[(int) DImode].libfunc ! 3426: = gen_rtx (SYMBOL_REF, Pmode, "__lshrdi3"); ! 3427: ! 3428: #ifdef HAVE_rotlqi3 ! 3429: if (HAVE_rotlqi3) ! 3430: rotl_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotlqi3; ! 3431: #endif ! 3432: #ifdef HAVE_rotlhi3 ! 3433: if (HAVE_rotlhi3) ! 3434: rotl_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotlhi3; ! 3435: #endif ! 3436: #ifdef HAVE_rotlpsi3 ! 3437: if (HAVE_rotlpsi3) ! 3438: rotl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotlpsi3; ! 3439: #endif ! 3440: #ifdef HAVE_rotlsi3 ! 3441: if (HAVE_rotlsi3) ! 3442: rotl_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotlsi3; ! 3443: #endif ! 3444: #ifdef HAVE_rotldi3 ! 3445: if (HAVE_rotldi3) ! 3446: rotl_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotldi3; ! 3447: #endif ! 3448: #ifdef HAVE_rotlti3 ! 3449: if (HAVE_rotlti3) ! 3450: rotl_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotlti3; ! 3451: #endif ! 3452: rotl_optab->handlers[(int) SImode].libfunc ! 3453: = gen_rtx (SYMBOL_REF, Pmode, "__rotlsi3"); ! 3454: rotl_optab->handlers[(int) DImode].libfunc ! 3455: = gen_rtx (SYMBOL_REF, Pmode, "__rotldi3"); ! 3456: ! 3457: #ifdef HAVE_rotrqi3 ! 3458: if (HAVE_rotrqi3) ! 3459: rotr_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotrqi3; ! 3460: #endif ! 3461: #ifdef HAVE_rotrhi3 ! 3462: if (HAVE_rotrhi3) ! 3463: rotr_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotrhi3; ! 3464: #endif ! 3465: #ifdef HAVE_rotrpsi3 ! 3466: if (HAVE_rotrpsi3) ! 3467: rotr_optab->handlers[(int) PSImode].insn_code = CODE_FOR_rotrpsi3; ! 3468: #endif ! 3469: #ifdef HAVE_rotrsi3 ! 3470: if (HAVE_rotrsi3) ! 3471: rotr_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotrsi3; ! 3472: #endif ! 3473: #ifdef HAVE_rotrdi3 ! 3474: if (HAVE_rotrdi3) ! 3475: rotr_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotrdi3; ! 3476: #endif ! 3477: #ifdef HAVE_rotrti3 ! 3478: if (HAVE_rotrti3) ! 3479: rotr_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotrti3; ! 3480: #endif ! 3481: rotr_optab->handlers[(int) SImode].libfunc ! 3482: = gen_rtx (SYMBOL_REF, Pmode, "__rotrsi3"); ! 3483: rotr_optab->handlers[(int) DImode].libfunc ! 3484: = gen_rtx (SYMBOL_REF, Pmode, "__rotrdi3"); ! 3485: ! 3486: #ifdef HAVE_sminqi3 ! 3487: if (HAVE_sminqi3) ! 3488: smin_optab->handlers[(int) QImode].insn_code = CODE_FOR_sminqi3; ! 3489: #endif ! 3490: #ifdef HAVE_sminhi3 ! 3491: if (HAVE_sminhi3) ! 3492: smin_optab->handlers[(int) HImode].insn_code = CODE_FOR_sminhi3; ! 3493: #endif ! 3494: #ifdef HAVE_sminsi3 ! 3495: if (HAVE_sminsi3) ! 3496: smin_optab->handlers[(int) SImode].insn_code = CODE_FOR_sminsi3; ! 3497: #endif ! 3498: #ifdef HAVE_smindi3 ! 3499: if (HAVE_smindi3) ! 3500: smin_optab->handlers[(int) DImode].insn_code = CODE_FOR_smindi3; ! 3501: #endif ! 3502: #ifdef HAVE_sminti3 ! 3503: if (HAVE_sminti3) ! 3504: smin_optab->handlers[(int) TImode].insn_code = CODE_FOR_sminti3; ! 3505: #endif ! 3506: #ifdef HAVE_sminsf3 ! 3507: if (HAVE_sminsf3) ! 3508: smin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sminsf3; ! 3509: #endif ! 3510: #ifdef HAVE_smindf3 ! 3511: if (HAVE_smindf3) ! 3512: smin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_smindf3; ! 3513: #endif ! 3514: #ifdef HAVE_smintf3 ! 3515: if (HAVE_smintf3) ! 3516: smin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_smintf3; ! 3517: #endif ! 3518: ! 3519: #ifdef HAVE_smaxqi3 ! 3520: if (HAVE_smaxqi3) ! 3521: smax_optab->handlers[(int) QImode].insn_code = CODE_FOR_smaxqi3; ! 3522: #endif ! 3523: #ifdef HAVE_smaxhi3 ! 3524: if (HAVE_smaxhi3) ! 3525: smax_optab->handlers[(int) HImode].insn_code = CODE_FOR_smaxhi3; ! 3526: #endif ! 3527: #ifdef HAVE_smaxsi3 ! 3528: if (HAVE_smaxsi3) ! 3529: smax_optab->handlers[(int) SImode].insn_code = CODE_FOR_smaxsi3; ! 3530: #endif ! 3531: #ifdef HAVE_smaxdi3 ! 3532: if (HAVE_smaxdi3) ! 3533: smax_optab->handlers[(int) DImode].insn_code = CODE_FOR_smaxdi3; ! 3534: #endif ! 3535: #ifdef HAVE_smaxti3 ! 3536: if (HAVE_smaxti3) ! 3537: smax_optab->handlers[(int) TImode].insn_code = CODE_FOR_smaxti3; ! 3538: #endif ! 3539: #ifdef HAVE_smaxsf3 ! 3540: if (HAVE_smaxsf3) ! 3541: smax_optab->handlers[(int) SFmode].insn_code = CODE_FOR_smaxsf3; ! 3542: #endif ! 3543: #ifdef HAVE_smaxdf3 ! 3544: if (HAVE_smaxdf3) ! 3545: smax_optab->handlers[(int) DFmode].insn_code = CODE_FOR_smaxdf3; ! 3546: #endif ! 3547: #ifdef HAVE_smaxtf3 ! 3548: if (HAVE_smaxtf3) ! 3549: smax_optab->handlers[(int) TFmode].insn_code = CODE_FOR_smaxtf3; ! 3550: #endif ! 3551: ! 3552: #ifdef HAVE_uminqi3 ! 3553: if (HAVE_uminqi3) ! 3554: umin_optab->handlers[(int) QImode].insn_code = CODE_FOR_uminqi3; ! 3555: #endif ! 3556: #ifdef HAVE_uminhi3 ! 3557: if (HAVE_uminhi3) ! 3558: umin_optab->handlers[(int) HImode].insn_code = CODE_FOR_uminhi3; ! 3559: #endif ! 3560: #ifdef HAVE_uminsi3 ! 3561: if (HAVE_uminsi3) ! 3562: umin_optab->handlers[(int) SImode].insn_code = CODE_FOR_uminsi3; ! 3563: #endif ! 3564: #ifdef HAVE_umindi3 ! 3565: if (HAVE_umindi3) ! 3566: umin_optab->handlers[(int) DImode].insn_code = CODE_FOR_umindi3; ! 3567: #endif ! 3568: #ifdef HAVE_uminti3 ! 3569: if (HAVE_uminti3) ! 3570: umin_optab->handlers[(int) TImode].insn_code = CODE_FOR_uminti3; ! 3571: #endif ! 3572: ! 3573: #ifdef HAVE_umaxqi3 ! 3574: if (HAVE_umaxqi3) ! 3575: umax_optab->handlers[(int) QImode].insn_code = CODE_FOR_umaxqi3; ! 3576: #endif ! 3577: #ifdef HAVE_umaxhi3 ! 3578: if (HAVE_umaxhi3) ! 3579: umax_optab->handlers[(int) HImode].insn_code = CODE_FOR_umaxhi3; ! 3580: #endif ! 3581: #ifdef HAVE_umaxsi3 ! 3582: if (HAVE_umaxsi3) ! 3583: umax_optab->handlers[(int) SImode].insn_code = CODE_FOR_umaxsi3; ! 3584: #endif ! 3585: #ifdef HAVE_umaxdi3 ! 3586: if (HAVE_umaxdi3) ! 3587: umax_optab->handlers[(int) DImode].insn_code = CODE_FOR_umaxdi3; ! 3588: #endif ! 3589: #ifdef HAVE_umaxti3 ! 3590: if (HAVE_umaxti3) ! 3591: umax_optab->handlers[(int) TImode].insn_code = CODE_FOR_umaxti3; ! 3592: #endif ! 3593: ! 3594: #ifdef HAVE_negqi2 ! 3595: if (HAVE_negqi2) ! 3596: neg_optab->handlers[(int) QImode].insn_code = CODE_FOR_negqi2; ! 3597: #endif ! 3598: #ifdef HAVE_neghi2 ! 3599: if (HAVE_neghi2) ! 3600: neg_optab->handlers[(int) HImode].insn_code = CODE_FOR_neghi2; ! 3601: #endif ! 3602: #ifdef HAVE_negpsi2 ! 3603: if (HAVE_negpsi2) ! 3604: neg_optab->handlers[(int) PSImode].insn_code = CODE_FOR_negpsi2; ! 3605: #endif ! 3606: #ifdef HAVE_negsi2 ! 3607: if (HAVE_negsi2) ! 3608: neg_optab->handlers[(int) SImode].insn_code = CODE_FOR_negsi2; ! 3609: #endif ! 3610: #ifdef HAVE_negdi2 ! 3611: if (HAVE_negdi2) ! 3612: neg_optab->handlers[(int) DImode].insn_code = CODE_FOR_negdi2; ! 3613: #endif ! 3614: #ifdef HAVE_negti2 ! 3615: if (HAVE_negti2) ! 3616: neg_optab->handlers[(int) TImode].insn_code = CODE_FOR_negti2; ! 3617: #endif ! 3618: #ifdef HAVE_negsf2 ! 3619: if (HAVE_negsf2) ! 3620: neg_optab->handlers[(int) SFmode].insn_code = CODE_FOR_negsf2; ! 3621: #endif ! 3622: #ifdef HAVE_negdf2 ! 3623: if (HAVE_negdf2) ! 3624: neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2; ! 3625: #endif ! 3626: #ifdef HAVE_negtf2 ! 3627: if (HAVE_negtf2) ! 3628: neg_optab->handlers[(int) TFmode].insn_code = CODE_FOR_negtf2; ! 3629: #endif ! 3630: neg_optab->handlers[(int) SImode].libfunc ! 3631: = gen_rtx (SYMBOL_REF, Pmode, "__negsi2"); ! 3632: neg_optab->handlers[(int) DImode].libfunc ! 3633: = gen_rtx (SYMBOL_REF, Pmode, "__negdi2"); ! 3634: neg_optab->handlers[(int) SFmode].libfunc ! 3635: = gen_rtx (SYMBOL_REF, Pmode, "__negsf2"); ! 3636: neg_optab->handlers[(int) DFmode].libfunc ! 3637: = gen_rtx (SYMBOL_REF, Pmode, "__negdf2"); ! 3638: ! 3639: #ifdef HAVE_absqi2 ! 3640: if (HAVE_absqi2) ! 3641: abs_optab->handlers[(int) QImode].insn_code = CODE_FOR_absqi2; ! 3642: #endif ! 3643: #ifdef HAVE_abshi2 ! 3644: if (HAVE_abshi2) ! 3645: abs_optab->handlers[(int) HImode].insn_code = CODE_FOR_abshi2; ! 3646: #endif ! 3647: #ifdef HAVE_abspsi2 ! 3648: if (HAVE_abspsi2) ! 3649: abs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_abspsi2; ! 3650: #endif ! 3651: #ifdef HAVE_abssi2 ! 3652: if (HAVE_abssi2) ! 3653: abs_optab->handlers[(int) SImode].insn_code = CODE_FOR_abssi2; ! 3654: #endif ! 3655: #ifdef HAVE_absdi2 ! 3656: if (HAVE_absdi2) ! 3657: abs_optab->handlers[(int) DImode].insn_code = CODE_FOR_absdi2; ! 3658: #endif ! 3659: #ifdef HAVE_absti2 ! 3660: if (HAVE_absti2) ! 3661: abs_optab->handlers[(int) TImode].insn_code = CODE_FOR_absti2; ! 3662: #endif ! 3663: #ifdef HAVE_abssf2 ! 3664: if (HAVE_abssf2) ! 3665: abs_optab->handlers[(int) SFmode].insn_code = CODE_FOR_abssf2; ! 3666: #endif ! 3667: #ifdef HAVE_absdf2 ! 3668: if (HAVE_absdf2) ! 3669: abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2; ! 3670: #endif ! 3671: #ifdef HAVE_abstf2 ! 3672: if (HAVE_abstf2) ! 3673: abs_optab->handlers[(int) TFmode].insn_code = CODE_FOR_abstf2; ! 3674: #endif ! 3675: /* No library calls here! If there is no abs instruction, ! 3676: expand_expr will generate a conditional negation. */ ! 3677: ! 3678: #ifdef HAVE_one_cmplqi2 ! 3679: if (HAVE_one_cmplqi2) ! 3680: one_cmpl_optab->handlers[(int) QImode].insn_code = CODE_FOR_one_cmplqi2; ! 3681: #endif ! 3682: #ifdef HAVE_one_cmplhi2 ! 3683: if (HAVE_one_cmplhi2) ! 3684: one_cmpl_optab->handlers[(int) HImode].insn_code = CODE_FOR_one_cmplhi2; ! 3685: #endif ! 3686: #ifdef HAVE_one_cmplpsi2 ! 3687: if (HAVE_one_cmplpsi2) ! 3688: one_cmpl_optab->handlers[(int) PSImode].insn_code = CODE_FOR_one_cmplpsi2; ! 3689: #endif ! 3690: #ifdef HAVE_one_cmplsi2 ! 3691: if (HAVE_one_cmplsi2) ! 3692: one_cmpl_optab->handlers[(int) SImode].insn_code = CODE_FOR_one_cmplsi2; ! 3693: #endif ! 3694: #ifdef HAVE_one_cmpldi2 ! 3695: if (HAVE_one_cmpldi2) ! 3696: one_cmpl_optab->handlers[(int) DImode].insn_code = CODE_FOR_one_cmpldi2; ! 3697: #endif ! 3698: #ifdef HAVE_one_cmplti2 ! 3699: if (HAVE_one_cmplti2) ! 3700: one_cmpl_optab->handlers[(int) TImode].insn_code = CODE_FOR_one_cmplti2; ! 3701: #endif ! 3702: one_cmpl_optab->handlers[(int) SImode].libfunc ! 3703: = gen_rtx (SYMBOL_REF, Pmode, "__one_cmplsi2"); ! 3704: ! 3705: #ifdef HAVE_ffsqi2 ! 3706: if (HAVE_ffsqi2) ! 3707: ffs_optab->handlers[(int) QImode].insn_code = CODE_FOR_ffsqi2; ! 3708: #endif ! 3709: #ifdef HAVE_ffshi2 ! 3710: if (HAVE_ffshi2) ! 3711: ffs_optab->handlers[(int) HImode].insn_code = CODE_FOR_ffshi2; ! 3712: #endif ! 3713: #ifdef HAVE_ffspsi2 ! 3714: if (HAVE_ffspsi2) ! 3715: ffs_optab->handlers[(int) PSImode].insn_code = CODE_FOR_ffspsi2; ! 3716: #endif ! 3717: #ifdef HAVE_ffssi2 ! 3718: if (HAVE_ffssi2) ! 3719: ffs_optab->handlers[(int) SImode].insn_code = CODE_FOR_ffssi2; ! 3720: #endif ! 3721: #ifdef HAVE_ffsdi2 ! 3722: if (HAVE_ffsdi2) ! 3723: ffs_optab->handlers[(int) DImode].insn_code = CODE_FOR_ffsdi2; ! 3724: #endif ! 3725: #ifdef HAVE_ffsti2 ! 3726: if (HAVE_ffsti2) ! 3727: ffs_optab->handlers[(int) TImode].insn_code = CODE_FOR_ffsti2; ! 3728: #endif ! 3729: ffs_optab->handlers[(int) SImode].libfunc ! 3730: = gen_rtx (SYMBOL_REF, Pmode, "ffs"); ! 3731: ! 3732: #ifdef HAVE_movqi ! 3733: if (HAVE_movqi) ! 3734: mov_optab->handlers[(int) QImode].insn_code = CODE_FOR_movqi; ! 3735: #endif ! 3736: #ifdef HAVE_movhi ! 3737: if (HAVE_movhi) ! 3738: mov_optab->handlers[(int) HImode].insn_code = CODE_FOR_movhi; ! 3739: #endif ! 3740: #ifdef HAVE_movpsi ! 3741: if (HAVE_movpsi) ! 3742: mov_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movpsi; ! 3743: #endif ! 3744: #ifdef HAVE_movsi ! 3745: if (HAVE_movsi) ! 3746: mov_optab->handlers[(int) SImode].insn_code = CODE_FOR_movsi; ! 3747: #endif ! 3748: #ifdef HAVE_movdi ! 3749: if (HAVE_movdi) ! 3750: mov_optab->handlers[(int) DImode].insn_code = CODE_FOR_movdi; ! 3751: #endif ! 3752: #ifdef HAVE_movti ! 3753: if (HAVE_movti) ! 3754: mov_optab->handlers[(int) TImode].insn_code = CODE_FOR_movti; ! 3755: #endif ! 3756: #ifdef HAVE_movsf ! 3757: if (HAVE_movsf) ! 3758: mov_optab->handlers[(int) SFmode].insn_code = CODE_FOR_movsf; ! 3759: #endif ! 3760: #ifdef HAVE_movdf ! 3761: if (HAVE_movdf) ! 3762: mov_optab->handlers[(int) DFmode].insn_code = CODE_FOR_movdf; ! 3763: #endif ! 3764: #ifdef HAVE_movtf ! 3765: if (HAVE_movtf) ! 3766: mov_optab->handlers[(int) TFmode].insn_code = CODE_FOR_movtf; ! 3767: #endif ! 3768: #ifdef HAVE_movcc ! 3769: if (HAVE_movcc) ! 3770: mov_optab->handlers[(int) CCmode].insn_code = CODE_FOR_movcc; ! 3771: #endif ! 3772: ! 3773: #ifdef EXTRA_CC_MODES ! 3774: init_mov_optab (); ! 3775: #endif ! 3776: ! 3777: #ifdef HAVE_movstrictqi ! 3778: if (HAVE_movstrictqi) ! 3779: movstrict_optab->handlers[(int) QImode].insn_code = CODE_FOR_movstrictqi; ! 3780: #endif ! 3781: #ifdef HAVE_movstricthi ! 3782: if (HAVE_movstricthi) ! 3783: movstrict_optab->handlers[(int) HImode].insn_code = CODE_FOR_movstricthi; ! 3784: #endif ! 3785: #ifdef HAVE_movstrictpsi ! 3786: if (HAVE_movstrictpsi) ! 3787: movstrict_optab->handlers[(int) PSImode].insn_code = CODE_FOR_movstrictpsi; ! 3788: #endif ! 3789: #ifdef HAVE_movstrictsi ! 3790: if (HAVE_movstrictsi) ! 3791: movstrict_optab->handlers[(int) SImode].insn_code = CODE_FOR_movstrictsi; ! 3792: #endif ! 3793: #ifdef HAVE_movstrictdi ! 3794: if (HAVE_movstrictdi) ! 3795: movstrict_optab->handlers[(int) DImode].insn_code = CODE_FOR_movstrictdi; ! 3796: #endif ! 3797: #ifdef HAVE_movstrictti ! 3798: if (HAVE_movstrictti) ! 3799: movstrict_optab->handlers[(int) TImode].insn_code = CODE_FOR_movstrictti; ! 3800: #endif ! 3801: ! 3802: #ifdef HAVE_cmpqi ! 3803: if (HAVE_cmpqi) ! 3804: cmp_optab->handlers[(int) QImode].insn_code = CODE_FOR_cmpqi; ! 3805: #endif ! 3806: #ifdef HAVE_cmphi ! 3807: if (HAVE_cmphi) ! 3808: cmp_optab->handlers[(int) HImode].insn_code = CODE_FOR_cmphi; ! 3809: #endif ! 3810: #ifdef HAVE_cmppsi ! 3811: if (HAVE_cmppsi) ! 3812: cmp_optab->handlers[(int) PSImode].insn_code = CODE_FOR_cmppsi; ! 3813: #endif ! 3814: #ifdef HAVE_cmpsi ! 3815: if (HAVE_cmpsi) ! 3816: cmp_optab->handlers[(int) SImode].insn_code = CODE_FOR_cmpsi; ! 3817: #endif ! 3818: #ifdef HAVE_cmpdi ! 3819: if (HAVE_cmpdi) ! 3820: cmp_optab->handlers[(int) DImode].insn_code = CODE_FOR_cmpdi; ! 3821: #endif ! 3822: #ifdef HAVE_cmpti ! 3823: if (HAVE_cmpti) ! 3824: cmp_optab->handlers[(int) TImode].insn_code = CODE_FOR_cmpti; ! 3825: #endif ! 3826: #ifdef HAVE_cmpsf ! 3827: if (HAVE_cmpsf) ! 3828: cmp_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cmpsf; ! 3829: #endif ! 3830: #ifdef HAVE_cmpdf ! 3831: if (HAVE_cmpdf) ! 3832: cmp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cmpdf; ! 3833: #endif ! 3834: #ifdef HAVE_cmptf ! 3835: if (HAVE_cmptf) ! 3836: cmp_optab->handlers[(int) TFmode].insn_code = CODE_FOR_cmptf; ! 3837: #endif ! 3838: #ifdef HAVE_tstqi ! 3839: if (HAVE_tstqi) ! 3840: tst_optab->handlers[(int) QImode].insn_code = CODE_FOR_tstqi; ! 3841: #endif ! 3842: #ifdef HAVE_tsthi ! 3843: if (HAVE_tsthi) ! 3844: tst_optab->handlers[(int) HImode].insn_code = CODE_FOR_tsthi; ! 3845: #endif ! 3846: #ifdef HAVE_tstpsi ! 3847: if (HAVE_tstpsi) ! 3848: tst_optab->handlers[(int) PSImode].insn_code = CODE_FOR_tstpsi; ! 3849: #endif ! 3850: #ifdef HAVE_tstsi ! 3851: if (HAVE_tstsi) ! 3852: tst_optab->handlers[(int) SImode].insn_code = CODE_FOR_tstsi; ! 3853: #endif ! 3854: #ifdef HAVE_tstdi ! 3855: if (HAVE_tstdi) ! 3856: tst_optab->handlers[(int) DImode].insn_code = CODE_FOR_tstdi; ! 3857: #endif ! 3858: #ifdef HAVE_tstti ! 3859: if (HAVE_tstti) ! 3860: tst_optab->handlers[(int) TImode].insn_code = CODE_FOR_tstti; ! 3861: #endif ! 3862: #ifdef HAVE_tstsf ! 3863: if (HAVE_tstsf) ! 3864: tst_optab->handlers[(int) SFmode].insn_code = CODE_FOR_tstsf; ! 3865: #endif ! 3866: #ifdef HAVE_tstdf ! 3867: if (HAVE_tstdf) ! 3868: tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf; ! 3869: #endif ! 3870: #ifdef HAVE_tsttf ! 3871: if (HAVE_tsttf) ! 3872: tst_optab->handlers[(int) TFmode].insn_code = CODE_FOR_tsttf; ! 3873: #endif ! 3874: /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */ ! 3875: cmp_optab->handlers[(int) DImode].libfunc ! 3876: = gen_rtx (SYMBOL_REF, Pmode, "__cmpdi2"); ! 3877: ucmp_optab->handlers[(int) DImode].libfunc ! 3878: = gen_rtx (SYMBOL_REF, Pmode, "__ucmpdi2"); ! 3879: ! 3880: #ifdef HAVE_beq ! 3881: if (HAVE_beq) ! 3882: bcc_gen_fctn[(int) EQ] = gen_beq; ! 3883: #endif ! 3884: #ifdef HAVE_bne ! 3885: if (HAVE_bne) ! 3886: bcc_gen_fctn[(int) NE] = gen_bne; ! 3887: #endif ! 3888: #ifdef HAVE_bgt ! 3889: if (HAVE_bgt) ! 3890: bcc_gen_fctn[(int) GT] = gen_bgt; ! 3891: #endif ! 3892: #ifdef HAVE_bge ! 3893: if (HAVE_bge) ! 3894: bcc_gen_fctn[(int) GE] = gen_bge; ! 3895: #endif ! 3896: #ifdef HAVE_bgtu ! 3897: if (HAVE_bgtu) ! 3898: bcc_gen_fctn[(int) GTU] = gen_bgtu; ! 3899: #endif ! 3900: #ifdef HAVE_bgeu ! 3901: if (HAVE_bgeu) ! 3902: bcc_gen_fctn[(int) GEU] = gen_bgeu; ! 3903: #endif ! 3904: #ifdef HAVE_blt ! 3905: if (HAVE_blt) ! 3906: bcc_gen_fctn[(int) LT] = gen_blt; ! 3907: #endif ! 3908: #ifdef HAVE_ble ! 3909: if (HAVE_ble) ! 3910: bcc_gen_fctn[(int) LE] = gen_ble; ! 3911: #endif ! 3912: #ifdef HAVE_bltu ! 3913: if (HAVE_bltu) ! 3914: bcc_gen_fctn[(int) LTU] = gen_bltu; ! 3915: #endif ! 3916: #ifdef HAVE_bleu ! 3917: if (HAVE_bleu) ! 3918: bcc_gen_fctn[(int) LEU] = gen_bleu; ! 3919: #endif ! 3920: ! 3921: for (i = 0; i < NUM_RTX_CODE; i++) ! 3922: setcc_gen_code[i] = CODE_FOR_nothing; ! 3923: ! 3924: #ifdef HAVE_seq ! 3925: if (HAVE_seq) ! 3926: setcc_gen_code[(int) EQ] = CODE_FOR_seq; ! 3927: #endif ! 3928: #ifdef HAVE_sne ! 3929: if (HAVE_sne) ! 3930: setcc_gen_code[(int) NE] = CODE_FOR_sne; ! 3931: #endif ! 3932: #ifdef HAVE_sgt ! 3933: if (HAVE_sgt) ! 3934: setcc_gen_code[(int) GT] = CODE_FOR_sgt; ! 3935: #endif ! 3936: #ifdef HAVE_sge ! 3937: if (HAVE_sge) ! 3938: setcc_gen_code[(int) GE] = CODE_FOR_sge; ! 3939: #endif ! 3940: #ifdef HAVE_sgtu ! 3941: if (HAVE_sgtu) ! 3942: setcc_gen_code[(int) GTU] = CODE_FOR_sgtu; ! 3943: #endif ! 3944: #ifdef HAVE_sgeu ! 3945: if (HAVE_sgeu) ! 3946: setcc_gen_code[(int) GEU] = CODE_FOR_sgeu; ! 3947: #endif ! 3948: #ifdef HAVE_slt ! 3949: if (HAVE_slt) ! 3950: setcc_gen_code[(int) LT] = CODE_FOR_slt; ! 3951: #endif ! 3952: #ifdef HAVE_sle ! 3953: if (HAVE_sle) ! 3954: setcc_gen_code[(int) LE] = CODE_FOR_sle; ! 3955: #endif ! 3956: #ifdef HAVE_sltu ! 3957: if (HAVE_sltu) ! 3958: setcc_gen_code[(int) LTU] = CODE_FOR_sltu; ! 3959: #endif ! 3960: #ifdef HAVE_sleu ! 3961: if (HAVE_sleu) ! 3962: setcc_gen_code[(int) LEU] = CODE_FOR_sleu; ! 3963: #endif ! 3964: ! 3965: extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2"); ! 3966: truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2"); ! 3967: memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy"); ! 3968: bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy"); ! 3969: memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp"); ! 3970: bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcmp"); ! 3971: memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset"); ! 3972: bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero"); ! 3973: eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2"); ! 3974: nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2"); ! 3975: gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2"); ! 3976: gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2"); ! 3977: ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2"); ! 3978: lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2"); ! 3979: eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2"); ! 3980: nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2"); ! 3981: gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2"); ! 3982: gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2"); ! 3983: ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2"); ! 3984: ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2"); ! 3985: floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf"); ! 3986: floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf"); ! 3987: floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf"); ! 3988: floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf"); ! 3989: fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi"); ! 3990: fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi"); ! 3991: fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi"); ! 3992: fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi"); ! 3993: fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi"); ! 3994: fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi"); ! 3995: fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi"); ! 3996: fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi"); ! 3997: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.