|
|
1.1 root 1: /* Expand the basic unary and binary arithmetic operations, for GNU compiler. 1.1.1.6 ! root 2: Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc. 1.1 root 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" 1.1.1.5 root 30: #include "reload.h" 1.1.1.4 root 31: #include <ctype.h> 1.1 root 32: 33: /* Each optab contains info on how this target machine 34: can perform a particular operation 35: for all sizes and kinds of operands. 36: 37: The operation to be performed is often specified 38: by passing one of these optabs as an argument. 39: 40: See expr.h for documentation of these optabs. */ 41: 42: optab add_optab; 43: optab sub_optab; 44: optab smul_optab; 45: optab smul_widen_optab; 46: optab umul_widen_optab; 47: optab sdiv_optab; 48: optab sdivmod_optab; 49: optab udiv_optab; 50: optab udivmod_optab; 51: optab smod_optab; 52: optab umod_optab; 53: optab flodiv_optab; 54: optab ftrunc_optab; 55: optab and_optab; 56: optab ior_optab; 57: optab xor_optab; 58: optab ashl_optab; 59: optab lshr_optab; 60: optab lshl_optab; 61: optab ashr_optab; 62: optab rotl_optab; 63: optab rotr_optab; 64: optab smin_optab; 65: optab smax_optab; 66: optab umin_optab; 67: optab umax_optab; 68: 69: optab mov_optab; 70: optab movstrict_optab; 71: 72: optab neg_optab; 73: optab abs_optab; 74: optab one_cmpl_optab; 75: optab ffs_optab; 1.1.1.2 root 76: optab sqrt_optab; 1.1.1.4 root 77: optab sin_optab; 78: optab cos_optab; 1.1 root 79: 80: optab cmp_optab; 81: optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */ 82: optab tst_optab; 83: 1.1.1.3 root 84: optab strlen_optab; 85: 1.1.1.5 root 86: /* Tables of patterns for extending one integer mode to another. */ 87: enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2]; 88: 89: /* Tables of patterns for converting between fixed and floating point. */ 90: enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; 91: enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; 92: enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2]; 93: 1.1.1.6 ! root 94: /* Contains the optab used for each rtx code. */ ! 95: optab code_to_optab[NUM_RTX_CODE + 1]; ! 96: 1.1 root 97: /* SYMBOL_REF rtx's for the library functions that are called 98: implicitly and not via optabs. */ 99: 100: rtx extendsfdf2_libfunc; 1.1.1.4 root 101: rtx extendsfxf2_libfunc; 102: rtx extendsftf2_libfunc; 103: rtx extenddfxf2_libfunc; 104: rtx extenddftf2_libfunc; 105: 1.1 root 106: rtx truncdfsf2_libfunc; 1.1.1.4 root 107: rtx truncxfsf2_libfunc; 108: rtx trunctfsf2_libfunc; 109: rtx truncxfdf2_libfunc; 110: rtx trunctfdf2_libfunc; 111: 1.1 root 112: rtx memcpy_libfunc; 113: rtx bcopy_libfunc; 114: rtx memcmp_libfunc; 115: rtx bcmp_libfunc; 116: rtx memset_libfunc; 117: rtx bzero_libfunc; 1.1.1.4 root 118: 1.1 root 119: rtx eqsf2_libfunc; 120: rtx nesf2_libfunc; 121: rtx gtsf2_libfunc; 122: rtx gesf2_libfunc; 123: rtx ltsf2_libfunc; 124: rtx lesf2_libfunc; 1.1.1.4 root 125: 1.1 root 126: rtx eqdf2_libfunc; 127: rtx nedf2_libfunc; 128: rtx gtdf2_libfunc; 129: rtx gedf2_libfunc; 130: rtx ltdf2_libfunc; 131: rtx ledf2_libfunc; 1.1.1.4 root 132: 133: rtx eqxf2_libfunc; 134: rtx nexf2_libfunc; 135: rtx gtxf2_libfunc; 136: rtx gexf2_libfunc; 137: rtx ltxf2_libfunc; 138: rtx lexf2_libfunc; 139: 140: rtx eqtf2_libfunc; 141: rtx netf2_libfunc; 142: rtx gttf2_libfunc; 143: rtx getf2_libfunc; 144: rtx lttf2_libfunc; 145: rtx letf2_libfunc; 146: 1.1 root 147: rtx floatsisf_libfunc; 1.1.1.4 root 148: rtx floatdisf_libfunc; 149: rtx floattisf_libfunc; 150: 1.1 root 151: rtx floatsidf_libfunc; 1.1.1.4 root 152: rtx floatdidf_libfunc; 153: rtx floattidf_libfunc; 154: 155: rtx floatsixf_libfunc; 156: rtx floatdixf_libfunc; 157: rtx floattixf_libfunc; 158: 159: rtx floatsitf_libfunc; 160: rtx floatditf_libfunc; 161: rtx floattitf_libfunc; 162: 1.1 root 163: rtx fixsfsi_libfunc; 164: rtx fixsfdi_libfunc; 1.1.1.4 root 165: rtx fixsfti_libfunc; 166: 1.1 root 167: rtx fixdfsi_libfunc; 168: rtx fixdfdi_libfunc; 1.1.1.4 root 169: rtx fixdfti_libfunc; 170: 171: rtx fixxfsi_libfunc; 172: rtx fixxfdi_libfunc; 173: rtx fixxfti_libfunc; 174: 175: rtx fixtfsi_libfunc; 176: rtx fixtfdi_libfunc; 177: rtx fixtfti_libfunc; 178: 1.1 root 179: rtx fixunssfsi_libfunc; 180: rtx fixunssfdi_libfunc; 1.1.1.4 root 181: rtx fixunssfti_libfunc; 182: 1.1 root 183: rtx fixunsdfsi_libfunc; 184: rtx fixunsdfdi_libfunc; 1.1.1.4 root 185: rtx fixunsdfti_libfunc; 186: 187: rtx fixunsxfsi_libfunc; 188: rtx fixunsxfdi_libfunc; 189: rtx fixunsxfti_libfunc; 190: 191: rtx fixunstfsi_libfunc; 192: rtx fixunstfdi_libfunc; 193: rtx fixunstfti_libfunc; 194: 195: /* from emit-rtl.c */ 196: extern rtx gen_highpart (); 1.1 root 197: 198: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) 199: gives the gen_function to make a branch to test that condition. */ 200: 201: rtxfun bcc_gen_fctn[NUM_RTX_CODE]; 202: 203: /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) 204: gives the insn code to make a store-condition insn 205: to test that condition. */ 206: 207: enum insn_code setcc_gen_code[NUM_RTX_CODE]; 208: 1.1.1.5 root 209: static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx)); 1.1.1.6 ! root 210: static rtx widen_operand PROTO((rtx, enum machine_mode, enum machine_mode, int, int)); 1.1.1.5 root 211: static void emit_float_lib_cmp PROTO((rtx, rtx, enum rtx_code)); 212: static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode, 213: int, int *)); 214: static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode, 215: int)); 216: static rtx ftruncify PROTO((rtx)); 217: static optab init_optab PROTO((enum rtx_code)); 218: static void init_libfuncs PROTO((optab, int, int, char *, int)); 219: static void init_integral_libfuncs PROTO((optab, char *, int)); 220: static void init_floating_libfuncs PROTO((optab, char *, int)); 221: static void init_complex_libfuncs PROTO((optab, char *, int)); 1.1 root 222: 223: /* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to 224: the result of operation CODE applied to OP0 (and OP1 if it is a binary 225: operation). 226: 227: If the last insn does not set TARGET, don't do anything, but return 1. 228: 229: If a previous insn sets TARGET and TARGET is one of OP0 or OP1, 230: don't add the REG_EQUAL note but return 0. Our caller can then try 231: again, ensuring that TARGET is not one of the operands. */ 232: 233: static int 234: add_equal_note (seq, target, code, op0, op1) 235: rtx seq; 236: rtx target; 237: enum rtx_code code; 238: rtx op0, op1; 239: { 240: rtx set; 241: int i; 242: rtx note; 243: 244: if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2' 245: && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<') 246: || GET_CODE (seq) != SEQUENCE 247: || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0 248: || GET_CODE (target) == ZERO_EXTRACT 249: || (! rtx_equal_p (SET_DEST (set), target) 250: /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the 251: SUBREG. */ 252: && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART 253: || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)), 254: target)))) 255: return 1; 256: 257: /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET 258: besides the last insn. */ 259: if (reg_overlap_mentioned_p (target, op0) 260: || (op1 && reg_overlap_mentioned_p (target, op1))) 261: for (i = XVECLEN (seq, 0) - 2; i >= 0; i--) 262: if (reg_set_p (target, XVECEXP (seq, 0, i))) 263: return 0; 264: 265: if (GET_RTX_CLASS (code) == '1') 1.1.1.5 root 266: note = gen_rtx (code, GET_MODE (target), copy_rtx (op0)); 1.1 root 267: else 1.1.1.5 root 268: note = gen_rtx (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1)); 1.1 root 269: 270: REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)) 271: = gen_rtx (EXPR_LIST, REG_EQUAL, note, 272: REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))); 273: 274: return 1; 275: } 276: 1.1.1.6 ! root 277: /* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP ! 278: says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need ! 279: not actually do a sign-extend or zero-extend, but can leave the ! 280: higher-order bits of the result rtx undefined, for example, in the case ! 281: of logical operations, but not right shifts. */ ! 282: ! 283: static rtx ! 284: widen_operand (op, mode, oldmode, unsignedp, no_extend) ! 285: rtx op; ! 286: enum machine_mode mode, oldmode; ! 287: int unsignedp; ! 288: int no_extend; ! 289: { ! 290: rtx result; ! 291: ! 292: /* If we must extend do so. If OP is either a constant or a SUBREG ! 293: for a promoted object, also extend since it will be more efficient to ! 294: do so. */ ! 295: if (! no_extend ! 296: || GET_MODE (op) == VOIDmode ! 297: || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op))) ! 298: return convert_modes (mode, oldmode, op, unsignedp); ! 299: ! 300: /* If MODE is no wider than a single word, we return a paradoxical ! 301: SUBREG. */ ! 302: if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) ! 303: return gen_rtx (SUBREG, mode, force_reg (GET_MODE (op), op), 0); ! 304: ! 305: /* Otherwise, get an object of MODE, clobber it, and set the low-order ! 306: part to OP. */ ! 307: ! 308: result = gen_reg_rtx (mode); ! 309: emit_insn (gen_rtx (CLOBBER, VOIDmode, result)); ! 310: emit_move_insn (gen_lowpart (GET_MODE (op), result), op); ! 311: return result; ! 312: } ! 313: 1.1 root 314: /* Generate code to perform an operation specified by BINOPTAB 315: on operands OP0 and OP1, with result having machine-mode MODE. 316: 317: UNSIGNEDP is for the case where we have to widen the operands 318: to perform the operation. It says to use zero-extension. 319: 320: If TARGET is nonzero, the value 321: is generated there, if it is convenient to do so. 322: In all cases an rtx is returned for the locus of the value; 323: this may or may not be TARGET. */ 324: 325: rtx 326: expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods) 327: enum machine_mode mode; 328: optab binoptab; 329: rtx op0, op1; 330: rtx target; 331: int unsignedp; 332: enum optab_methods methods; 333: { 334: enum mode_class class; 335: enum machine_mode wider_mode; 336: register rtx temp; 337: int commutative_op = 0; 338: int shift_op = (binoptab->code == ASHIFT 339: || binoptab->code == ASHIFTRT 340: || binoptab->code == LSHIFT 341: || binoptab->code == LSHIFTRT 342: || binoptab->code == ROTATE 343: || binoptab->code == ROTATERT); 1.1.1.4 root 344: rtx entry_last = get_last_insn (); 1.1 root 345: rtx last; 346: 347: class = GET_MODE_CLASS (mode); 348: 349: op0 = protect_from_queue (op0, 0); 350: op1 = protect_from_queue (op1, 0); 351: if (target) 352: target = protect_from_queue (target, 1); 353: 354: if (flag_force_mem) 355: { 356: op0 = force_not_mem (op0); 357: op1 = force_not_mem (op1); 358: } 359: 1.1.1.4 root 360: /* If subtracting an integer constant, convert this into an addition of 361: the negated constant. */ 362: 363: if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT) 364: { 365: op1 = negate_rtx (mode, op1); 366: binoptab = add_optab; 367: } 368: 1.1 root 369: /* If we are inside an appropriately-short loop and one operand is an 370: expensive constant, force it into a register. */ 1.1.1.3 root 371: if (CONSTANT_P (op0) && preserve_subexpressions_p () 372: && rtx_cost (op0, binoptab->code) > 2) 1.1 root 373: op0 = force_reg (mode, op0); 374: 1.1.1.3 root 375: if (CONSTANT_P (op1) && preserve_subexpressions_p () 376: && rtx_cost (op1, binoptab->code) > 2) 1.1 root 377: op1 = force_reg (shift_op ? word_mode : mode, op1); 378: 379: /* Record where to delete back to if we backtrack. */ 380: last = get_last_insn (); 381: 382: /* If operation is commutative, 383: try to make the first operand a register. 384: Even better, try to make it the same as the target. 385: Also try to make the last operand a constant. */ 386: if (GET_RTX_CLASS (binoptab->code) == 'c' 387: || binoptab == smul_widen_optab 388: || binoptab == umul_widen_optab) 389: { 390: commutative_op = 1; 391: 392: if (((target == 0 || GET_CODE (target) == REG) 393: ? ((GET_CODE (op1) == REG 394: && GET_CODE (op0) != REG) 395: || target == op1) 396: : rtx_equal_p (op1, target)) 397: || GET_CODE (op0) == CONST_INT) 398: { 399: temp = op1; 400: op1 = op0; 401: op0 = temp; 402: } 403: } 404: 405: /* If we can do it with a three-operand insn, do so. */ 406: 407: if (methods != OPTAB_MUST_WIDEN 408: && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 409: { 410: int icode = (int) binoptab->handlers[(int) mode].insn_code; 411: enum machine_mode mode0 = insn_operand_mode[icode][1]; 412: enum machine_mode mode1 = insn_operand_mode[icode][2]; 413: rtx pat; 414: rtx xop0 = op0, xop1 = op1; 415: 416: if (target) 417: temp = target; 418: else 419: temp = gen_reg_rtx (mode); 420: 421: /* If it is a commutative operator and the modes would match 422: if we would swap the operands, we can save the conversions. */ 423: if (commutative_op) 424: { 425: if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1 426: && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0) 427: { 428: register rtx tmp; 429: 430: tmp = op0; op0 = op1; op1 = tmp; 431: tmp = xop0; xop0 = xop1; xop1 = tmp; 432: } 433: } 434: 435: /* In case the insn wants input operands in modes different from 436: the result, convert the operands. */ 437: 438: if (GET_MODE (op0) != VOIDmode 439: && GET_MODE (op0) != mode0) 440: xop0 = convert_to_mode (mode0, xop0, unsignedp); 441: 442: if (GET_MODE (xop1) != VOIDmode 443: && GET_MODE (xop1) != mode1) 444: xop1 = convert_to_mode (mode1, xop1, unsignedp); 445: 446: /* Now, if insn's predicates don't allow our operands, put them into 447: pseudo regs. */ 448: 449: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) 450: xop0 = copy_to_mode_reg (mode0, xop0); 451: 452: if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)) 453: xop1 = copy_to_mode_reg (mode1, xop1); 454: 455: if (! (*insn_operand_predicate[icode][0]) (temp, mode)) 456: temp = gen_reg_rtx (mode); 457: 458: pat = GEN_FCN (icode) (temp, xop0, xop1); 459: if (pat) 460: { 461: /* If PAT is a multi-insn sequence, try to add an appropriate 462: REG_EQUAL note to it. If we can't because TEMP conflicts with an 463: operand, call ourselves again, this time without a target. */ 464: if (GET_CODE (pat) == SEQUENCE 465: && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1)) 466: { 467: delete_insns_since (last); 1.1.1.4 root 468: return expand_binop (mode, binoptab, op0, op1, NULL_RTX, 469: unsignedp, methods); 1.1 root 470: } 471: 472: emit_insn (pat); 473: return temp; 474: } 475: else 476: delete_insns_since (last); 477: } 478: 1.1.1.4 root 479: /* If this is a multiply, see if we can do a widening operation that 480: takes operands of this mode and makes a wider mode. */ 481: 482: if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode 483: && (((unsignedp ? umul_widen_optab : smul_widen_optab) 484: ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code) 485: != CODE_FOR_nothing)) 486: { 487: temp = expand_binop (GET_MODE_WIDER_MODE (mode), 488: unsignedp ? umul_widen_optab : smul_widen_optab, 489: op0, op1, 0, unsignedp, OPTAB_DIRECT); 490: 491: if (GET_MODE_CLASS (mode) == MODE_INT) 492: return gen_lowpart (mode, temp); 493: else 494: return convert_to_mode (mode, temp, unsignedp); 495: } 496: 497: /* Look for a wider mode of the same class for which we think we 498: can open-code the operation. Check for a widening multiply at the 499: wider mode as well. */ 500: 501: if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 502: && methods != OPTAB_DIRECT && methods != OPTAB_LIB) 503: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 504: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 505: { 506: if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing 507: || (binoptab == smul_optab 508: && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode 509: && (((unsignedp ? umul_widen_optab : smul_widen_optab) 510: ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code) 511: != CODE_FOR_nothing))) 512: { 513: rtx xop0 = op0, xop1 = op1; 514: int no_extend = 0; 515: 516: /* For certain integer operations, we need not actually extend 517: the narrow operands, as long as we will truncate 1.1.1.6 ! root 518: the results to the same narrowness. */ 1.1.1.4 root 519: 520: if ((binoptab == ior_optab || binoptab == and_optab 521: || binoptab == xor_optab 522: || binoptab == add_optab || binoptab == sub_optab 523: || binoptab == smul_optab 524: || binoptab == ashl_optab || binoptab == lshl_optab) 1.1.1.6 ! root 525: && class == MODE_INT) 1.1.1.4 root 526: no_extend = 1; 527: 1.1.1.6 ! root 528: xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend); 1.1.1.4 root 529: 1.1.1.6 ! root 530: /* The second operand of a shift must always be extended. */ ! 531: xop1 = widen_operand (xop1, wider_mode, mode, unsignedp, ! 532: no_extend && binoptab != ashl_optab ! 533: && binoptab != lshl_optab); 1.1.1.4 root 534: 535: temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX, 536: unsignedp, OPTAB_DIRECT); 537: if (temp) 538: { 539: if (class != MODE_INT) 540: { 541: if (target == 0) 542: target = gen_reg_rtx (mode); 543: convert_move (target, temp, 0); 544: return target; 545: } 546: else 547: return gen_lowpart (mode, temp); 548: } 549: else 550: delete_insns_since (last); 551: } 552: } 553: 1.1 root 554: /* These can be done a word at a time. */ 555: if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab) 556: && class == MODE_INT 557: && GET_MODE_SIZE (mode) > UNITS_PER_WORD 558: && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) 559: { 560: int i; 561: rtx insns; 562: rtx equiv_value; 563: 564: /* If TARGET is the same as one of the operands, the REG_EQUAL note 565: won't be accurate, so use a new target. */ 566: if (target == 0 || target == op0 || target == op1) 567: target = gen_reg_rtx (mode); 568: 569: start_sequence (); 570: 571: /* Do the actual arithmetic. */ 572: for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++) 573: { 574: rtx target_piece = operand_subword (target, i, 1, mode); 575: rtx x = expand_binop (word_mode, binoptab, 576: operand_subword_force (op0, i, mode), 577: operand_subword_force (op1, i, mode), 578: target_piece, unsignedp, methods); 579: if (target_piece != x) 580: emit_move_insn (target_piece, x); 581: } 582: 583: insns = get_insns (); 584: end_sequence (); 585: 586: if (binoptab->code != UNKNOWN) 1.1.1.5 root 587: equiv_value 588: = gen_rtx (binoptab->code, mode, copy_rtx (op0), copy_rtx (op1)); 1.1 root 589: else 590: equiv_value = 0; 591: 592: emit_no_conflict_block (insns, target, op0, op1, equiv_value); 593: return target; 594: } 595: 1.1.1.6 ! root 596: /* Synthesize double word shifts from single word shifts. */ ! 597: if ((binoptab == lshl_optab || binoptab == lshr_optab ! 598: || binoptab == ashl_optab || binoptab == ashr_optab) ! 599: && class == MODE_INT ! 600: && GET_CODE (op1) == CONST_INT ! 601: && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD ! 602: && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing ! 603: && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing ! 604: && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) ! 605: { ! 606: rtx insns, equiv_value; ! 607: rtx into_target, outof_target; ! 608: rtx into_input, outof_input; ! 609: int shift_count, left_shift, outof_word; ! 610: ! 611: /* If TARGET is the same as one of the operands, the REG_EQUAL note ! 612: won't be accurate, so use a new target. */ ! 613: if (target == 0 || target == op0 || target == op1) ! 614: target = gen_reg_rtx (mode); ! 615: ! 616: start_sequence (); ! 617: ! 618: shift_count = INTVAL (op1); ! 619: ! 620: /* OUTOF_* is the word we are shifting bits away from, and ! 621: INTO_* is the word that we are shifting bits towards, thus ! 622: they differ depending on the direction of the shift and ! 623: WORDS_BIG_ENDIAN. */ ! 624: ! 625: left_shift = (binoptab == ashl_optab || binoptab == lshl_optab); ! 626: outof_word = left_shift ^ ! WORDS_BIG_ENDIAN; ! 627: ! 628: outof_target = operand_subword (target, outof_word, 1, mode); ! 629: into_target = operand_subword (target, 1 - outof_word, 1, mode); ! 630: ! 631: outof_input = operand_subword_force (op0, outof_word, mode); ! 632: into_input = operand_subword_force (op0, 1 - outof_word, mode); ! 633: ! 634: if (shift_count >= BITS_PER_WORD) ! 635: { ! 636: emit_move_insn (into_target, ! 637: expand_binop (word_mode, binoptab, ! 638: outof_input, ! 639: GEN_INT (shift_count - BITS_PER_WORD), ! 640: into_target, unsignedp, methods)); ! 641: ! 642: /* For a signed right shift, we must fill the word we are shifting ! 643: out of with copies of the sign bit. Otherwise it is zeroed. */ ! 644: if (binoptab != ashr_optab) ! 645: emit_move_insn (outof_target, CONST0_RTX (word_mode)); ! 646: else ! 647: emit_move_insn (outof_target, ! 648: expand_binop (word_mode, binoptab, ! 649: outof_input, ! 650: GEN_INT (BITS_PER_WORD - 1), ! 651: outof_target, unsignedp, methods)); ! 652: } ! 653: else ! 654: { ! 655: rtx carries, into_temp; ! 656: optab reverse_unsigned_shift, unsigned_shift; ! 657: ! 658: /* For a shift of less then BITS_PER_WORD, to compute the carry, ! 659: we must do a logical shift in the opposite direction of the ! 660: desired shift. */ ! 661: ! 662: /* We use ashl_optab instead of lshl_optab, because ashl is ! 663: guaranteed to exist, but lshl may or may not exist. */ ! 664: ! 665: reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab); ! 666: ! 667: /* For a shift of less than BITS_PER_WORD, to compute the word ! 668: shifted towards, we need to unsigned shift the orig value of ! 669: that word. */ ! 670: ! 671: unsigned_shift = (left_shift ? ashl_optab : lshr_optab); ! 672: ! 673: carries = expand_binop (word_mode, reverse_unsigned_shift, ! 674: outof_input, ! 675: GEN_INT (BITS_PER_WORD - shift_count), ! 676: 0, unsignedp, methods); ! 677: ! 678: emit_move_insn (outof_target, ! 679: expand_binop (word_mode, binoptab, ! 680: outof_input, ! 681: op1, outof_target, unsignedp, methods)); ! 682: into_temp = expand_binop (word_mode, unsigned_shift, ! 683: into_input, ! 684: op1, 0, unsignedp, methods); ! 685: ! 686: emit_move_insn (into_target, ! 687: expand_binop (word_mode, ior_optab, ! 688: carries, into_temp, ! 689: into_target, unsignedp, methods)); ! 690: } ! 691: ! 692: insns = get_insns (); ! 693: end_sequence (); ! 694: ! 695: if (binoptab->code != UNKNOWN) ! 696: equiv_value = gen_rtx (binoptab->code, mode, op0, op1); ! 697: else ! 698: equiv_value = 0; ! 699: ! 700: emit_no_conflict_block (insns, target, op0, op1, equiv_value); ! 701: return target; ! 702: } ! 703: ! 704: /* Synthesize double word rotates from single word shifts. */ ! 705: if ((binoptab == rotl_optab || binoptab == rotr_optab) ! 706: && class == MODE_INT ! 707: && GET_CODE (op1) == CONST_INT ! 708: && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD ! 709: && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing ! 710: && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) ! 711: { ! 712: rtx insns, equiv_value; ! 713: rtx into_target, outof_target; ! 714: rtx into_input, outof_input; ! 715: int shift_count, left_shift, outof_word; ! 716: ! 717: /* If TARGET is the same as one of the operands, the REG_EQUAL note ! 718: won't be accurate, so use a new target. */ ! 719: if (target == 0 || target == op0 || target == op1) ! 720: target = gen_reg_rtx (mode); ! 721: ! 722: start_sequence (); ! 723: ! 724: shift_count = INTVAL (op1); ! 725: ! 726: /* OUTOF_* is the word we are shifting bits away from, and ! 727: INTO_* is the word that we are shifting bits towards, thus ! 728: they differ depending on the direction of the shift and ! 729: WORDS_BIG_ENDIAN. */ ! 730: ! 731: left_shift = (binoptab == rotl_optab); ! 732: outof_word = left_shift ^ ! WORDS_BIG_ENDIAN; ! 733: ! 734: outof_target = operand_subword (target, outof_word, 1, mode); ! 735: into_target = operand_subword (target, 1 - outof_word, 1, mode); ! 736: ! 737: outof_input = operand_subword_force (op0, outof_word, mode); ! 738: into_input = operand_subword_force (op0, 1 - outof_word, mode); ! 739: ! 740: if (shift_count == BITS_PER_WORD) ! 741: { ! 742: /* This is just a word swap. */ ! 743: emit_move_insn (outof_target, into_input); ! 744: emit_move_insn (into_target, outof_input); ! 745: } ! 746: else ! 747: { ! 748: rtx into_temp1, into_temp2, outof_temp1, outof_temp2; ! 749: rtx first_shift_count, second_shift_count; ! 750: optab reverse_unsigned_shift, unsigned_shift; ! 751: ! 752: reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD) ! 753: ? lshr_optab : ashl_optab); ! 754: ! 755: unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD) ! 756: ? ashl_optab : lshr_optab); ! 757: ! 758: if (shift_count > BITS_PER_WORD) ! 759: { ! 760: first_shift_count = GEN_INT (shift_count - BITS_PER_WORD); ! 761: second_shift_count = GEN_INT (2*BITS_PER_WORD - shift_count); ! 762: } ! 763: else ! 764: { ! 765: first_shift_count = GEN_INT (BITS_PER_WORD - shift_count); ! 766: second_shift_count = GEN_INT (shift_count); ! 767: } ! 768: ! 769: into_temp1 = expand_binop (word_mode, unsigned_shift, ! 770: outof_input, first_shift_count, ! 771: 0, unsignedp, methods); ! 772: into_temp2 = expand_binop (word_mode, reverse_unsigned_shift, ! 773: into_input, second_shift_count, ! 774: into_target, unsignedp, methods); ! 775: emit_move_insn (into_target, ! 776: expand_binop (word_mode, ior_optab, ! 777: into_temp1, into_temp2, ! 778: into_target, unsignedp, methods)); ! 779: ! 780: outof_temp1 = expand_binop (word_mode, unsigned_shift, ! 781: into_input, first_shift_count, ! 782: 0, unsignedp, methods); ! 783: outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift, ! 784: outof_input, second_shift_count, ! 785: outof_target, unsignedp, methods); ! 786: emit_move_insn (outof_target, ! 787: expand_binop (word_mode, ior_optab, ! 788: outof_temp1, outof_temp2, ! 789: outof_target, unsignedp, methods)); ! 790: } ! 791: ! 792: insns = get_insns (); ! 793: end_sequence (); ! 794: ! 795: if (binoptab->code != UNKNOWN) ! 796: equiv_value = gen_rtx (binoptab->code, mode, op0, op1); ! 797: else ! 798: equiv_value = 0; ! 799: ! 800: /* We can't make this a no conflict block if this is a word swap, ! 801: because the word swap case fails if the input and output values ! 802: are in the same register. */ ! 803: if (shift_count != BITS_PER_WORD) ! 804: emit_no_conflict_block (insns, target, op0, op1, equiv_value); ! 805: else ! 806: emit_insns (insns); ! 807: return target; ! 808: } ! 809: 1.1 root 810: /* These can be done a word at a time by propagating carries. */ 811: if ((binoptab == add_optab || binoptab == sub_optab) 812: && class == MODE_INT 813: && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD 814: && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) 815: { 816: int i; 817: rtx carry_tmp = gen_reg_rtx (word_mode); 818: optab otheroptab = binoptab == add_optab ? sub_optab : add_optab; 819: int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; 820: rtx carry_in, carry_out; 1.1.1.4 root 821: rtx xop0, xop1; 1.1 root 822: 823: /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG 824: value is one of those, use it. Otherwise, use 1 since it is the 825: one easiest to get. */ 826: #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1 827: int normalizep = STORE_FLAG_VALUE; 828: #else 829: int normalizep = 1; 830: #endif 831: 832: /* Prepare the operands. */ 1.1.1.4 root 833: xop0 = force_reg (mode, op0); 834: xop1 = force_reg (mode, op1); 1.1 root 835: 836: if (target == 0 || GET_CODE (target) != REG 1.1.1.4 root 837: || target == xop0 || target == xop1) 1.1 root 838: target = gen_reg_rtx (mode); 839: 1.1.1.5 root 840: /* Indicate for flow that the entire target reg is being set. */ 841: if (GET_CODE (target) == REG) 842: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); 843: 1.1 root 844: /* Do the actual arithmetic. */ 845: for (i = 0; i < nwords; i++) 846: { 847: int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i); 848: rtx target_piece = operand_subword (target, index, 1, mode); 1.1.1.4 root 849: rtx op0_piece = operand_subword_force (xop0, index, mode); 850: rtx op1_piece = operand_subword_force (xop1, index, mode); 1.1 root 851: rtx x; 852: 853: /* Main add/subtract of the input operands. */ 854: x = expand_binop (word_mode, binoptab, 855: op0_piece, op1_piece, 856: target_piece, unsignedp, methods); 857: if (x == 0) 858: break; 859: 860: if (i + 1 < nwords) 861: { 862: /* Store carry from main add/subtract. */ 863: carry_out = gen_reg_rtx (word_mode); 864: carry_out = emit_store_flag (carry_out, 865: binoptab == add_optab ? LTU : GTU, 866: x, op0_piece, 867: word_mode, 1, normalizep); 868: if (!carry_out) 869: break; 870: } 871: 872: if (i > 0) 873: { 874: /* Add/subtract previous carry to main result. */ 875: x = expand_binop (word_mode, 876: normalizep == 1 ? binoptab : otheroptab, 877: x, carry_in, 878: target_piece, 1, methods); 879: if (target_piece != x) 880: emit_move_insn (target_piece, x); 881: 882: if (i + 1 < nwords) 883: { 884: /* THIS CODE HAS NOT BEEN TESTED. */ 885: /* Get out carry from adding/subtracting carry in. */ 886: carry_tmp = emit_store_flag (carry_tmp, 887: binoptab == add_optab 888: ? LTU : GTU, 889: x, carry_in, 890: word_mode, 1, normalizep); 891: /* Logical-ior the two poss. carry together. */ 892: carry_out = expand_binop (word_mode, ior_optab, 893: carry_out, carry_tmp, 894: carry_out, 0, methods); 895: if (!carry_out) 896: break; 897: } 898: } 899: 900: carry_in = carry_out; 901: } 902: 903: if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD) 904: { 905: rtx temp; 906: 907: temp = emit_move_insn (target, target); 908: REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL, 1.1.1.5 root 909: gen_rtx (binoptab->code, mode, 910: copy_rtx (xop0), 911: copy_rtx (xop1)), 1.1 root 912: REG_NOTES (temp)); 913: return target; 914: } 915: else 916: delete_insns_since (last); 917: } 918: 919: /* If we want to multiply two two-word values and have normal and widening 920: multiplies of single-word values, we can do this with three smaller 921: multiplications. Note that we do not make a REG_NO_CONFLICT block here 922: because we are not operating on one word at a time. 923: 924: The multiplication proceeds as follows: 925: _______________________ 926: [__op0_high_|__op0_low__] 927: _______________________ 1.1.1.5 root 928: * [__op1_high_|__op1_low__] 1.1 root 929: _______________________________________________ 930: _______________________ 1.1.1.5 root 931: (1) [__op0_low__*__op1_low__] 1.1 root 932: _______________________ 1.1.1.5 root 933: (2a) [__op0_low__*__op1_high_] 1.1 root 934: _______________________ 1.1.1.5 root 935: (2b) [__op0_high_*__op1_low__] 1.1 root 936: _______________________ 937: (3) [__op0_high_*__op1_high_] 938: 939: 940: This gives a 4-word result. Since we are only interested in the 941: lower 2 words, partial result (3) and the upper words of (2a) and 942: (2b) don't need to be calculated. Hence (2a) and (2b) can be 943: calculated using non-widening multiplication. 944: 945: (1), however, needs to be calculated with an unsigned widening 946: multiplication. If this operation is not directly supported we 947: try using a signed widening multiplication and adjust the result. 948: This adjustment works as follows: 949: 950: If both operands are positive then no adjustment is needed. 951: 952: If the operands have different signs, for example op0_low < 0 and 953: op1_low >= 0, the instruction treats the most significant bit of 954: op0_low as a sign bit instead of a bit with significance 955: 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low 956: with 2**BITS_PER_WORD - op0_low, and two's complements the 957: result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to 958: the result. 959: 960: Similarly, if both operands are negative, we need to add 961: (op0_low + op1_low) * 2**BITS_PER_WORD. 962: 963: We use a trick to adjust quickly. We logically shift op0_low right 964: (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to 965: op0_high (op1_high) before it is used to calculate 2b (2a). If no 966: logical shift exists, we do an arithmetic right shift and subtract 967: the 0 or -1. */ 968: 969: if (binoptab == smul_optab 970: && class == MODE_INT 971: && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD 972: && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing 973: && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing 974: && ((umul_widen_optab->handlers[(int) mode].insn_code 975: != CODE_FOR_nothing) 976: || (smul_widen_optab->handlers[(int) mode].insn_code 977: != CODE_FOR_nothing))) 978: { 979: int low = (WORDS_BIG_ENDIAN ? 1 : 0); 980: int high = (WORDS_BIG_ENDIAN ? 0 : 1); 981: rtx op0_high = operand_subword_force (op0, high, mode); 982: rtx op0_low = operand_subword_force (op0, low, mode); 983: rtx op1_high = operand_subword_force (op1, high, mode); 984: rtx op1_low = operand_subword_force (op1, low, mode); 985: rtx product = 0; 986: rtx op0_xhigh; 987: rtx op1_xhigh; 988: 989: /* If the target is the same as one of the inputs, don't use it. This 990: prevents problems with the REG_EQUAL note. */ 991: if (target == op0 || target == op1) 992: target = 0; 993: 994: /* Multiply the two lower words to get a double-word product. 995: If unsigned widening multiplication is available, use that; 996: otherwise use the signed form and compensate. */ 997: 998: if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 999: { 1000: product = expand_binop (mode, umul_widen_optab, op0_low, op1_low, 1001: target, 1, OPTAB_DIRECT); 1002: 1003: /* If we didn't succeed, delete everything we did so far. */ 1004: if (product == 0) 1005: delete_insns_since (last); 1006: else 1007: op0_xhigh = op0_high, op1_xhigh = op1_high; 1008: } 1009: 1010: if (product == 0 1011: && smul_widen_optab->handlers[(int) mode].insn_code 1012: != CODE_FOR_nothing) 1013: { 1.1.1.4 root 1014: rtx wordm1 = GEN_INT (BITS_PER_WORD - 1); 1.1 root 1015: product = expand_binop (mode, smul_widen_optab, op0_low, op1_low, 1016: target, 1, OPTAB_DIRECT); 1017: op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1, 1.1.1.4 root 1018: NULL_RTX, 1, OPTAB_DIRECT); 1.1 root 1019: if (op0_xhigh) 1020: op0_xhigh = expand_binop (word_mode, add_optab, op0_high, 1021: op0_xhigh, op0_xhigh, 0, OPTAB_DIRECT); 1022: else 1023: { 1024: op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1, 1.1.1.4 root 1025: NULL_RTX, 0, OPTAB_DIRECT); 1.1 root 1026: if (op0_xhigh) 1027: op0_xhigh = expand_binop (word_mode, sub_optab, op0_high, 1028: op0_xhigh, op0_xhigh, 0, 1029: OPTAB_DIRECT); 1030: } 1031: 1032: op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1, 1.1.1.4 root 1033: NULL_RTX, 1, OPTAB_DIRECT); 1.1 root 1034: if (op1_xhigh) 1035: op1_xhigh = expand_binop (word_mode, add_optab, op1_high, 1036: op1_xhigh, op1_xhigh, 0, OPTAB_DIRECT); 1037: else 1038: { 1039: op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1, 1.1.1.4 root 1040: NULL_RTX, 0, OPTAB_DIRECT); 1.1 root 1041: if (op1_xhigh) 1042: op1_xhigh = expand_binop (word_mode, sub_optab, op1_high, 1043: op1_xhigh, op1_xhigh, 0, 1044: OPTAB_DIRECT); 1045: } 1046: } 1047: 1048: /* If we have been able to directly compute the product of the 1049: low-order words of the operands and perform any required adjustments 1050: of the operands, we proceed by trying two more multiplications 1051: and then computing the appropriate sum. 1052: 1053: We have checked above that the required addition is provided. 1054: Full-word addition will normally always succeed, especially if 1055: it is provided at all, so we don't worry about its failure. The 1056: multiplication may well fail, however, so we do handle that. */ 1057: 1058: if (product && op0_xhigh && op1_xhigh) 1059: { 1060: rtx product_piece; 1061: rtx product_high = operand_subword (product, high, 1, mode); 1.1.1.4 root 1062: rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh, 1063: NULL_RTX, 0, OPTAB_DIRECT); 1.1 root 1064: 1065: if (temp) 1066: { 1067: product_piece = expand_binop (word_mode, add_optab, temp, 1068: product_high, product_high, 1069: 0, OPTAB_LIB_WIDEN); 1070: if (product_piece != product_high) 1071: emit_move_insn (product_high, product_piece); 1072: 1.1.1.4 root 1073: temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh, 1074: NULL_RTX, 0, OPTAB_DIRECT); 1.1 root 1075: 1076: product_piece = expand_binop (word_mode, add_optab, temp, 1077: product_high, product_high, 1078: 0, OPTAB_LIB_WIDEN); 1079: if (product_piece != product_high) 1080: emit_move_insn (product_high, product_piece); 1081: 1082: temp = emit_move_insn (product, product); 1083: REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL, 1.1.1.5 root 1084: gen_rtx (MULT, mode, copy_rtx (op0), 1085: copy_rtx (op1)), 1.1 root 1086: REG_NOTES (temp)); 1087: 1088: return product; 1089: } 1090: } 1091: 1092: /* If we get here, we couldn't do it for some reason even though we 1093: originally thought we could. Delete anything we've emitted in 1094: trying to do it. */ 1095: 1096: delete_insns_since (last); 1097: } 1098: 1.1.1.4 root 1099: /* We need to open-code the complex type operations: '+, -, * and /' */ 1100: 1101: /* At this point we allow operations between two similar complex 1102: numbers, and also if one of the operands is not a complex number 1103: but rather of MODE_FLOAT or MODE_INT. However, the caller 1104: must make sure that the MODE of the non-complex operand matches 1105: the SUBMODE of the complex operand. */ 1106: 1107: if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT) 1108: { 1109: rtx real0 = (rtx) 0; 1110: rtx imag0 = (rtx) 0; 1111: rtx real1 = (rtx) 0; 1112: rtx imag1 = (rtx) 0; 1113: rtx realr; 1114: rtx imagr; 1115: rtx res; 1116: rtx seq; 1117: rtx equiv_value; 1118: 1119: /* Find the correct mode for the real and imaginary parts */ 1120: enum machine_mode submode 1121: = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, 1122: class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, 1123: 0); 1124: 1125: if (submode == BLKmode) 1126: abort (); 1127: 1128: if (! target) 1129: target = gen_reg_rtx (mode); 1130: 1131: start_sequence (); 1132: 1133: realr = gen_realpart (submode, target); 1134: imagr = gen_imagpart (submode, target); 1135: 1136: if (GET_MODE (op0) == mode) 1137: { 1138: real0 = gen_realpart (submode, op0); 1139: imag0 = gen_imagpart (submode, op0); 1140: } 1141: else 1142: real0 = op0; 1143: 1144: if (GET_MODE (op1) == mode) 1145: { 1146: real1 = gen_realpart (submode, op1); 1147: imag1 = gen_imagpart (submode, op1); 1148: } 1149: else 1150: real1 = op1; 1151: 1152: if (! real0 || ! real1 || ! (imag0 || imag1)) 1153: abort (); 1154: 1155: switch (binoptab->code) 1156: { 1157: case PLUS: 1.1.1.5 root 1158: /* (a+ib) + (c+id) = (a+c) + i(b+d) */ 1.1.1.4 root 1159: case MINUS: 1.1.1.5 root 1160: /* (a+ib) - (c+id) = (a-c) + i(b-d) */ 1.1.1.4 root 1161: res = expand_binop (submode, binoptab, real0, real1, 1162: realr, unsignedp, methods); 1163: if (res != realr) 1164: emit_move_insn (realr, res); 1165: 1166: if (imag0 && imag1) 1167: res = expand_binop (submode, binoptab, imag0, imag1, 1168: imagr, unsignedp, methods); 1169: else if (imag0) 1170: res = imag0; 1171: else if (binoptab->code == MINUS) 1172: res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp); 1173: else 1174: res = imag1; 1175: 1176: if (res != imagr) 1177: emit_move_insn (imagr, res); 1178: break; 1179: 1180: case MULT: 1181: /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */ 1182: 1183: if (imag0 && imag1) 1184: { 1.1.1.5 root 1185: /* Don't fetch these from memory more than once. */ 1186: real0 = force_reg (submode, real0); 1187: real1 = force_reg (submode, real1); 1188: imag0 = force_reg (submode, imag0); 1189: imag1 = force_reg (submode, imag1); 1190: 1191: res = expand_binop (submode, sub_optab, 1192: expand_binop (submode, binoptab, real0, 1193: real1, 0, unsignedp, methods), 1194: expand_binop (submode, binoptab, imag0, 1195: imag1, 0, unsignedp, methods), 1196: realr, unsignedp, methods); 1.1.1.4 root 1197: 1.1.1.5 root 1198: if (res != realr) 1199: emit_move_insn (realr, res); 1.1.1.4 root 1200: 1201: res = expand_binop (submode, add_optab, 1202: expand_binop (submode, binoptab, 1203: real0, imag1, 1204: 0, unsignedp, methods), 1205: expand_binop (submode, binoptab, 1206: real1, imag0, 1207: 0, unsignedp, methods), 1208: imagr, unsignedp, methods); 1209: if (res != imagr) 1210: emit_move_insn (imagr, res); 1211: } 1212: else 1213: { 1.1.1.5 root 1214: /* Don't fetch these from memory more than once. */ 1215: real0 = force_reg (submode, real0); 1216: real1 = force_reg (submode, real1); 1217: 1218: res = expand_binop (submode, binoptab, real0, real1, 1219: realr, unsignedp, methods); 1.1.1.4 root 1220: if (res != realr) 1221: emit_move_insn (realr, res); 1222: 1223: if (imag0) 1224: res = expand_binop (submode, binoptab, 1225: real1, imag0, imagr, unsignedp, methods); 1226: else 1227: res = expand_binop (submode, binoptab, 1228: real0, imag1, imagr, unsignedp, methods); 1229: if (res != imagr) 1230: emit_move_insn (imagr, res); 1231: } 1232: break; 1233: 1234: case DIV: 1.1.1.5 root 1235: /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */ 1.1.1.4 root 1236: 1237: if (! imag1) 1.1.1.5 root 1238: { /* (a+ib) / (c+i0) = (a/c) + i(b/c) */ 1239: 1240: /* Don't fetch these from memory more than once. */ 1241: real1 = force_reg (submode, real1); 1242: 1243: /* Simply divide the real and imaginary parts by `c' */ 1.1.1.4 root 1244: res = expand_binop (submode, binoptab, real0, real1, 1245: realr, unsignedp, methods); 1246: if (res != realr) 1247: emit_move_insn (realr, res); 1248: 1249: res = expand_binop (submode, binoptab, imag0, real1, 1250: imagr, unsignedp, methods); 1251: if (res != imagr) 1252: emit_move_insn (imagr, res); 1253: } 1254: else /* Divisor is of complex type */ 1255: { /* X/(a+ib) */ 1256: 1257: rtx divisor; 1258: rtx real_t; 1259: rtx imag_t; 1260: 1261: optab mulopt = unsignedp ? umul_widen_optab : smul_optab; 1262: 1.1.1.5 root 1263: /* Don't fetch these from memory more than once. */ 1264: real0 = force_reg (submode, real0); 1265: real1 = force_reg (submode, real1); 1266: if (imag0) 1267: imag0 = force_reg (submode, imag0); 1268: imag1 = force_reg (submode, imag1); 1269: 1.1.1.4 root 1270: /* Divisor: c*c + d*d */ 1271: divisor = expand_binop (submode, add_optab, 1272: expand_binop (submode, mulopt, 1273: real1, real1, 1274: 0, unsignedp, methods), 1275: expand_binop (submode, mulopt, 1276: imag1, imag1, 1277: 0, unsignedp, methods), 1278: 0, unsignedp, methods); 1279: 1280: if (! imag0) /* ((a)(c-id))/divisor */ 1281: { /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */ 1282: /* Calculate the dividend */ 1283: real_t = expand_binop (submode, mulopt, real0, real1, 1284: 0, unsignedp, methods); 1285: 1286: imag_t 1287: = expand_unop (submode, neg_optab, 1288: expand_binop (submode, mulopt, real0, imag1, 1289: 0, unsignedp, methods), 1290: 0, unsignedp); 1291: } 1292: else /* ((a+ib)(c-id))/divider */ 1293: { 1294: /* Calculate the dividend */ 1295: real_t = expand_binop (submode, add_optab, 1296: expand_binop (submode, mulopt, 1297: real0, real1, 1298: 0, unsignedp, methods), 1299: expand_binop (submode, mulopt, 1300: imag0, imag1, 1301: 0, unsignedp, methods), 1302: 0, unsignedp, methods); 1303: 1304: imag_t = expand_binop (submode, sub_optab, 1305: expand_binop (submode, mulopt, 1306: imag0, real1, 1307: 0, unsignedp, methods), 1308: expand_binop (submode, mulopt, 1309: real0, imag1, 1310: 0, unsignedp, methods), 1311: 0, unsignedp, methods); 1312: 1313: } 1314: 1315: res = expand_binop (submode, binoptab, real_t, divisor, 1316: realr, unsignedp, methods); 1317: if (res != realr) 1318: emit_move_insn (realr, res); 1319: 1320: res = expand_binop (submode, binoptab, imag_t, divisor, 1321: imagr, unsignedp, methods); 1322: if (res != imagr) 1323: emit_move_insn (imagr, res); 1324: } 1325: break; 1326: 1327: default: 1328: abort (); 1329: } 1330: 1331: seq = get_insns (); 1332: end_sequence (); 1333: 1334: if (binoptab->code != UNKNOWN) 1.1.1.5 root 1335: equiv_value 1336: = gen_rtx (binoptab->code, mode, copy_rtx (op0), copy_rtx (op1)); 1.1.1.4 root 1337: else 1338: equiv_value = 0; 1339: 1340: emit_no_conflict_block (seq, target, op0, op1, equiv_value); 1341: 1342: return target; 1343: } 1344: 1.1 root 1345: /* It can't be open-coded in this mode. 1346: Use a library call if one is available and caller says that's ok. */ 1347: 1348: if (binoptab->handlers[(int) mode].libfunc 1349: && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN)) 1350: { 1351: rtx insns; 1352: rtx funexp = binoptab->handlers[(int) mode].libfunc; 1.1.1.4 root 1353: rtx op1x = op1; 1354: enum machine_mode op1_mode = mode; 1.1.1.6 ! root 1355: rtx value; 1.1 root 1356: 1357: start_sequence (); 1358: 1.1.1.4 root 1359: if (shift_op) 1360: { 1361: op1_mode = word_mode; 1362: /* Specify unsigned here, 1363: since negative shift counts are meaningless. */ 1364: op1x = convert_to_mode (word_mode, op1, 1); 1365: } 1366: 1.1 root 1367: /* Pass 1 for NO_QUEUE so we don't lose any increments 1368: if the libcall is cse'd or moved. */ 1.1.1.6 ! root 1369: value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc, ! 1370: NULL_RTX, 1, mode, 2, ! 1371: op0, mode, op1x, op1_mode); 1.1 root 1372: 1373: insns = get_insns (); 1374: end_sequence (); 1375: 1376: target = gen_reg_rtx (mode); 1.1.1.6 ! root 1377: emit_libcall_block (insns, target, value, 1.1 root 1378: gen_rtx (binoptab->code, mode, op0, op1)); 1379: 1380: return target; 1381: } 1382: 1383: delete_insns_since (last); 1384: 1385: /* It can't be done in this mode. Can we do it in a wider mode? */ 1386: 1387: if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN 1388: || methods == OPTAB_MUST_WIDEN)) 1.1.1.4 root 1389: { 1390: /* Caller says, don't even try. */ 1391: delete_insns_since (entry_last); 1392: return 0; 1393: } 1.1 root 1394: 1395: /* Compute the value of METHODS to pass to recursive calls. 1396: Don't allow widening to be tried recursively. */ 1397: 1398: methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT); 1399: 1400: /* Look for a wider mode of the same class for which it appears we can do 1401: the operation. */ 1402: 1403: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 1404: { 1405: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 1406: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 1407: { 1408: if ((binoptab->handlers[(int) wider_mode].insn_code 1409: != CODE_FOR_nothing) 1410: || (methods == OPTAB_LIB 1411: && binoptab->handlers[(int) wider_mode].libfunc)) 1412: { 1413: rtx xop0 = op0, xop1 = op1; 1414: int no_extend = 0; 1415: 1416: /* For certain integer operations, we need not actually extend 1417: the narrow operands, as long as we will truncate 1.1.1.6 ! root 1418: the results to the same narrowness. */ 1.1 root 1419: 1420: if ((binoptab == ior_optab || binoptab == and_optab 1421: || binoptab == xor_optab 1422: || binoptab == add_optab || binoptab == sub_optab 1423: || binoptab == smul_optab 1424: || binoptab == ashl_optab || binoptab == lshl_optab) 1.1.1.6 ! root 1425: && class == MODE_INT) 1.1 root 1426: no_extend = 1; 1427: 1.1.1.6 ! root 1428: xop0 = widen_operand (xop0, wider_mode, mode, ! 1429: unsignedp, no_extend); 1.1 root 1430: 1.1.1.6 ! root 1431: /* The second operand of a shift must always be extended. */ ! 1432: xop1 = widen_operand (xop1, wider_mode, mode, unsignedp, ! 1433: no_extend && binoptab != ashl_optab ! 1434: && binoptab != lshl_optab); 1.1 root 1435: 1.1.1.4 root 1436: temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX, 1.1 root 1437: unsignedp, methods); 1438: if (temp) 1439: { 1440: if (class != MODE_INT) 1441: { 1442: if (target == 0) 1443: target = gen_reg_rtx (mode); 1444: convert_move (target, temp, 0); 1445: return target; 1446: } 1447: else 1448: return gen_lowpart (mode, temp); 1449: } 1450: else 1451: delete_insns_since (last); 1452: } 1453: } 1454: } 1455: 1.1.1.4 root 1456: delete_insns_since (entry_last); 1.1 root 1457: return 0; 1458: } 1459: 1460: /* Expand a binary operator which has both signed and unsigned forms. 1461: UOPTAB is the optab for unsigned operations, and SOPTAB is for 1462: signed operations. 1463: 1464: If we widen unsigned operands, we may use a signed wider operation instead 1465: of an unsigned wider operation, since the result would be the same. */ 1466: 1467: rtx 1468: sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods) 1469: enum machine_mode mode; 1470: optab uoptab, soptab; 1471: rtx op0, op1, target; 1472: int unsignedp; 1473: enum optab_methods methods; 1474: { 1475: register rtx temp; 1476: optab direct_optab = unsignedp ? uoptab : soptab; 1477: struct optab wide_soptab; 1478: 1479: /* Do it without widening, if possible. */ 1480: temp = expand_binop (mode, direct_optab, op0, op1, target, 1481: unsignedp, OPTAB_DIRECT); 1482: if (temp || methods == OPTAB_DIRECT) 1483: return temp; 1484: 1485: /* Try widening to a signed int. Make a fake signed optab that 1486: hides any signed insn for direct use. */ 1487: wide_soptab = *soptab; 1488: wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing; 1489: wide_soptab.handlers[(int) mode].libfunc = 0; 1490: 1491: temp = expand_binop (mode, &wide_soptab, op0, op1, target, 1492: unsignedp, OPTAB_WIDEN); 1493: 1494: /* For unsigned operands, try widening to an unsigned int. */ 1495: if (temp == 0 && unsignedp) 1496: temp = expand_binop (mode, uoptab, op0, op1, target, 1497: unsignedp, OPTAB_WIDEN); 1498: if (temp || methods == OPTAB_WIDEN) 1499: return temp; 1500: 1501: /* Use the right width lib call if that exists. */ 1502: temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB); 1503: if (temp || methods == OPTAB_LIB) 1504: return temp; 1505: 1506: /* Must widen and use a lib call, use either signed or unsigned. */ 1507: temp = expand_binop (mode, &wide_soptab, op0, op1, target, 1508: unsignedp, methods); 1509: if (temp != 0) 1510: return temp; 1511: if (unsignedp) 1512: return expand_binop (mode, uoptab, op0, op1, target, 1513: unsignedp, methods); 1514: return 0; 1515: } 1516: 1517: /* Generate code to perform an operation specified by BINOPTAB 1518: on operands OP0 and OP1, with two results to TARG1 and TARG2. 1519: We assume that the order of the operands for the instruction 1520: is TARG0, OP0, OP1, TARG1, which would fit a pattern like 1521: [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))]. 1522: 1523: Either TARG0 or TARG1 may be zero, but what that means is that 1524: that result is not actually wanted. We will generate it into 1525: a dummy pseudo-reg and discard it. They may not both be zero. 1526: 1527: Returns 1 if this operation can be performed; 0 if not. */ 1528: 1529: int 1530: expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp) 1531: optab binoptab; 1532: rtx op0, op1; 1533: rtx targ0, targ1; 1534: int unsignedp; 1535: { 1536: enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1); 1537: enum mode_class class; 1538: enum machine_mode wider_mode; 1.1.1.4 root 1539: rtx entry_last = get_last_insn (); 1.1 root 1540: rtx last; 1541: 1542: class = GET_MODE_CLASS (mode); 1543: 1544: op0 = protect_from_queue (op0, 0); 1545: op1 = protect_from_queue (op1, 0); 1546: 1547: if (flag_force_mem) 1548: { 1549: op0 = force_not_mem (op0); 1550: op1 = force_not_mem (op1); 1551: } 1552: 1553: /* If we are inside an appropriately-short loop and one operand is an 1554: expensive constant, force it into a register. */ 1.1.1.3 root 1555: if (CONSTANT_P (op0) && preserve_subexpressions_p () 1556: && rtx_cost (op0, binoptab->code) > 2) 1.1 root 1557: op0 = force_reg (mode, op0); 1558: 1.1.1.3 root 1559: if (CONSTANT_P (op1) && preserve_subexpressions_p () 1560: && rtx_cost (op1, binoptab->code) > 2) 1.1 root 1561: op1 = force_reg (mode, op1); 1562: 1563: if (targ0) 1564: targ0 = protect_from_queue (targ0, 1); 1565: else 1566: targ0 = gen_reg_rtx (mode); 1567: if (targ1) 1568: targ1 = protect_from_queue (targ1, 1); 1569: else 1570: targ1 = gen_reg_rtx (mode); 1571: 1572: /* Record where to go back to if we fail. */ 1573: last = get_last_insn (); 1574: 1575: if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 1576: { 1577: int icode = (int) binoptab->handlers[(int) mode].insn_code; 1578: enum machine_mode mode0 = insn_operand_mode[icode][1]; 1579: enum machine_mode mode1 = insn_operand_mode[icode][2]; 1580: rtx pat; 1581: rtx xop0 = op0, xop1 = op1; 1582: 1583: /* In case this insn wants input operands in modes different from the 1584: result, convert the operands. */ 1585: if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0) 1586: xop0 = convert_to_mode (mode0, xop0, unsignedp); 1587: 1588: if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1) 1589: xop1 = convert_to_mode (mode1, xop1, unsignedp); 1590: 1591: /* Now, if insn doesn't accept these operands, put them into pseudos. */ 1592: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) 1593: xop0 = copy_to_mode_reg (mode0, xop0); 1594: 1595: if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)) 1596: xop1 = copy_to_mode_reg (mode1, xop1); 1597: 1598: /* We could handle this, but we should always be called with a pseudo 1599: for our targets and all insns should take them as outputs. */ 1600: if (! (*insn_operand_predicate[icode][0]) (targ0, mode) 1601: || ! (*insn_operand_predicate[icode][3]) (targ1, mode)) 1602: abort (); 1603: 1604: pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1); 1605: if (pat) 1606: { 1607: emit_insn (pat); 1608: return 1; 1609: } 1610: else 1611: delete_insns_since (last); 1612: } 1613: 1614: /* It can't be done in this mode. Can we do it in a wider mode? */ 1615: 1616: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 1617: { 1618: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 1619: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 1620: { 1621: if (binoptab->handlers[(int) wider_mode].insn_code 1622: != CODE_FOR_nothing) 1623: { 1624: register rtx t0 = gen_reg_rtx (wider_mode); 1625: register rtx t1 = gen_reg_rtx (wider_mode); 1626: 1627: if (expand_twoval_binop (binoptab, 1.1.1.6 ! root 1628: convert_modes (wider_mode, mode, op0, ! 1629: unsignedp), ! 1630: convert_modes (wider_mode, mode, op1, ! 1631: unsignedp), 1.1 root 1632: t0, t1, unsignedp)) 1633: { 1634: convert_move (targ0, t0, unsignedp); 1635: convert_move (targ1, t1, unsignedp); 1636: return 1; 1637: } 1638: else 1639: delete_insns_since (last); 1640: } 1641: } 1642: } 1643: 1.1.1.4 root 1644: delete_insns_since (entry_last); 1.1 root 1645: return 0; 1646: } 1647: 1648: /* Generate code to perform an operation specified by UNOPTAB 1649: on operand OP0, with result having machine-mode MODE. 1650: 1651: UNSIGNEDP is for the case where we have to widen the operands 1652: to perform the operation. It says to use zero-extension. 1653: 1654: If TARGET is nonzero, the value 1655: is generated there, if it is convenient to do so. 1656: In all cases an rtx is returned for the locus of the value; 1657: this may or may not be TARGET. */ 1658: 1659: rtx 1660: expand_unop (mode, unoptab, op0, target, unsignedp) 1661: enum machine_mode mode; 1662: optab unoptab; 1663: rtx op0; 1664: rtx target; 1665: int unsignedp; 1666: { 1667: enum mode_class class; 1668: enum machine_mode wider_mode; 1669: register rtx temp; 1670: rtx last = get_last_insn (); 1671: rtx pat; 1672: 1673: class = GET_MODE_CLASS (mode); 1674: 1675: op0 = protect_from_queue (op0, 0); 1676: 1677: if (flag_force_mem) 1678: { 1679: op0 = force_not_mem (op0); 1680: } 1681: 1682: if (target) 1683: target = protect_from_queue (target, 1); 1684: 1685: if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 1686: { 1687: int icode = (int) unoptab->handlers[(int) mode].insn_code; 1688: enum machine_mode mode0 = insn_operand_mode[icode][1]; 1689: rtx xop0 = op0; 1690: 1691: if (target) 1692: temp = target; 1693: else 1694: temp = gen_reg_rtx (mode); 1695: 1696: if (GET_MODE (xop0) != VOIDmode 1697: && GET_MODE (xop0) != mode0) 1698: xop0 = convert_to_mode (mode0, xop0, unsignedp); 1699: 1700: /* Now, if insn doesn't accept our operand, put it into a pseudo. */ 1701: 1702: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) 1703: xop0 = copy_to_mode_reg (mode0, xop0); 1704: 1705: if (! (*insn_operand_predicate[icode][0]) (temp, mode)) 1706: temp = gen_reg_rtx (mode); 1707: 1708: pat = GEN_FCN (icode) (temp, xop0); 1709: if (pat) 1710: { 1711: if (GET_CODE (pat) == SEQUENCE 1.1.1.4 root 1712: && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX)) 1.1 root 1713: { 1714: delete_insns_since (last); 1.1.1.4 root 1715: return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp); 1.1 root 1716: } 1717: 1718: emit_insn (pat); 1719: 1720: return temp; 1721: } 1722: else 1723: delete_insns_since (last); 1724: } 1725: 1.1.1.4 root 1726: /* It can't be done in this mode. Can we open-code it in a wider mode? */ 1727: 1728: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 1729: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 1730: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 1731: { 1732: if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing) 1733: { 1734: rtx xop0 = op0; 1735: 1736: /* For certain operations, we need not actually extend 1737: the narrow operand, as long as we will truncate the 1.1.1.6 ! root 1738: results to the same narrowness. */ 1.1.1.4 root 1739: 1.1.1.6 ! root 1740: xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, ! 1741: (unoptab == neg_optab ! 1742: || unoptab == one_cmpl_optab) ! 1743: && class == MODE_INT); 1.1.1.4 root 1744: 1745: temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, 1746: unsignedp); 1747: 1748: if (temp) 1749: { 1750: if (class != MODE_INT) 1751: { 1752: if (target == 0) 1753: target = gen_reg_rtx (mode); 1754: convert_move (target, temp, 0); 1755: return target; 1756: } 1757: else 1758: return gen_lowpart (mode, temp); 1759: } 1760: else 1761: delete_insns_since (last); 1762: } 1763: } 1764: 1.1 root 1765: /* These can be done a word at a time. */ 1766: if (unoptab == one_cmpl_optab 1767: && class == MODE_INT 1768: && GET_MODE_SIZE (mode) > UNITS_PER_WORD 1769: && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing) 1770: { 1771: int i; 1772: rtx insns; 1773: 1774: if (target == 0 || target == op0) 1775: target = gen_reg_rtx (mode); 1776: 1777: start_sequence (); 1778: 1779: /* Do the actual arithmetic. */ 1780: for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++) 1781: { 1782: rtx target_piece = operand_subword (target, i, 1, mode); 1783: rtx x = expand_unop (word_mode, unoptab, 1784: operand_subword_force (op0, i, mode), 1785: target_piece, unsignedp); 1786: if (target_piece != x) 1787: emit_move_insn (target_piece, x); 1788: } 1789: 1790: insns = get_insns (); 1791: end_sequence (); 1792: 1.1.1.4 root 1793: emit_no_conflict_block (insns, target, op0, NULL_RTX, 1.1.1.5 root 1794: gen_rtx (unoptab->code, mode, copy_rtx (op0))); 1.1 root 1795: return target; 1796: } 1797: 1.1.1.4 root 1798: /* Open-code the complex negation operation. */ 1799: else if (unoptab == neg_optab 1800: && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)) 1801: { 1802: rtx target_piece; 1803: rtx x; 1804: rtx seq; 1805: 1806: /* Find the correct mode for the real and imaginary parts */ 1807: enum machine_mode submode 1808: = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, 1809: class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, 1810: 0); 1811: 1812: if (submode == BLKmode) 1813: abort (); 1814: 1815: if (target == 0) 1816: target = gen_reg_rtx (mode); 1817: 1818: start_sequence (); 1819: 1820: target_piece = gen_imagpart (submode, target); 1821: x = expand_unop (submode, unoptab, 1822: gen_imagpart (submode, op0), 1823: target_piece, unsignedp); 1824: if (target_piece != x) 1825: emit_move_insn (target_piece, x); 1826: 1827: target_piece = gen_realpart (submode, target); 1828: x = expand_unop (submode, unoptab, 1829: gen_realpart (submode, op0), 1830: target_piece, unsignedp); 1831: if (target_piece != x) 1832: emit_move_insn (target_piece, x); 1833: 1834: seq = get_insns (); 1835: end_sequence (); 1836: 1837: emit_no_conflict_block (seq, target, op0, 0, 1.1.1.5 root 1838: gen_rtx (unoptab->code, mode, copy_rtx (op0))); 1.1.1.4 root 1839: return target; 1840: } 1841: 1842: /* Now try a library call in this mode. */ 1.1 root 1843: if (unoptab->handlers[(int) mode].libfunc) 1844: { 1845: rtx insns; 1846: rtx funexp = unoptab->handlers[(int) mode].libfunc; 1.1.1.6 ! root 1847: rtx value; 1.1 root 1848: 1849: start_sequence (); 1850: 1851: /* Pass 1 for NO_QUEUE so we don't lose any increments 1852: if the libcall is cse'd or moved. */ 1.1.1.6 ! root 1853: value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc, ! 1854: NULL_RTX, 1, mode, 1, op0, mode); 1.1 root 1855: insns = get_insns (); 1856: end_sequence (); 1857: 1858: target = gen_reg_rtx (mode); 1.1.1.6 ! root 1859: emit_libcall_block (insns, target, value, 1.1 root 1860: gen_rtx (unoptab->code, mode, op0)); 1861: 1862: return target; 1863: } 1864: 1865: /* It can't be done in this mode. Can we do it in a wider mode? */ 1866: 1867: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 1868: { 1869: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 1870: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 1871: { 1872: if ((unoptab->handlers[(int) wider_mode].insn_code 1873: != CODE_FOR_nothing) 1874: || unoptab->handlers[(int) wider_mode].libfunc) 1875: { 1876: rtx xop0 = op0; 1877: 1878: /* For certain operations, we need not actually extend 1879: the narrow operand, as long as we will truncate the 1880: results to the same narrowness. */ 1881: 1.1.1.6 ! root 1882: xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, ! 1883: (unoptab == neg_optab ! 1884: || unoptab == one_cmpl_optab) ! 1885: && class == MODE_INT); 1.1 root 1886: 1.1.1.4 root 1887: temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, 1888: unsignedp); 1.1 root 1889: 1890: if (temp) 1891: { 1892: if (class != MODE_INT) 1893: { 1894: if (target == 0) 1895: target = gen_reg_rtx (mode); 1896: convert_move (target, temp, 0); 1897: return target; 1898: } 1899: else 1900: return gen_lowpart (mode, temp); 1901: } 1902: else 1903: delete_insns_since (last); 1904: } 1905: } 1906: } 1907: 1908: return 0; 1909: } 1910: 1.1.1.4 root 1911: /* Emit code to compute the absolute value of OP0, with result to 1912: TARGET if convenient. (TARGET may be 0.) The return value says 1913: where the result actually is to be found. 1914: 1915: MODE is the mode of the operand; the mode of the result is 1916: different but can be deduced from MODE. 1917: 1918: UNSIGNEDP is relevant for complex integer modes. */ 1919: 1920: rtx 1921: expand_complex_abs (mode, op0, target, unsignedp) 1922: enum machine_mode mode; 1923: rtx op0; 1924: rtx target; 1925: int unsignedp; 1926: { 1927: enum mode_class class = GET_MODE_CLASS (mode); 1928: enum machine_mode wider_mode; 1929: register rtx temp; 1930: rtx entry_last = get_last_insn (); 1931: rtx last; 1932: rtx pat; 1933: 1934: /* Find the correct mode for the real and imaginary parts. */ 1935: enum machine_mode submode 1936: = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, 1937: class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, 1938: 0); 1939: 1940: if (submode == BLKmode) 1941: abort (); 1942: 1943: op0 = protect_from_queue (op0, 0); 1944: 1945: if (flag_force_mem) 1946: { 1947: op0 = force_not_mem (op0); 1948: } 1949: 1950: last = get_last_insn (); 1951: 1952: if (target) 1953: target = protect_from_queue (target, 1); 1954: 1955: if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 1956: { 1957: int icode = (int) abs_optab->handlers[(int) mode].insn_code; 1958: enum machine_mode mode0 = insn_operand_mode[icode][1]; 1959: rtx xop0 = op0; 1960: 1961: if (target) 1962: temp = target; 1963: else 1964: temp = gen_reg_rtx (submode); 1965: 1966: if (GET_MODE (xop0) != VOIDmode 1967: && GET_MODE (xop0) != mode0) 1968: xop0 = convert_to_mode (mode0, xop0, unsignedp); 1969: 1970: /* Now, if insn doesn't accept our operand, put it into a pseudo. */ 1971: 1972: if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) 1973: xop0 = copy_to_mode_reg (mode0, xop0); 1974: 1975: if (! (*insn_operand_predicate[icode][0]) (temp, submode)) 1976: temp = gen_reg_rtx (submode); 1977: 1978: pat = GEN_FCN (icode) (temp, xop0); 1979: if (pat) 1980: { 1981: if (GET_CODE (pat) == SEQUENCE 1982: && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX)) 1983: { 1984: delete_insns_since (last); 1985: return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp); 1986: } 1987: 1988: emit_insn (pat); 1989: 1990: return temp; 1991: } 1992: else 1993: delete_insns_since (last); 1994: } 1995: 1996: /* It can't be done in this mode. Can we open-code it in a wider mode? */ 1997: 1998: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 1999: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 2000: { 2001: if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing) 2002: { 2003: rtx xop0 = op0; 2004: 1.1.1.6 ! root 2005: xop0 = convert_modes (wider_mode, mode, xop0, unsignedp); 1.1.1.4 root 2006: temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp); 2007: 2008: if (temp) 2009: { 2010: if (class != MODE_COMPLEX_INT) 2011: { 2012: if (target == 0) 2013: target = gen_reg_rtx (submode); 2014: convert_move (target, temp, 0); 2015: return target; 2016: } 2017: else 2018: return gen_lowpart (submode, temp); 2019: } 2020: else 2021: delete_insns_since (last); 2022: } 2023: } 2024: 2025: /* Open-code the complex absolute-value operation 2026: if we can open-code sqrt. Otherwise it's not worth while. */ 2027: if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing) 2028: { 2029: rtx real, imag, total; 2030: 2031: real = gen_realpart (submode, op0); 2032: imag = gen_imagpart (submode, op0); 1.1.1.6 ! root 2033: 1.1.1.4 root 2034: /* Square both parts. */ 1.1.1.6 ! root 2035: real = expand_mult (submode, real, real, NULL_RTX, 0); ! 2036: imag = expand_mult (submode, imag, imag, NULL_RTX, 0); ! 2037: 1.1.1.4 root 2038: /* Sum the parts. */ 2039: total = expand_binop (submode, add_optab, real, imag, 0, 2040: 0, OPTAB_LIB_WIDEN); 1.1.1.6 ! root 2041: 1.1.1.4 root 2042: /* Get sqrt in TARGET. Set TARGET to where the result is. */ 2043: target = expand_unop (submode, sqrt_optab, total, target, 0); 2044: if (target == 0) 2045: delete_insns_since (last); 2046: else 2047: return target; 2048: } 2049: 2050: /* Now try a library call in this mode. */ 2051: if (abs_optab->handlers[(int) mode].libfunc) 2052: { 2053: rtx insns; 2054: rtx funexp = abs_optab->handlers[(int) mode].libfunc; 1.1.1.6 ! root 2055: rtx value; 1.1.1.4 root 2056: 2057: start_sequence (); 2058: 2059: /* Pass 1 for NO_QUEUE so we don't lose any increments 2060: if the libcall is cse'd or moved. */ 1.1.1.6 ! root 2061: value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc, ! 2062: NULL_RTX, 1, submode, 1, op0, mode); 1.1.1.4 root 2063: insns = get_insns (); 2064: end_sequence (); 2065: 2066: target = gen_reg_rtx (submode); 1.1.1.6 ! root 2067: emit_libcall_block (insns, target, value, 1.1.1.4 root 2068: gen_rtx (abs_optab->code, mode, op0)); 2069: 2070: return target; 2071: } 2072: 2073: /* It can't be done in this mode. Can we do it in a wider mode? */ 2074: 2075: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 2076: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 2077: { 2078: if ((abs_optab->handlers[(int) wider_mode].insn_code 2079: != CODE_FOR_nothing) 2080: || abs_optab->handlers[(int) wider_mode].libfunc) 2081: { 2082: rtx xop0 = op0; 2083: 1.1.1.6 ! root 2084: xop0 = convert_modes (wider_mode, mode, xop0, unsignedp); 1.1.1.4 root 2085: 2086: temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp); 2087: 2088: if (temp) 2089: { 2090: if (class != MODE_COMPLEX_INT) 2091: { 2092: if (target == 0) 2093: target = gen_reg_rtx (submode); 2094: convert_move (target, temp, 0); 2095: return target; 2096: } 2097: else 2098: return gen_lowpart (submode, temp); 2099: } 2100: else 2101: delete_insns_since (last); 2102: } 2103: } 2104: 2105: delete_insns_since (entry_last); 2106: return 0; 2107: } 2108: 1.1 root 2109: /* Generate an instruction whose insn-code is INSN_CODE, 2110: with two operands: an output TARGET and an input OP0. 2111: TARGET *must* be nonzero, and the output is always stored there. 2112: CODE is an rtx code such that (CODE OP0) is an rtx that describes 2113: the value that is stored into TARGET. */ 2114: 2115: void 2116: emit_unop_insn (icode, target, op0, code) 2117: int icode; 2118: rtx target; 2119: rtx op0; 2120: enum rtx_code code; 2121: { 2122: register rtx temp; 2123: enum machine_mode mode0 = insn_operand_mode[icode][1]; 2124: rtx pat; 2125: 2126: temp = target = protect_from_queue (target, 1); 2127: 2128: op0 = protect_from_queue (op0, 0); 2129: 2130: if (flag_force_mem) 2131: op0 = force_not_mem (op0); 2132: 2133: /* Now, if insn does not accept our operands, put them into pseudos. */ 2134: 2135: if (! (*insn_operand_predicate[icode][1]) (op0, mode0)) 2136: op0 = copy_to_mode_reg (mode0, op0); 2137: 2138: if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp)) 2139: || (flag_force_mem && GET_CODE (temp) == MEM)) 2140: temp = gen_reg_rtx (GET_MODE (temp)); 2141: 2142: pat = GEN_FCN (icode) (temp, op0); 2143: 2144: if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN) 1.1.1.4 root 2145: add_equal_note (pat, temp, code, op0, NULL_RTX); 1.1 root 2146: 2147: emit_insn (pat); 2148: 2149: if (temp != target) 2150: emit_move_insn (target, temp); 2151: } 2152: 2153: /* Emit code to perform a series of operations on a multi-word quantity, one 2154: word at a time. 2155: 1.1.1.2 root 2156: Such a block is preceded by a CLOBBER of the output, consists of multiple 1.1 root 2157: insns, each setting one word of the output, and followed by a SET copying 2158: the output to itself. 2159: 2160: Each of the insns setting words of the output receives a REG_NO_CONFLICT 2161: note indicating that it doesn't conflict with the (also multi-word) 2162: inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL 2163: notes. 2164: 2165: INSNS is a block of code generated to perform the operation, not including 2166: the CLOBBER and final copy. All insns that compute intermediate values 2167: are first emitted, followed by the block as described above. Only 2168: INSNs are allowed in the block; no library calls or jumps may be 2169: present. 2170: 2171: TARGET, OP0, and OP1 are the output and inputs of the operations, 2172: respectively. OP1 may be zero for a unary operation. 2173: 2174: EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note 2175: on the last insn. 2176: 2177: If TARGET is not a register, INSNS is simply emitted with no special 2178: processing. 2179: 2180: The final insn emitted is returned. */ 2181: 2182: rtx 2183: emit_no_conflict_block (insns, target, op0, op1, equiv) 2184: rtx insns; 2185: rtx target; 2186: rtx op0, op1; 2187: rtx equiv; 2188: { 2189: rtx prev, next, first, last, insn; 2190: 2191: if (GET_CODE (target) != REG || reload_in_progress) 2192: return emit_insns (insns); 2193: 2194: /* First emit all insns that do not store into words of the output and remove 2195: these from the list. */ 2196: for (insn = insns; insn; insn = next) 2197: { 2198: rtx set = 0; 2199: int i; 2200: 2201: next = NEXT_INSN (insn); 2202: 2203: if (GET_CODE (insn) != INSN) 2204: abort (); 2205: 2206: if (GET_CODE (PATTERN (insn)) == SET) 2207: set = PATTERN (insn); 2208: else if (GET_CODE (PATTERN (insn)) == PARALLEL) 2209: { 2210: for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) 2211: if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET) 2212: { 2213: set = XVECEXP (PATTERN (insn), 0, i); 2214: break; 2215: } 2216: } 2217: 2218: if (set == 0) 2219: abort (); 2220: 2221: if (! reg_overlap_mentioned_p (target, SET_DEST (set))) 2222: { 2223: if (PREV_INSN (insn)) 2224: NEXT_INSN (PREV_INSN (insn)) = next; 2225: else 2226: insns = next; 2227: 2228: if (next) 2229: PREV_INSN (next) = PREV_INSN (insn); 2230: 2231: add_insn (insn); 2232: } 2233: } 2234: 2235: prev = get_last_insn (); 2236: 2237: /* Now write the CLOBBER of the output, followed by the setting of each 2238: of the words, followed by the final copy. */ 2239: if (target != op0 && target != op1) 2240: emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); 2241: 2242: for (insn = insns; insn; insn = next) 2243: { 2244: next = NEXT_INSN (insn); 2245: add_insn (insn); 2246: 2247: if (op1 && GET_CODE (op1) == REG) 2248: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op1, 2249: REG_NOTES (insn)); 2250: 2251: if (op0 && GET_CODE (op0) == REG) 2252: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_NO_CONFLICT, op0, 2253: REG_NOTES (insn)); 2254: } 2255: 1.1.1.5 root 2256: if (mov_optab->handlers[(int) GET_MODE (target)].insn_code 2257: != CODE_FOR_nothing) 2258: { 2259: last = emit_move_insn (target, target); 2260: if (equiv) 2261: REG_NOTES (last) 2262: = gen_rtx (EXPR_LIST, REG_EQUAL, equiv, REG_NOTES (last)); 2263: } 2264: else 2265: last = get_last_insn (); 1.1 root 2266: 2267: if (prev == 0) 2268: first = get_insns (); 2269: else 2270: first = NEXT_INSN (prev); 2271: 2272: /* Encapsulate the block so it gets manipulated as a unit. */ 2273: REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last, 2274: REG_NOTES (first)); 2275: REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last)); 2276: 2277: return last; 2278: } 2279: 2280: /* Emit code to make a call to a constant function or a library call. 2281: 2282: INSNS is a list containing all insns emitted in the call. 2283: These insns leave the result in RESULT. Our block is to copy RESULT 2284: to TARGET, which is logically equivalent to EQUIV. 2285: 2286: We first emit any insns that set a pseudo on the assumption that these are 2287: loading constants into registers; doing so allows them to be safely cse'ed 2288: between blocks. Then we emit all the other insns in the block, followed by 2289: an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL 2290: note with an operand of EQUIV. 2291: 1.1.1.3 root 2292: Moving assignments to pseudos outside of the block is done to improve 2293: the generated code, but is not required to generate correct code, 2294: hence being unable to move an assignment is not grounds for not making 2295: a libcall block. There are two reasons why it is safe to leave these 2296: insns inside the block: First, we know that these pseudos cannot be 2297: used in generated RTL outside the block since they are created for 2298: temporary purposes within the block. Second, CSE will not record the 2299: values of anything set inside a libcall block, so we know they must 2300: be dead at the end of the block. 2301: 1.1 root 2302: Except for the first group of insns (the ones setting pseudos), the 2303: block is delimited by REG_RETVAL and REG_LIBCALL notes. */ 2304: 2305: void 2306: emit_libcall_block (insns, target, result, equiv) 2307: rtx insns; 2308: rtx target; 2309: rtx result; 2310: rtx equiv; 2311: { 2312: rtx prev, next, first, last, insn; 2313: 2314: /* First emit all insns that set pseudos. Remove them from the list as 1.1.1.6 ! root 2315: we go. Avoid insns that set pseudos which were referenced in previous 1.1.1.3 root 2316: insns. These can be generated by move_by_pieces, for example, 1.1.1.6 ! root 2317: to update an address. Similarly, avoid insns that reference things ! 2318: set in previous insns. */ 1.1 root 2319: 2320: for (insn = insns; insn; insn = next) 2321: { 2322: rtx set = single_set (insn); 2323: 2324: next = NEXT_INSN (insn); 2325: 2326: if (set != 0 && GET_CODE (SET_DEST (set)) == REG 1.1.1.3 root 2327: && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER 2328: && (insn == insns 2329: || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns)) 1.1.1.6 ! root 2330: && ! reg_used_between_p (SET_DEST (set), insns, insn) ! 2331: && ! modified_in_p (SET_SRC (set), insns) ! 2332: && ! modified_between_p (SET_SRC (set), insns, insn)))) 1.1 root 2333: { 2334: if (PREV_INSN (insn)) 2335: NEXT_INSN (PREV_INSN (insn)) = next; 2336: else 2337: insns = next; 2338: 2339: if (next) 2340: PREV_INSN (next) = PREV_INSN (insn); 2341: 2342: add_insn (insn); 2343: } 2344: } 2345: 2346: prev = get_last_insn (); 2347: 2348: /* Write the remaining insns followed by the final copy. */ 2349: 2350: for (insn = insns; insn; insn = next) 2351: { 2352: next = NEXT_INSN (insn); 2353: 2354: add_insn (insn); 2355: } 2356: 2357: last = emit_move_insn (target, result); 1.1.1.5 root 2358: REG_NOTES (last) = gen_rtx (EXPR_LIST, 2359: REG_EQUAL, copy_rtx (equiv), REG_NOTES (last)); 1.1 root 2360: 2361: if (prev == 0) 2362: first = get_insns (); 2363: else 2364: first = NEXT_INSN (prev); 2365: 2366: /* Encapsulate the block so it gets manipulated as a unit. */ 2367: REG_NOTES (first) = gen_rtx (INSN_LIST, REG_LIBCALL, last, 2368: REG_NOTES (first)); 2369: REG_NOTES (last) = gen_rtx (INSN_LIST, REG_RETVAL, first, REG_NOTES (last)); 2370: } 2371: 2372: /* Generate code to store zero in X. */ 2373: 2374: void 2375: emit_clr_insn (x) 2376: rtx x; 2377: { 2378: emit_move_insn (x, const0_rtx); 2379: } 2380: 2381: /* Generate code to store 1 in X 2382: assuming it contains zero beforehand. */ 2383: 2384: void 2385: emit_0_to_1_insn (x) 2386: rtx x; 2387: { 2388: emit_move_insn (x, const1_rtx); 2389: } 2390: 2391: /* Generate code to compare X with Y 2392: so that the condition codes are set. 2393: 2394: MODE is the mode of the inputs (in case they are const_int). 2395: UNSIGNEDP nonzero says that X and Y are unsigned; 2396: this matters if they need to be widened. 2397: 2398: If they have mode BLKmode, then SIZE specifies the size of both X and Y, 2399: and ALIGN specifies the known shared alignment of X and Y. 2400: 2401: COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). 2402: It is ignored for fixed-point and block comparisons; 2403: it is used only for floating-point comparisons. */ 2404: 2405: void 2406: emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align) 2407: rtx x, y; 2408: enum rtx_code comparison; 2409: rtx size; 1.1.1.3 root 2410: enum machine_mode mode; 1.1 root 2411: int unsignedp; 2412: int align; 2413: { 2414: enum mode_class class; 2415: enum machine_mode wider_mode; 2416: 2417: class = GET_MODE_CLASS (mode); 2418: 2419: /* They could both be VOIDmode if both args are immediate constants, 2420: but we should fold that at an earlier stage. 2421: With no special code here, this will call abort, 2422: reminding the programmer to implement such folding. */ 2423: 2424: if (mode != BLKmode && flag_force_mem) 2425: { 2426: x = force_not_mem (x); 2427: y = force_not_mem (y); 2428: } 2429: 2430: /* If we are inside an appropriately-short loop and one operand is an 2431: expensive constant, force it into a register. */ 1.1.1.3 root 2432: if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2) 1.1 root 2433: x = force_reg (mode, x); 2434: 1.1.1.3 root 2435: if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2) 1.1 root 2436: y = force_reg (mode, y); 2437: 2438: /* Don't let both operands fail to indicate the mode. */ 2439: if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode) 2440: x = force_reg (mode, x); 2441: 2442: /* Handle all BLKmode compares. */ 2443: 2444: if (mode == BLKmode) 2445: { 2446: emit_queue (); 2447: x = protect_from_queue (x, 0); 2448: y = protect_from_queue (y, 0); 2449: 2450: if (size == 0) 2451: abort (); 2452: #ifdef HAVE_cmpstrqi 2453: if (HAVE_cmpstrqi 2454: && GET_CODE (size) == CONST_INT 2455: && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode))) 2456: { 2457: enum machine_mode result_mode 2458: = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0]; 2459: rtx result = gen_reg_rtx (result_mode); 1.1.1.4 root 2460: emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align))); 2461: emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, 2462: result_mode, 0, 0); 1.1 root 2463: } 2464: else 2465: #endif 2466: #ifdef HAVE_cmpstrhi 2467: if (HAVE_cmpstrhi 2468: && GET_CODE (size) == CONST_INT 2469: && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode))) 2470: { 2471: enum machine_mode result_mode 2472: = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0]; 2473: rtx result = gen_reg_rtx (result_mode); 1.1.1.4 root 2474: emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align))); 2475: emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, 2476: result_mode, 0, 0); 1.1 root 2477: } 2478: else 2479: #endif 2480: #ifdef HAVE_cmpstrsi 2481: if (HAVE_cmpstrsi) 2482: { 2483: enum machine_mode result_mode 2484: = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0]; 2485: rtx result = gen_reg_rtx (result_mode); 1.1.1.4 root 2486: size = protect_from_queue (size, 0); 1.1 root 2487: emit_insn (gen_cmpstrsi (result, x, y, 2488: convert_to_mode (SImode, size, 1), 1.1.1.4 root 2489: GEN_INT (align))); 2490: emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, 2491: result_mode, 0, 0); 1.1 root 2492: } 2493: else 2494: #endif 2495: { 2496: #ifdef TARGET_MEM_FUNCTIONS 1.1.1.4 root 2497: emit_library_call (memcmp_libfunc, 0, 1.1 root 2498: TYPE_MODE (integer_type_node), 3, 2499: XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, 2500: size, Pmode); 2501: #else 1.1.1.4 root 2502: emit_library_call (bcmp_libfunc, 0, 1.1 root 2503: TYPE_MODE (integer_type_node), 3, 2504: XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, 2505: size, Pmode); 2506: #endif 2507: emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)), 1.1.1.4 root 2508: const0_rtx, comparison, NULL_RTX, 1.1 root 2509: TYPE_MODE (integer_type_node), 0, 0); 2510: } 2511: return; 2512: } 2513: 2514: /* Handle some compares against zero. */ 2515: 2516: if (y == CONST0_RTX (mode) 2517: && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 2518: { 2519: int icode = (int) tst_optab->handlers[(int) mode].insn_code; 2520: 2521: emit_queue (); 2522: x = protect_from_queue (x, 0); 2523: y = protect_from_queue (y, 0); 2524: 2525: /* Now, if insn does accept these operands, put them into pseudos. */ 2526: if (! (*insn_operand_predicate[icode][0]) 2527: (x, insn_operand_mode[icode][0])) 2528: x = copy_to_mode_reg (insn_operand_mode[icode][0], x); 2529: 2530: emit_insn (GEN_FCN (icode) (x)); 2531: return; 2532: } 2533: 2534: /* Handle compares for which there is a directly suitable insn. */ 2535: 2536: if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) 2537: { 2538: int icode = (int) cmp_optab->handlers[(int) mode].insn_code; 2539: 2540: emit_queue (); 2541: x = protect_from_queue (x, 0); 2542: y = protect_from_queue (y, 0); 2543: 2544: /* Now, if insn doesn't accept these operands, put them into pseudos. */ 2545: if (! (*insn_operand_predicate[icode][0]) 2546: (x, insn_operand_mode[icode][0])) 2547: x = copy_to_mode_reg (insn_operand_mode[icode][0], x); 2548: 2549: if (! (*insn_operand_predicate[icode][1]) 2550: (y, insn_operand_mode[icode][1])) 2551: y = copy_to_mode_reg (insn_operand_mode[icode][1], y); 2552: 2553: emit_insn (GEN_FCN (icode) (x, y)); 2554: return; 2555: } 2556: 2557: /* Try widening if we can find a direct insn that way. */ 2558: 2559: if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) 2560: { 2561: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 2562: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 2563: { 2564: if (cmp_optab->handlers[(int) wider_mode].insn_code 2565: != CODE_FOR_nothing) 2566: { 1.1.1.4 root 2567: x = protect_from_queue (x, 0); 2568: y = protect_from_queue (y, 0); 1.1.1.6 ! root 2569: x = convert_modes (wider_mode, mode, x, unsignedp); ! 2570: y = convert_modes (wider_mode, mode, y, unsignedp); 1.1.1.4 root 2571: emit_cmp_insn (x, y, comparison, NULL_RTX, 1.1 root 2572: wider_mode, unsignedp, align); 2573: return; 2574: } 2575: } 2576: } 2577: 2578: /* Handle a lib call just for the mode we are using. */ 2579: 2580: if (cmp_optab->handlers[(int) mode].libfunc 2581: && class != MODE_FLOAT) 2582: { 2583: rtx libfunc = cmp_optab->handlers[(int) mode].libfunc; 2584: /* If we want unsigned, and this mode has a distinct unsigned 2585: comparison routine, use that. */ 2586: if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc) 2587: libfunc = ucmp_optab->handlers[(int) mode].libfunc; 2588: 1.1.1.2 root 2589: emit_library_call (libfunc, 1, 1.1.1.5 root 2590: word_mode, 2, x, mode, y, mode); 1.1 root 2591: 2592: /* Integer comparison returns a result that must be compared against 1, 2593: so that even if we do an unsigned compare afterward, 2594: there is still a value that can represent the result "less than". */ 2595: 1.1.1.5 root 2596: emit_cmp_insn (hard_libcall_value (word_mode), const1_rtx, 2597: comparison, NULL_RTX, word_mode, unsignedp, 0); 1.1 root 2598: return; 2599: } 2600: 2601: if (class == MODE_FLOAT) 2602: emit_float_lib_cmp (x, y, comparison); 2603: 2604: else 2605: abort (); 2606: } 2607: 2608: /* Nonzero if a compare of mode MODE can be done straightforwardly 2609: (without splitting it into pieces). */ 2610: 2611: int 2612: can_compare_p (mode) 2613: enum machine_mode mode; 2614: { 2615: do 2616: { 2617: if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing) 2618: return 1; 2619: mode = GET_MODE_WIDER_MODE (mode); 2620: } while (mode != VOIDmode); 2621: 2622: return 0; 2623: } 2624: 2625: /* Emit a library call comparison between floating point X and Y. 2626: COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */ 2627: 2628: static void 2629: emit_float_lib_cmp (x, y, comparison) 2630: rtx x, y; 2631: enum rtx_code comparison; 2632: { 2633: enum machine_mode mode = GET_MODE (x); 2634: rtx libfunc; 2635: 2636: if (mode == SFmode) 2637: switch (comparison) 2638: { 2639: case EQ: 2640: libfunc = eqsf2_libfunc; 2641: break; 2642: 2643: case NE: 2644: libfunc = nesf2_libfunc; 2645: break; 2646: 2647: case GT: 2648: libfunc = gtsf2_libfunc; 2649: break; 2650: 2651: case GE: 2652: libfunc = gesf2_libfunc; 2653: break; 2654: 2655: case LT: 2656: libfunc = ltsf2_libfunc; 2657: break; 2658: 2659: case LE: 2660: libfunc = lesf2_libfunc; 2661: break; 2662: } 2663: else if (mode == DFmode) 2664: switch (comparison) 2665: { 2666: case EQ: 2667: libfunc = eqdf2_libfunc; 2668: break; 2669: 2670: case NE: 2671: libfunc = nedf2_libfunc; 2672: break; 2673: 2674: case GT: 2675: libfunc = gtdf2_libfunc; 2676: break; 2677: 2678: case GE: 2679: libfunc = gedf2_libfunc; 2680: break; 2681: 2682: case LT: 2683: libfunc = ltdf2_libfunc; 2684: break; 2685: 2686: case LE: 2687: libfunc = ledf2_libfunc; 2688: break; 2689: } 1.1.1.4 root 2690: else if (mode == XFmode) 2691: switch (comparison) 2692: { 2693: case EQ: 2694: libfunc = eqxf2_libfunc; 2695: break; 2696: 2697: case NE: 2698: libfunc = nexf2_libfunc; 2699: break; 2700: 2701: case GT: 2702: libfunc = gtxf2_libfunc; 2703: break; 2704: 2705: case GE: 2706: libfunc = gexf2_libfunc; 2707: break; 2708: 2709: case LT: 2710: libfunc = ltxf2_libfunc; 2711: break; 2712: 2713: case LE: 2714: libfunc = lexf2_libfunc; 2715: break; 2716: } 2717: else if (mode == TFmode) 2718: switch (comparison) 2719: { 2720: case EQ: 2721: libfunc = eqtf2_libfunc; 2722: break; 2723: 2724: case NE: 2725: libfunc = netf2_libfunc; 2726: break; 2727: 2728: case GT: 2729: libfunc = gttf2_libfunc; 2730: break; 2731: 2732: case GE: 2733: libfunc = getf2_libfunc; 2734: break; 2735: 2736: case LT: 2737: libfunc = lttf2_libfunc; 2738: break; 2739: 2740: case LE: 2741: libfunc = letf2_libfunc; 2742: break; 2743: } 1.1 root 2744: else 2745: { 2746: enum machine_mode wider_mode; 2747: 2748: for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; 2749: wider_mode = GET_MODE_WIDER_MODE (wider_mode)) 2750: { 2751: if ((cmp_optab->handlers[(int) wider_mode].insn_code 2752: != CODE_FOR_nothing) 2753: || (cmp_optab->handlers[(int) wider_mode].libfunc != 0)) 2754: { 1.1.1.4 root 2755: x = protect_from_queue (x, 0); 2756: y = protect_from_queue (y, 0); 1.1 root 2757: x = convert_to_mode (wider_mode, x, 0); 2758: y = convert_to_mode (wider_mode, y, 0); 2759: emit_float_lib_cmp (x, y, comparison); 2760: return; 2761: } 2762: } 2763: abort (); 2764: } 2765: 1.1.1.2 root 2766: emit_library_call (libfunc, 1, 1.1.1.5 root 2767: word_mode, 2, x, mode, y, mode); 1.1 root 2768: 1.1.1.5 root 2769: emit_cmp_insn (hard_libcall_value (word_mode), const0_rtx, comparison, 2770: NULL_RTX, word_mode, 0, 0); 1.1 root 2771: } 2772: 2773: /* Generate code to indirectly jump to a location given in the rtx LOC. */ 2774: 2775: void 2776: emit_indirect_jump (loc) 2777: rtx loc; 2778: { 2779: if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0]) 1.1.1.5 root 2780: (loc, Pmode))) 2781: loc = copy_to_mode_reg (Pmode, loc); 1.1 root 2782: 2783: emit_jump_insn (gen_indirect_jump (loc)); 1.1.1.3 root 2784: emit_barrier (); 1.1 root 2785: } 2786: 2787: /* These three functions generate an insn body and return it 2788: rather than emitting the insn. 2789: 2790: They do not protect from queued increments, 2791: because they may be used 1) in protect_from_queue itself 2792: and 2) in other passes where there is no queue. */ 2793: 2794: /* Generate and return an insn body to add Y to X. */ 2795: 2796: rtx 2797: gen_add2_insn (x, y) 2798: rtx x, y; 2799: { 2800: int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 2801: 2802: if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0]) 2803: || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1]) 2804: || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2])) 2805: abort (); 2806: 2807: return (GEN_FCN (icode) (x, x, y)); 2808: } 2809: 2810: int 2811: have_add2_insn (mode) 2812: enum machine_mode mode; 2813: { 2814: return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; 2815: } 2816: 2817: /* Generate and return an insn body to subtract Y from X. */ 2818: 2819: rtx 2820: gen_sub2_insn (x, y) 2821: rtx x, y; 2822: { 2823: int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 2824: 2825: if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0]) 2826: || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1]) 2827: || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2])) 2828: abort (); 2829: 2830: return (GEN_FCN (icode) (x, x, y)); 2831: } 2832: 2833: int 2834: have_sub2_insn (mode) 2835: enum machine_mode mode; 2836: { 2837: return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing; 2838: } 2839: 1.1.1.5 root 2840: /* Generate the body of an instruction to copy Y into X. 2841: It may be a SEQUENCE, if one insn isn't enough. */ 1.1 root 2842: 2843: rtx 2844: gen_move_insn (x, y) 2845: rtx x, y; 2846: { 2847: register enum machine_mode mode = GET_MODE (x); 2848: enum insn_code insn_code; 1.1.1.5 root 2849: rtx seq; 1.1 root 2850: 2851: if (mode == VOIDmode) 2852: mode = GET_MODE (y); 2853: 2854: insn_code = mov_optab->handlers[(int) mode].insn_code; 2855: 2856: /* Handle MODE_CC modes: If we don't have a special move insn for this mode, 2857: find a mode to do it in. If we have a movcc, use it. Otherwise, 2858: find the MODE_INT mode of the same width. */ 2859: 1.1.1.5 root 2860: if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing) 1.1 root 2861: { 2862: enum machine_mode tmode = VOIDmode; 2863: rtx x1 = x, y1 = y; 2864: 1.1.1.5 root 2865: if (mode != CCmode 1.1 root 2866: && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing) 2867: tmode = CCmode; 1.1.1.5 root 2868: else 1.1 root 2869: for (tmode = QImode; tmode != VOIDmode; 2870: tmode = GET_MODE_WIDER_MODE (tmode)) 2871: if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode)) 2872: break; 2873: 2874: if (tmode == VOIDmode) 2875: abort (); 2876: 2877: /* Get X and Y in TMODE. We can't use gen_lowpart here because it 2878: may call change_address which is not appropriate if we were 2879: called when a reload was in progress. We don't have to worry 2880: about changing the address since the size in bytes is supposed to 2881: be the same. Copy the MEM to change the mode and move any 2882: substitutions from the old MEM to the new one. */ 2883: 2884: if (reload_in_progress) 2885: { 2886: x = gen_lowpart_common (tmode, x1); 2887: if (x == 0 && GET_CODE (x1) == MEM) 2888: { 2889: x = gen_rtx (MEM, tmode, XEXP (x1, 0)); 2890: RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1); 2891: MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1); 2892: MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1); 2893: copy_replacements (x1, x); 2894: } 2895: 2896: y = gen_lowpart_common (tmode, y1); 2897: if (y == 0 && GET_CODE (y1) == MEM) 2898: { 2899: y = gen_rtx (MEM, tmode, XEXP (y1, 0)); 2900: RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1); 2901: MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1); 2902: MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1); 2903: copy_replacements (y1, y); 2904: } 2905: } 2906: else 2907: { 2908: x = gen_lowpart (tmode, x); 2909: y = gen_lowpart (tmode, y); 2910: } 2911: 2912: insn_code = mov_optab->handlers[(int) tmode].insn_code; 1.1.1.5 root 2913: return (GEN_FCN (insn_code) (x, y)); 1.1 root 2914: } 2915: 1.1.1.5 root 2916: start_sequence (); 2917: emit_move_insn_1 (x, y); 2918: seq = gen_sequence (); 2919: end_sequence (); 2920: return seq; 1.1 root 2921: } 2922: 2923: /* Return the insn code used to extend FROM_MODE to TO_MODE. 2924: UNSIGNEDP specifies zero-extension instead of sign-extension. If 2925: no such operation exists, CODE_FOR_nothing will be returned. */ 2926: 2927: enum insn_code 2928: can_extend_p (to_mode, from_mode, unsignedp) 2929: enum machine_mode to_mode, from_mode; 2930: int unsignedp; 2931: { 2932: return extendtab[(int) to_mode][(int) from_mode][unsignedp]; 2933: } 2934: 2935: /* Generate the body of an insn to extend Y (with mode MFROM) 2936: into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */ 2937: 2938: rtx 2939: gen_extend_insn (x, y, mto, mfrom, unsignedp) 2940: rtx x, y; 2941: enum machine_mode mto, mfrom; 2942: int unsignedp; 2943: { 2944: return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y)); 2945: } 2946: 2947: /* can_fix_p and can_float_p say whether the target machine 2948: can directly convert a given fixed point type to 2949: a given floating point type, or vice versa. 2950: The returned value is the CODE_FOR_... value to use, 1.1.1.5 root 2951: or CODE_FOR_nothing if these modes cannot be directly converted. 1.1 root 2952: 1.1.1.5 root 2953: *TRUNCP_PTR is set to 1 if it is necessary to output 1.1 root 2954: an explicit FTRUNC insn before the fix insn; otherwise 0. */ 2955: 2956: static enum insn_code 2957: can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr) 2958: enum machine_mode fltmode, fixmode; 2959: int unsignedp; 2960: int *truncp_ptr; 2961: { 2962: *truncp_ptr = 0; 2963: if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing) 2964: return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp]; 2965: 2966: if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing) 2967: { 2968: *truncp_ptr = 1; 2969: return fixtab[(int) fltmode][(int) fixmode][unsignedp]; 2970: } 2971: return CODE_FOR_nothing; 2972: } 2973: 2974: static enum insn_code 2975: can_float_p (fltmode, fixmode, unsignedp) 2976: enum machine_mode fixmode, fltmode; 2977: int unsignedp; 2978: { 2979: return floattab[(int) fltmode][(int) fixmode][unsignedp]; 2980: } 2981: 2982: /* Generate code to convert FROM to floating point 2983: and store in TO. FROM must be fixed point and not VOIDmode. 2984: UNSIGNEDP nonzero means regard FROM as unsigned. 2985: Normally this is done by correcting the final value 2986: if it is negative. */ 2987: 2988: void 2989: expand_float (to, from, unsignedp) 2990: rtx to, from; 2991: int unsignedp; 2992: { 2993: enum insn_code icode; 2994: register rtx target = to; 2995: enum machine_mode fmode, imode; 2996: 2997: /* Crash now, because we won't be able to decide which mode to use. */ 2998: if (GET_MODE (from) == VOIDmode) 2999: abort (); 3000: 3001: /* Look for an insn to do the conversion. Do it in the specified 3002: modes if possible; otherwise convert either input, output or both to 3003: wider mode. If the integer mode is wider than the mode of FROM, 3004: we can do the conversion signed even if the input is unsigned. */ 3005: 3006: for (imode = GET_MODE (from); imode != VOIDmode; 3007: imode = GET_MODE_WIDER_MODE (imode)) 3008: for (fmode = GET_MODE (to); fmode != VOIDmode; 3009: fmode = GET_MODE_WIDER_MODE (fmode)) 3010: { 3011: int doing_unsigned = unsignedp; 3012: 3013: icode = can_float_p (fmode, imode, unsignedp); 3014: if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp) 3015: icode = can_float_p (fmode, imode, 0), doing_unsigned = 0; 3016: 3017: if (icode != CODE_FOR_nothing) 3018: { 3019: to = protect_from_queue (to, 1); 1.1.1.4 root 3020: from = protect_from_queue (from, 0); 1.1 root 3021: 3022: if (imode != GET_MODE (from)) 3023: from = convert_to_mode (imode, from, unsignedp); 3024: 3025: if (fmode != GET_MODE (to)) 3026: target = gen_reg_rtx (fmode); 3027: 3028: emit_unop_insn (icode, target, from, 3029: doing_unsigned ? UNSIGNED_FLOAT : FLOAT); 3030: 3031: if (target != to) 3032: convert_move (to, target, 0); 3033: return; 3034: } 3035: } 3036: 3037: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) 3038: 3039: /* Unsigned integer, and no way to convert directly. 3040: Convert as signed, then conditionally adjust the result. */ 3041: if (unsignedp) 3042: { 3043: rtx label = gen_label_rtx (); 3044: rtx temp; 3045: REAL_VALUE_TYPE offset; 3046: 3047: emit_queue (); 3048: 3049: to = protect_from_queue (to, 1); 3050: from = protect_from_queue (from, 0); 3051: 3052: if (flag_force_mem) 3053: from = force_not_mem (from); 3054: 1.1.1.5 root 3055: /* Look for a usable floating mode FMODE wider than the source and at 3056: least as wide as the target. Using FMODE will avoid rounding woes 3057: with unsigned values greater than the signed maximum value. */ 3058: for (fmode = GET_MODE (to); fmode != VOIDmode; 3059: fmode = GET_MODE_WIDER_MODE (fmode)) 3060: if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode) 3061: && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing) 3062: break; 3063: if (fmode == VOIDmode) 3064: { 3065: /* There is no such mode. Pretend the target is wide enough. 3066: This may cause rounding problems, unfortunately. */ 3067: fmode = GET_MODE (to); 3068: } 3069: 1.1 root 3070: /* If we are about to do some arithmetic to correct for an 3071: unsigned operand, do it in a pseudo-register. */ 3072: 1.1.1.5 root 3073: if (GET_MODE (to) != fmode 3074: || GET_CODE (to) != REG || REGNO (to) <= LAST_VIRTUAL_REGISTER) 3075: target = gen_reg_rtx (fmode); 1.1 root 3076: 3077: /* Convert as signed integer to floating. */ 3078: expand_float (target, from, 0); 3079: 3080: /* If FROM is negative (and therefore TO is negative), 3081: correct its value by 2**bitwidth. */ 3082: 3083: do_pending_stack_adjust (); 1.1.1.4 root 3084: emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0); 1.1 root 3085: emit_jump_insn (gen_bge (label)); 3086: /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1). 3087: Rather than setting up a dconst_dot_5, let's hope SCO 3088: fixes the bug. */ 3089: offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from))); 1.1.1.5 root 3090: temp = expand_binop (fmode, add_optab, target, 3091: immed_real_const_1 (offset, fmode), 1.1 root 3092: target, 0, OPTAB_LIB_WIDEN); 3093: if (temp != target) 3094: emit_move_insn (target, temp); 3095: do_pending_stack_adjust (); 3096: emit_label (label); 3097: } 3098: else 3099: #endif 3100: 1.1.1.4 root 3101: /* No hardware instruction available; call a library rotine to convert from 3102: SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */ 1.1 root 3103: { 3104: rtx libfcn; 3105: rtx insns; 1.1.1.6 ! root 3106: rtx value; 1.1 root 3107: 3108: to = protect_from_queue (to, 1); 1.1.1.4 root 3109: from = protect_from_queue (from, 0); 1.1 root 3110: 3111: if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode)) 3112: from = convert_to_mode (SImode, from, unsignedp); 3113: 3114: if (flag_force_mem) 3115: from = force_not_mem (from); 3116: 3117: if (GET_MODE (to) == SFmode) 3118: { 3119: if (GET_MODE (from) == SImode) 3120: libfcn = floatsisf_libfunc; 3121: else if (GET_MODE (from) == DImode) 3122: libfcn = floatdisf_libfunc; 1.1.1.4 root 3123: else if (GET_MODE (from) == TImode) 3124: libfcn = floattisf_libfunc; 1.1 root 3125: else 3126: abort (); 3127: } 3128: else if (GET_MODE (to) == DFmode) 3129: { 3130: if (GET_MODE (from) == SImode) 3131: libfcn = floatsidf_libfunc; 3132: else if (GET_MODE (from) == DImode) 3133: libfcn = floatdidf_libfunc; 1.1.1.4 root 3134: else if (GET_MODE (from) == TImode) 3135: libfcn = floattidf_libfunc; 3136: else 3137: abort (); 3138: } 3139: else if (GET_MODE (to) == XFmode) 3140: { 3141: if (GET_MODE (from) == SImode) 3142: libfcn = floatsixf_libfunc; 3143: else if (GET_MODE (from) == DImode) 3144: libfcn = floatdixf_libfunc; 3145: else if (GET_MODE (from) == TImode) 3146: libfcn = floattixf_libfunc; 3147: else 3148: abort (); 3149: } 3150: else if (GET_MODE (to) == TFmode) 3151: { 3152: if (GET_MODE (from) == SImode) 3153: libfcn = floatsitf_libfunc; 3154: else if (GET_MODE (from) == DImode) 3155: libfcn = floatditf_libfunc; 3156: else if (GET_MODE (from) == TImode) 3157: libfcn = floattitf_libfunc; 1.1 root 3158: else 3159: abort (); 3160: } 3161: else 3162: abort (); 3163: 3164: start_sequence (); 3165: 1.1.1.6 ! root 3166: value = emit_library_call_value (libfcn, NULL_RTX, 1, ! 3167: GET_MODE (to), ! 3168: 1, from, GET_MODE (from)); 1.1 root 3169: insns = get_insns (); 3170: end_sequence (); 3171: 1.1.1.6 ! root 3172: emit_libcall_block (insns, target, value, 1.1 root 3173: gen_rtx (FLOAT, GET_MODE (to), from)); 3174: } 3175: 3176: /* Copy result to requested destination 3177: if we have been computing in a temp location. */ 3178: 3179: if (target != to) 3180: { 3181: if (GET_MODE (target) == GET_MODE (to)) 3182: emit_move_insn (to, target); 3183: else 3184: convert_move (to, target, 0); 3185: } 3186: } 3187: 3188: /* expand_fix: generate code to convert FROM to fixed point 3189: and store in TO. FROM must be floating point. */ 3190: 3191: static rtx 3192: ftruncify (x) 3193: rtx x; 3194: { 3195: rtx temp = gen_reg_rtx (GET_MODE (x)); 3196: return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0); 3197: } 3198: 3199: void 3200: expand_fix (to, from, unsignedp) 3201: register rtx to, from; 3202: int unsignedp; 3203: { 3204: enum insn_code icode; 3205: register rtx target = to; 3206: enum machine_mode fmode, imode; 3207: int must_trunc = 0; 3208: rtx libfcn = 0; 3209: 3210: /* We first try to find a pair of modes, one real and one integer, at 3211: least as wide as FROM and TO, respectively, in which we can open-code 3212: this conversion. If the integer mode is wider than the mode of TO, 3213: we can do the conversion either signed or unsigned. */ 3214: 3215: for (imode = GET_MODE (to); imode != VOIDmode; 3216: imode = GET_MODE_WIDER_MODE (imode)) 3217: for (fmode = GET_MODE (from); fmode != VOIDmode; 3218: fmode = GET_MODE_WIDER_MODE (fmode)) 3219: { 3220: int doing_unsigned = unsignedp; 3221: 3222: icode = can_fix_p (imode, fmode, unsignedp, &must_trunc); 3223: if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp) 3224: icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0; 3225: 3226: if (icode != CODE_FOR_nothing) 3227: { 3228: to = protect_from_queue (to, 1); 1.1.1.4 root 3229: from = protect_from_queue (from, 0); 1.1 root 3230: 3231: if (fmode != GET_MODE (from)) 3232: from = convert_to_mode (fmode, from, 0); 3233: 3234: if (must_trunc) 3235: from = ftruncify (from); 3236: 3237: if (imode != GET_MODE (to)) 3238: target = gen_reg_rtx (imode); 3239: 3240: emit_unop_insn (icode, target, from, 3241: doing_unsigned ? UNSIGNED_FIX : FIX); 3242: if (target != to) 3243: convert_move (to, target, unsignedp); 3244: return; 3245: } 3246: } 3247: 3248: #if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) 3249: /* For an unsigned conversion, there is one more way to do it. 3250: If we have a signed conversion, we generate code that compares 3251: the real value to the largest representable positive number. If if 3252: is smaller, the conversion is done normally. Otherwise, subtract 3253: one plus the highest signed number, convert, and add it back. 3254: 3255: We only need to check all real modes, since we know we didn't find 1.1.1.3 root 3256: anything with a wider integer mode. */ 1.1 root 3257: 1.1.1.4 root 3258: if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT) 1.1 root 3259: for (fmode = GET_MODE (from); fmode != VOIDmode; 3260: fmode = GET_MODE_WIDER_MODE (fmode)) 3261: /* Make sure we won't lose significant bits doing this. */ 3262: if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to)) 3263: && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, 3264: &must_trunc)) 3265: { 1.1.1.5 root 3266: int bitsize; 3267: REAL_VALUE_TYPE offset; 3268: rtx limit, lab1, lab2, insn; 3269: 3270: bitsize = GET_MODE_BITSIZE (GET_MODE (to)); 3271: offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1); 3272: limit = immed_real_const_1 (offset, fmode); 3273: lab1 = gen_label_rtx (); 3274: lab2 = gen_label_rtx (); 1.1 root 3275: 3276: emit_queue (); 3277: to = protect_from_queue (to, 1); 3278: from = protect_from_queue (from, 0); 3279: 3280: if (flag_force_mem) 3281: from = force_not_mem (from); 3282: 3283: if (fmode != GET_MODE (from)) 3284: from = convert_to_mode (fmode, from, 0); 3285: 3286: /* See if we need to do the subtraction. */ 3287: do_pending_stack_adjust (); 1.1.1.4 root 3288: emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0); 1.1 root 3289: emit_jump_insn (gen_bge (lab1)); 3290: 3291: /* If not, do the signed "fix" and branch around fixup code. */ 3292: expand_fix (to, from, 0); 3293: emit_jump_insn (gen_jump (lab2)); 3294: emit_barrier (); 3295: 3296: /* Otherwise, subtract 2**(N-1), convert to signed number, 3297: then add 2**(N-1). Do the addition using XOR since this 3298: will often generate better code. */ 3299: emit_label (lab1); 3300: target = expand_binop (GET_MODE (from), sub_optab, from, limit, 1.1.1.4 root 3301: NULL_RTX, 0, OPTAB_LIB_WIDEN); 1.1 root 3302: expand_fix (to, target, 0); 3303: target = expand_binop (GET_MODE (to), xor_optab, to, 1.1.1.4 root 3304: GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)), 1.1 root 3305: to, 1, OPTAB_LIB_WIDEN); 3306: 3307: if (target != to) 3308: emit_move_insn (to, target); 3309: 3310: emit_label (lab2); 3311: 3312: /* Make a place for a REG_NOTE and add it. */ 3313: insn = emit_move_insn (to, to); 3314: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, 3315: gen_rtx (UNSIGNED_FIX, GET_MODE (to), 1.1.1.5 root 3316: copy_rtx (from)), 3317: REG_NOTES (insn)); 1.1 root 3318: 3319: return; 3320: } 3321: #endif 3322: 3323: /* We can't do it with an insn, so use a library call. But first ensure 3324: that the mode of TO is at least as wide as SImode, since those are the 3325: only library calls we know about. */ 3326: 3327: if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode)) 3328: { 3329: target = gen_reg_rtx (SImode); 3330: 3331: expand_fix (target, from, unsignedp); 3332: } 3333: else if (GET_MODE (from) == SFmode) 3334: { 3335: if (GET_MODE (to) == SImode) 3336: libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc; 3337: else if (GET_MODE (to) == DImode) 3338: libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc; 1.1.1.4 root 3339: else if (GET_MODE (to) == TImode) 3340: libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc; 1.1 root 3341: else 3342: abort (); 3343: } 3344: else if (GET_MODE (from) == DFmode) 3345: { 3346: if (GET_MODE (to) == SImode) 3347: libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc; 3348: else if (GET_MODE (to) == DImode) 3349: libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc; 1.1.1.4 root 3350: else if (GET_MODE (to) == TImode) 3351: libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc; 3352: else 3353: abort (); 3354: } 3355: else if (GET_MODE (from) == XFmode) 3356: { 3357: if (GET_MODE (to) == SImode) 3358: libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc; 3359: else if (GET_MODE (to) == DImode) 3360: libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc; 3361: else if (GET_MODE (to) == TImode) 3362: libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc; 3363: else 3364: abort (); 3365: } 3366: else if (GET_MODE (from) == TFmode) 3367: { 3368: if (GET_MODE (to) == SImode) 3369: libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc; 3370: else if (GET_MODE (to) == DImode) 3371: libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc; 3372: else if (GET_MODE (to) == TImode) 3373: libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc; 1.1 root 3374: else 3375: abort (); 3376: } 3377: else 3378: abort (); 3379: 3380: if (libfcn) 3381: { 3382: rtx insns; 3383: 3384: to = protect_from_queue (to, 1); 3385: from = protect_from_queue (from, 0); 3386: 3387: if (flag_force_mem) 3388: from = force_not_mem (from); 3389: 3390: start_sequence (); 3391: 1.1.1.2 root 3392: emit_library_call (libfcn, 1, GET_MODE (to), 1, from, GET_MODE (from)); 1.1 root 3393: insns = get_insns (); 3394: end_sequence (); 3395: 3396: emit_libcall_block (insns, target, hard_libcall_value (GET_MODE (to)), 3397: gen_rtx (unsignedp ? FIX : UNSIGNED_FIX, 3398: GET_MODE (to), from)); 3399: } 3400: 3401: if (GET_MODE (to) == GET_MODE (target)) 3402: emit_move_insn (to, target); 3403: else 3404: convert_move (to, target, 0); 3405: } 3406: 3407: static optab 3408: init_optab (code) 3409: enum rtx_code code; 3410: { 3411: int i; 3412: optab op = (optab) xmalloc (sizeof (struct optab)); 3413: op->code = code; 3414: for (i = 0; i < NUM_MACHINE_MODES; i++) 3415: { 3416: op->handlers[i].insn_code = CODE_FOR_nothing; 3417: op->handlers[i].libfunc = 0; 3418: } 1.1.1.6 ! root 3419: ! 3420: if (code != UNKNOWN) ! 3421: code_to_optab[(int) code] = op; ! 3422: 1.1 root 3423: return op; 3424: } 3425: 1.1.1.4 root 3426: /* Initialize the libfunc fields of an entire group of entries in some 3427: optab. Each entry is set equal to a string consisting of a leading 3428: pair of underscores followed by a generic operation name followed by 3429: a mode name (downshifted to lower case) followed by a single character 3430: representing the number of operands for the given operation (which is 3431: usually one of the characters '2', '3', or '4'). 3432: 3433: OPTABLE is the table in which libfunc fields are to be initialized. 3434: FIRST_MODE is the first machine mode index in the given optab to 3435: initialize. 3436: LAST_MODE is the last machine mode index in the given optab to 3437: initialize. 3438: OPNAME is the generic (string) name of the operation. 3439: SUFFIX is the character which specifies the number of operands for 3440: the given generic operation. 3441: */ 3442: 3443: static void 3444: init_libfuncs (optable, first_mode, last_mode, opname, suffix) 3445: register optab optable; 1.1.1.5 root 3446: register int first_mode; 3447: register int last_mode; 1.1.1.4 root 3448: register char *opname; 3449: register char suffix; 3450: { 1.1.1.5 root 3451: register int mode; 1.1.1.4 root 3452: register unsigned opname_len = strlen (opname); 3453: 3454: for (mode = first_mode; (int) mode <= (int) last_mode; 3455: mode = (enum machine_mode) ((int) mode + 1)) 3456: { 3457: register char *mname = mode_name[(int) mode]; 3458: register unsigned mname_len = strlen (mname); 3459: register char *libfunc_name 3460: = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1); 3461: register char *p; 3462: register char *q; 3463: 3464: p = libfunc_name; 3465: *p++ = '_'; 3466: *p++ = '_'; 3467: for (q = opname; *q; ) 3468: *p++ = *q++; 3469: for (q = mname; *q; q++) 3470: *p++ = tolower (*q); 3471: *p++ = suffix; 3472: *p++ = '\0'; 3473: optable->handlers[(int) mode].libfunc 3474: = gen_rtx (SYMBOL_REF, Pmode, libfunc_name); 3475: } 3476: } 3477: 3478: /* Initialize the libfunc fields of an entire group of entries in some 3479: optab which correspond to all integer mode operations. The parameters 3480: have the same meaning as similarly named ones for the `init_libfuncs' 3481: routine. (See above). */ 3482: 3483: static void 3484: init_integral_libfuncs (optable, opname, suffix) 3485: register optab optable; 3486: register char *opname; 3487: register char suffix; 3488: { 3489: init_libfuncs (optable, SImode, TImode, opname, suffix); 3490: } 3491: 3492: /* Initialize the libfunc fields of an entire group of entries in some 3493: optab which correspond to all real mode operations. The parameters 3494: have the same meaning as similarly named ones for the `init_libfuncs' 3495: routine. (See above). */ 3496: 3497: static void 3498: init_floating_libfuncs (optable, opname, suffix) 3499: register optab optable; 3500: register char *opname; 3501: register char suffix; 3502: { 3503: init_libfuncs (optable, SFmode, TFmode, opname, suffix); 3504: } 3505: 3506: /* Initialize the libfunc fields of an entire group of entries in some 3507: optab which correspond to all complex floating modes. The parameters 3508: have the same meaning as similarly named ones for the `init_libfuncs' 3509: routine. (See above). */ 3510: 3511: static void 3512: init_complex_libfuncs (optable, opname, suffix) 3513: register optab optable; 3514: register char *opname; 3515: register char suffix; 3516: { 3517: init_libfuncs (optable, SCmode, TCmode, opname, suffix); 3518: } 3519: 1.1 root 3520: /* Call this once to initialize the contents of the optabs 3521: appropriately for the current target machine. */ 3522: 3523: void 3524: init_optabs () 3525: { 1.1.1.5 root 3526: int i, j; 3527: enum insn_code *p; 3528: 3529: /* Start by initializing all tables to contain CODE_FOR_nothing. */ 3530: 3531: for (p = fixtab[0][0]; 3532: p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); 3533: p++) 3534: *p = CODE_FOR_nothing; 3535: 3536: for (p = fixtrunctab[0][0]; 3537: p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); 3538: p++) 3539: *p = CODE_FOR_nothing; 3540: 3541: for (p = floattab[0][0]; 3542: p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); 3543: p++) 3544: *p = CODE_FOR_nothing; 3545: 3546: for (p = extendtab[0][0]; 3547: p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0]; 3548: p++) 3549: *p = CODE_FOR_nothing; 1.1 root 3550: 1.1.1.5 root 3551: for (i = 0; i < NUM_RTX_CODE; i++) 3552: setcc_gen_code[i] = CODE_FOR_nothing; 1.1 root 3553: 3554: add_optab = init_optab (PLUS); 3555: sub_optab = init_optab (MINUS); 3556: smul_optab = init_optab (MULT); 3557: smul_widen_optab = init_optab (UNKNOWN); 3558: umul_widen_optab = init_optab (UNKNOWN); 3559: sdiv_optab = init_optab (DIV); 3560: sdivmod_optab = init_optab (UNKNOWN); 3561: udiv_optab = init_optab (UDIV); 3562: udivmod_optab = init_optab (UNKNOWN); 3563: smod_optab = init_optab (MOD); 3564: umod_optab = init_optab (UMOD); 3565: flodiv_optab = init_optab (DIV); 3566: ftrunc_optab = init_optab (UNKNOWN); 3567: and_optab = init_optab (AND); 3568: ior_optab = init_optab (IOR); 3569: xor_optab = init_optab (XOR); 3570: ashl_optab = init_optab (ASHIFT); 3571: ashr_optab = init_optab (ASHIFTRT); 3572: lshl_optab = init_optab (LSHIFT); 3573: lshr_optab = init_optab (LSHIFTRT); 3574: rotl_optab = init_optab (ROTATE); 3575: rotr_optab = init_optab (ROTATERT); 3576: smin_optab = init_optab (SMIN); 3577: smax_optab = init_optab (SMAX); 3578: umin_optab = init_optab (UMIN); 3579: umax_optab = init_optab (UMAX); 3580: mov_optab = init_optab (UNKNOWN); 3581: movstrict_optab = init_optab (UNKNOWN); 3582: cmp_optab = init_optab (UNKNOWN); 3583: ucmp_optab = init_optab (UNKNOWN); 3584: tst_optab = init_optab (UNKNOWN); 3585: neg_optab = init_optab (NEG); 3586: abs_optab = init_optab (ABS); 3587: one_cmpl_optab = init_optab (NOT); 3588: ffs_optab = init_optab (FFS); 1.1.1.2 root 3589: sqrt_optab = init_optab (SQRT); 1.1.1.4 root 3590: sin_optab = init_optab (UNKNOWN); 3591: cos_optab = init_optab (UNKNOWN); 1.1.1.3 root 3592: strlen_optab = init_optab (UNKNOWN); 1.1 root 3593: 1.1.1.5 root 3594: for (i = 0; i < NUM_MACHINE_MODES; i++) 3595: { 3596: movstr_optab[i] = CODE_FOR_nothing; 3597: 3598: #ifdef HAVE_SECONDARY_RELOADS 3599: reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing; 1.1 root 3600: #endif 1.1.1.5 root 3601: } 3602: 3603: /* Fill in the optabs with the insns we support. */ 3604: init_all_optabs (); 3605: 3606: #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC 3607: /* This flag says the same insns that convert to a signed fixnum 3608: also convert validly to an unsigned one. */ 3609: for (i = 0; i < NUM_MACHINE_MODES; i++) 3610: for (j = 0; j < NUM_MACHINE_MODES; j++) 3611: fixtrunctab[i][j][1] = fixtrunctab[i][j][0]; 1.1.1.4 root 3612: #endif 1.1.1.5 root 3613: 3614: #ifdef EXTRA_CC_MODES 3615: init_mov_optab (); 1.1 root 3616: #endif 1.1.1.5 root 3617: 3618: /* Initialize the optabs with the names of the library functions. */ 1.1.1.4 root 3619: init_integral_libfuncs (add_optab, "add", '3'); 3620: init_floating_libfuncs (add_optab, "add", '3'); 3621: init_integral_libfuncs (sub_optab, "sub", '3'); 3622: init_floating_libfuncs (sub_optab, "sub", '3'); 3623: init_integral_libfuncs (smul_optab, "mul", '3'); 3624: init_floating_libfuncs (smul_optab, "mul", '3'); 1.1.1.5 root 3625: init_integral_libfuncs (sdiv_optab, "div", '3'); 3626: init_integral_libfuncs (udiv_optab, "udiv", '3'); 3627: init_integral_libfuncs (sdivmod_optab, "divmod", '4'); 3628: init_integral_libfuncs (udivmod_optab, "udivmod", '4'); 3629: init_integral_libfuncs (smod_optab, "mod", '3'); 3630: init_integral_libfuncs (umod_optab, "umod", '3'); 3631: init_floating_libfuncs (flodiv_optab, "div", '3'); 3632: init_floating_libfuncs (ftrunc_optab, "ftrunc", '2'); 3633: init_integral_libfuncs (and_optab, "and", '3'); 3634: init_integral_libfuncs (ior_optab, "ior", '3'); 3635: init_integral_libfuncs (xor_optab, "xor", '3'); 3636: init_integral_libfuncs (ashl_optab, "ashl", '3'); 3637: init_integral_libfuncs (ashr_optab, "ashr", '3'); 3638: init_integral_libfuncs (lshl_optab, "lshl", '3'); 3639: init_integral_libfuncs (lshr_optab, "lshr", '3'); 3640: init_integral_libfuncs (rotl_optab, "rotl", '3'); 3641: init_integral_libfuncs (rotr_optab, "rotr", '3'); 3642: init_integral_libfuncs (smin_optab, "min", '3'); 3643: init_floating_libfuncs (smin_optab, "min", '3'); 3644: init_integral_libfuncs (smax_optab, "max", '3'); 3645: init_floating_libfuncs (smax_optab, "max", '3'); 3646: init_integral_libfuncs (umin_optab, "umin", '3'); 3647: init_integral_libfuncs (umax_optab, "umax", '3'); 3648: init_integral_libfuncs (neg_optab, "neg", '2'); 3649: init_floating_libfuncs (neg_optab, "neg", '2'); 3650: init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2'); 3651: init_integral_libfuncs (ffs_optab, "ffs", '2'); 3652: 3653: /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */ 3654: init_integral_libfuncs (cmp_optab, "cmp", '2'); 3655: init_integral_libfuncs (ucmp_optab, "ucmp", '2'); 3656: init_floating_libfuncs (cmp_optab, "cmp", '2'); 1.1 root 3657: 3658: #ifdef MULSI3_LIBCALL 3659: smul_optab->handlers[(int) SImode].libfunc 3660: = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL); 3661: #endif 3662: #ifdef MULDI3_LIBCALL 3663: smul_optab->handlers[(int) DImode].libfunc 3664: = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL); 3665: #endif 1.1.1.4 root 3666: #ifdef MULTI3_LIBCALL 3667: smul_optab->handlers[(int) TImode].libfunc 3668: = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL); 3669: #endif 1.1 root 3670: 3671: #ifdef DIVSI3_LIBCALL 3672: sdiv_optab->handlers[(int) SImode].libfunc 3673: = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL); 3674: #endif 3675: #ifdef DIVDI3_LIBCALL 3676: sdiv_optab->handlers[(int) DImode].libfunc 3677: = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL); 1.1.1.4 root 3678: #endif 3679: #ifdef DIVTI3_LIBCALL 3680: sdiv_optab->handlers[(int) TImode].libfunc 3681: = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL); 1.1 root 3682: #endif 3683: 3684: #ifdef UDIVSI3_LIBCALL 3685: udiv_optab->handlers[(int) SImode].libfunc 3686: = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL); 3687: #endif 3688: #ifdef UDIVDI3_LIBCALL 3689: udiv_optab->handlers[(int) DImode].libfunc 3690: = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL); 1.1.1.4 root 3691: #endif 3692: #ifdef UDIVTI3_LIBCALL 3693: udiv_optab->handlers[(int) TImode].libfunc 3694: = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL); 1.1 root 3695: #endif 3696: 3697: 3698: #ifdef MODSI3_LIBCALL 3699: smod_optab->handlers[(int) SImode].libfunc 3700: = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL); 3701: #endif 3702: #ifdef MODDI3_LIBCALL 3703: smod_optab->handlers[(int) DImode].libfunc 3704: = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL); 1.1.1.4 root 3705: #endif 3706: #ifdef MODTI3_LIBCALL 3707: smod_optab->handlers[(int) TImode].libfunc 3708: = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL); 1.1 root 3709: #endif 3710: 3711: 3712: #ifdef UMODSI3_LIBCALL 3713: umod_optab->handlers[(int) SImode].libfunc 3714: = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL); 3715: #endif 3716: #ifdef UMODDI3_LIBCALL 3717: umod_optab->handlers[(int) DImode].libfunc 3718: = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL); 1.1.1.4 root 3719: #endif 3720: #ifdef UMODTI3_LIBCALL 3721: umod_optab->handlers[(int) TImode].libfunc 3722: = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL); 1.1 root 3723: #endif 3724: 1.1.1.4 root 3725: /* Use cabs for DC complex abs, since systems generally have cabs. 3726: Don't define any libcall for SCmode, so that cabs will be used. */ 3727: abs_optab->handlers[(int) DCmode].libfunc 3728: = gen_rtx (SYMBOL_REF, Pmode, "cabs"); 1.1 root 3729: 1.1.1.6 ! root 3730: /* The ffs function operates on `int'. */ ! 3731: #ifndef INT_TYPE_SIZE ! 3732: #define INT_TYPE_SIZE BITS_PER_WORD ! 3733: #endif ! 3734: ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc 1.1.1.5 root 3735: = gen_rtx (SYMBOL_REF, Pmode, "ffs"); 1.1 root 3736: 3737: extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2"); 1.1.1.4 root 3738: extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2"); 3739: extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2"); 3740: extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2"); 3741: extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2"); 3742: 1.1 root 3743: truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2"); 1.1.1.4 root 3744: truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2"); 3745: trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2"); 3746: truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2"); 3747: trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2"); 3748: 1.1 root 3749: memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy"); 3750: bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy"); 3751: memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp"); 1.1.1.4 root 3752: bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gcc_bcmp"); 1.1 root 3753: memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset"); 3754: bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero"); 1.1.1.4 root 3755: 1.1 root 3756: eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2"); 3757: nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2"); 3758: gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtsf2"); 3759: gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gesf2"); 3760: ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2"); 3761: lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2"); 1.1.1.4 root 3762: 1.1 root 3763: eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2"); 3764: nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2"); 3765: gtdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtdf2"); 3766: gedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gedf2"); 3767: ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2"); 3768: ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2"); 1.1.1.4 root 3769: 3770: eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2"); 3771: nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2"); 3772: gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2"); 3773: gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2"); 3774: ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2"); 3775: lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2"); 3776: 3777: eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2"); 3778: netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2"); 3779: gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2"); 3780: getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2"); 3781: lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2"); 3782: letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2"); 3783: 1.1 root 3784: floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf"); 1.1.1.4 root 3785: floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf"); 3786: floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf"); 3787: 1.1 root 3788: floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf"); 1.1.1.4 root 3789: floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf"); 3790: floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf"); 3791: 3792: floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf"); 3793: floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf"); 3794: floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf"); 3795: 3796: floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf"); 3797: floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf"); 3798: floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf"); 3799: 1.1 root 3800: fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi"); 3801: fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi"); 1.1.1.4 root 3802: fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti"); 3803: 1.1 root 3804: fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi"); 3805: fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi"); 1.1.1.4 root 3806: fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti"); 3807: 3808: fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi"); 3809: fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi"); 3810: fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti"); 3811: 3812: fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi"); 3813: fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi"); 3814: fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti"); 3815: 1.1 root 3816: fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi"); 3817: fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi"); 1.1.1.4 root 3818: fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti"); 3819: 1.1 root 3820: fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi"); 3821: fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi"); 1.1.1.4 root 3822: fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti"); 3823: 3824: fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi"); 3825: fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi"); 3826: fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti"); 3827: 3828: fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi"); 3829: fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi"); 3830: fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti"); 1.1 root 3831: } 1.1.1.2 root 3832: 3833: #ifdef BROKEN_LDEXP 3834: 3835: /* SCO 3.2 apparently has a broken ldexp. */ 3836: 3837: double 3838: ldexp(x,n) 3839: double x; 3840: int n; 3841: { 3842: if (n > 0) 3843: while (n--) 3844: x *= 2; 3845: 3846: return x; 3847: } 3848: #endif /* BROKEN_LDEXP */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.