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