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