00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "toplev.h"
00029
00030
00031
00032 #include "insn-config.h"
00033 #include "rtl.h"
00034 #include "tree.h"
00035 #include "tm_p.h"
00036 #include "flags.h"
00037 #include "function.h"
00038 #include "except.h"
00039 #include "expr.h"
00040 #include "optabs.h"
00041 #include "libfuncs.h"
00042 #include "recog.h"
00043 #include "reload.h"
00044 #include "ggc.h"
00045 #include "real.h"
00046 #include "basic-block.h"
00047 #include "target.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 optab optab_table[OTI_MAX];
00059
00060 rtx libfunc_table[LTI_MAX];
00061
00062
00063 convert_optab convert_optab_table[COI_MAX];
00064
00065
00066 optab code_to_optab[NUM_RTX_CODE + 1];
00067
00068
00069
00070
00071 rtxfun bcc_gen_fctn[NUM_RTX_CODE];
00072
00073
00074
00075
00076
00077 enum insn_code setcc_gen_code[NUM_RTX_CODE];
00078
00079 #ifdef HAVE_conditional_move
00080
00081
00082
00083
00084
00085 enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
00086 #endif
00087
00088
00089
00090
00091 enum insn_code vcond_gen_code[NUM_MACHINE_MODES];
00092 enum insn_code vcondu_gen_code[NUM_MACHINE_MODES];
00093
00094
00095
00096
00097 static GTY(()) rtx trap_rtx;
00098
00099 static int add_equal_note (rtx, rtx, enum rtx_code, rtx, rtx);
00100 static rtx widen_operand (rtx, enum machine_mode, enum machine_mode, int,
00101 int);
00102 static void prepare_cmp_insn (rtx *, rtx *, enum rtx_code *, rtx,
00103 enum machine_mode *, int *,
00104 enum can_compare_purpose);
00105 static enum insn_code can_fix_p (enum machine_mode, enum machine_mode, int,
00106 int *);
00107 static enum insn_code can_float_p (enum machine_mode, enum machine_mode, int);
00108 static optab new_optab (void);
00109 static convert_optab new_convert_optab (void);
00110 static inline optab init_optab (enum rtx_code);
00111 static inline optab init_optabv (enum rtx_code);
00112 static inline convert_optab init_convert_optab (enum rtx_code);
00113 static void init_libfuncs (optab, int, int, const char *, int);
00114 static void init_integral_libfuncs (optab, const char *, int);
00115 static void init_floating_libfuncs (optab, const char *, int);
00116 static void init_interclass_conv_libfuncs (convert_optab, const char *,
00117 enum mode_class, enum mode_class);
00118 static void init_intraclass_conv_libfuncs (convert_optab, const char *,
00119 enum mode_class, bool);
00120 static void emit_cmp_and_jump_insn_1 (rtx, rtx, enum machine_mode,
00121 enum rtx_code, int, rtx);
00122 static void prepare_float_lib_cmp (rtx *, rtx *, enum rtx_code *,
00123 enum machine_mode *, int *);
00124 static rtx widen_clz (enum machine_mode, rtx, rtx);
00125 static rtx expand_parity (enum machine_mode, rtx, rtx);
00126 static enum rtx_code get_rtx_code (enum tree_code, bool);
00127 static rtx vector_compare_rtx (tree, bool, enum insn_code);
00128
00129 #ifndef HAVE_conditional_trap
00130 #define HAVE_conditional_trap 0
00131 #define gen_conditional_trap(a,b) (gcc_unreachable (), NULL_RTX)
00132 #endif
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 static int
00145 add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
00146 {
00147 rtx last_insn, insn, set;
00148 rtx note;
00149
00150 gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
00151
00152 if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
00153 && GET_RTX_CLASS (code) != RTX_BIN_ARITH
00154 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE
00155 && GET_RTX_CLASS (code) != RTX_COMPARE
00156 && GET_RTX_CLASS (code) != RTX_UNARY)
00157 return 1;
00158
00159 if (GET_CODE (target) == ZERO_EXTRACT)
00160 return 1;
00161
00162 for (last_insn = insns;
00163 NEXT_INSN (last_insn) != NULL_RTX;
00164 last_insn = NEXT_INSN (last_insn))
00165 ;
00166
00167 set = single_set (last_insn);
00168 if (set == NULL_RTX)
00169 return 1;
00170
00171 if (! rtx_equal_p (SET_DEST (set), target)
00172
00173 && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
00174 || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
00175 return 1;
00176
00177
00178
00179 if (reg_overlap_mentioned_p (target, op0)
00180 || (op1 && reg_overlap_mentioned_p (target, op1)))
00181 {
00182 insn = PREV_INSN (last_insn);
00183 while (insn != NULL_RTX)
00184 {
00185 if (reg_set_p (target, insn))
00186 return 0;
00187
00188 insn = PREV_INSN (insn);
00189 }
00190 }
00191
00192 if (GET_RTX_CLASS (code) == RTX_UNARY)
00193 note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
00194 else
00195 note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
00196
00197 set_unique_reg_note (last_insn, REG_EQUAL, note);
00198
00199 return 1;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 static rtx
00209 widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode,
00210 int unsignedp, int no_extend)
00211 {
00212 rtx result;
00213
00214
00215 if (no_extend && GET_MODE (op) == VOIDmode)
00216 return op;
00217
00218
00219
00220
00221 if (! no_extend
00222 || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
00223 && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
00224 return convert_modes (mode, oldmode, op, unsignedp);
00225
00226
00227
00228 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
00229 return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
00230
00231
00232
00233
00234 result = gen_reg_rtx (mode);
00235 emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
00236 emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
00237 return result;
00238 }
00239
00240
00241
00242
00243
00244
00245 optab
00246 optab_for_tree_code (enum tree_code code, tree type)
00247 {
00248 bool trapv;
00249 switch (code)
00250 {
00251 case BIT_AND_EXPR:
00252 return and_optab;
00253
00254 case BIT_IOR_EXPR:
00255 return ior_optab;
00256
00257 case BIT_NOT_EXPR:
00258 return one_cmpl_optab;
00259
00260 case BIT_XOR_EXPR:
00261 return xor_optab;
00262
00263 case TRUNC_MOD_EXPR:
00264 case CEIL_MOD_EXPR:
00265 case FLOOR_MOD_EXPR:
00266 case ROUND_MOD_EXPR:
00267 return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
00268
00269 case RDIV_EXPR:
00270 case TRUNC_DIV_EXPR:
00271 case CEIL_DIV_EXPR:
00272 case FLOOR_DIV_EXPR:
00273 case ROUND_DIV_EXPR:
00274 case EXACT_DIV_EXPR:
00275 return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
00276
00277 case LSHIFT_EXPR:
00278 return ashl_optab;
00279
00280 case RSHIFT_EXPR:
00281 return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
00282
00283 case LROTATE_EXPR:
00284 return rotl_optab;
00285
00286 case RROTATE_EXPR:
00287 return rotr_optab;
00288
00289 case MAX_EXPR:
00290 return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
00291
00292 case MIN_EXPR:
00293 return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
00294
00295 case REALIGN_LOAD_EXPR:
00296 return vec_realign_load_optab;
00297
00298 case WIDEN_SUM_EXPR:
00299 return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
00300
00301 case DOT_PROD_EXPR:
00302 return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
00303
00304 case REDUC_MAX_EXPR:
00305 return TYPE_UNSIGNED (type) ? reduc_umax_optab : reduc_smax_optab;
00306
00307 case REDUC_MIN_EXPR:
00308 return TYPE_UNSIGNED (type) ? reduc_umin_optab : reduc_smin_optab;
00309
00310 case REDUC_PLUS_EXPR:
00311 return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
00312
00313 case VEC_LSHIFT_EXPR:
00314 return vec_shl_optab;
00315
00316 case VEC_RSHIFT_EXPR:
00317 return vec_shr_optab;
00318
00319 default:
00320 break;
00321 }
00322
00323 trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
00324 switch (code)
00325 {
00326 case PLUS_EXPR:
00327 return trapv ? addv_optab : add_optab;
00328
00329 case MINUS_EXPR:
00330 return trapv ? subv_optab : sub_optab;
00331
00332 case MULT_EXPR:
00333 return trapv ? smulv_optab : smul_optab;
00334
00335 case NEGATE_EXPR:
00336 return trapv ? negv_optab : neg_optab;
00337
00338 case ABS_EXPR:
00339 return trapv ? absv_optab : abs_optab;
00340
00341 default:
00342 return NULL;
00343 }
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 rtx
00368 expand_widen_pattern_expr (tree exp, rtx op0, rtx op1, rtx wide_op, rtx target,
00369 int unsignedp)
00370 {
00371 tree oprnd0, oprnd1, oprnd2;
00372 enum machine_mode wmode = 0, tmode0, tmode1 = 0;
00373 optab widen_pattern_optab;
00374 int icode;
00375 enum machine_mode xmode0, xmode1 = 0, wxmode = 0;
00376 rtx temp;
00377 rtx pat;
00378 rtx xop0, xop1, wxop;
00379 int nops = TREE_CODE_LENGTH (TREE_CODE (exp));
00380
00381 oprnd0 = TREE_OPERAND (exp, 0);
00382 tmode0 = TYPE_MODE (TREE_TYPE (oprnd0));
00383 widen_pattern_optab =
00384 optab_for_tree_code (TREE_CODE (exp), TREE_TYPE (oprnd0));
00385 icode = (int) widen_pattern_optab->handlers[(int) tmode0].insn_code;
00386 gcc_assert (icode != CODE_FOR_nothing);
00387 xmode0 = insn_data[icode].operand[1].mode;
00388
00389 if (nops >= 2)
00390 {
00391 oprnd1 = TREE_OPERAND (exp, 1);
00392 tmode1 = TYPE_MODE (TREE_TYPE (oprnd1));
00393 xmode1 = insn_data[icode].operand[2].mode;
00394 }
00395
00396
00397 if (nops == 2)
00398 {
00399 wmode = tmode1;
00400 wxmode = xmode1;
00401 }
00402 else if (nops == 3)
00403 {
00404 gcc_assert (tmode1 == tmode0);
00405 gcc_assert (op1);
00406 oprnd2 = TREE_OPERAND (exp, 2);
00407 wmode = TYPE_MODE (TREE_TYPE (oprnd2));
00408 wxmode = insn_data[icode].operand[3].mode;
00409 }
00410
00411 if (!wide_op)
00412 wmode = wxmode = insn_data[icode].operand[0].mode;
00413
00414 if (!target
00415 || ! (*insn_data[icode].operand[0].predicate) (target, wmode))
00416 temp = gen_reg_rtx (wmode);
00417 else
00418 temp = target;
00419
00420 xop0 = op0;
00421 xop1 = op1;
00422 wxop = wide_op;
00423
00424
00425
00426
00427
00428
00429
00430 if (GET_MODE (op0) != xmode0 && xmode0 != VOIDmode)
00431 xop0 = convert_modes (xmode0,
00432 GET_MODE (op0) != VOIDmode
00433 ? GET_MODE (op0)
00434 : tmode0,
00435 xop0, unsignedp);
00436
00437 if (op1)
00438 if (GET_MODE (op1) != xmode1 && xmode1 != VOIDmode)
00439 xop1 = convert_modes (xmode1,
00440 GET_MODE (op1) != VOIDmode
00441 ? GET_MODE (op1)
00442 : tmode1,
00443 xop1, unsignedp);
00444
00445 if (wide_op)
00446 if (GET_MODE (wide_op) != wxmode && wxmode != VOIDmode)
00447 wxop = convert_modes (wxmode,
00448 GET_MODE (wide_op) != VOIDmode
00449 ? GET_MODE (wide_op)
00450 : wmode,
00451 wxop, unsignedp);
00452
00453
00454
00455
00456 if (! (*insn_data[icode].operand[1].predicate) (xop0, xmode0)
00457 && xmode0 != VOIDmode)
00458 xop0 = copy_to_mode_reg (xmode0, xop0);
00459
00460 if (op1)
00461 {
00462 if (! (*insn_data[icode].operand[2].predicate) (xop1, xmode1)
00463 && xmode1 != VOIDmode)
00464 xop1 = copy_to_mode_reg (xmode1, xop1);
00465
00466 if (wide_op)
00467 {
00468 if (! (*insn_data[icode].operand[3].predicate) (wxop, wxmode)
00469 && wxmode != VOIDmode)
00470 wxop = copy_to_mode_reg (wxmode, wxop);
00471
00472 pat = GEN_FCN (icode) (temp, xop0, xop1, wxop);
00473 }
00474 else
00475 pat = GEN_FCN (icode) (temp, xop0, xop1);
00476 }
00477 else
00478 {
00479 if (wide_op)
00480 {
00481 if (! (*insn_data[icode].operand[2].predicate) (wxop, wxmode)
00482 && wxmode != VOIDmode)
00483 wxop = copy_to_mode_reg (wxmode, wxop);
00484
00485 pat = GEN_FCN (icode) (temp, xop0, wxop);
00486 }
00487 else
00488 pat = GEN_FCN (icode) (temp, xop0);
00489 }
00490
00491 emit_insn (pat);
00492 return temp;
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 rtx
00507 expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
00508 rtx op1, rtx op2, rtx target, int unsignedp)
00509 {
00510 int icode = (int) ternary_optab->handlers[(int) mode].insn_code;
00511 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
00512 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
00513 enum machine_mode mode2 = insn_data[icode].operand[3].mode;
00514 rtx temp;
00515 rtx pat;
00516 rtx xop0 = op0, xop1 = op1, xop2 = op2;
00517
00518 gcc_assert (ternary_optab->handlers[(int) mode].insn_code
00519 != CODE_FOR_nothing);
00520
00521 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
00522 temp = gen_reg_rtx (mode);
00523 else
00524 temp = target;
00525
00526
00527
00528
00529
00530
00531
00532 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
00533 xop0 = convert_modes (mode0,
00534 GET_MODE (op0) != VOIDmode
00535 ? GET_MODE (op0)
00536 : mode,
00537 xop0, unsignedp);
00538
00539 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
00540 xop1 = convert_modes (mode1,
00541 GET_MODE (op1) != VOIDmode
00542 ? GET_MODE (op1)
00543 : mode,
00544 xop1, unsignedp);
00545
00546 if (GET_MODE (op2) != mode2 && mode2 != VOIDmode)
00547 xop2 = convert_modes (mode2,
00548 GET_MODE (op2) != VOIDmode
00549 ? GET_MODE (op2)
00550 : mode,
00551 xop2, unsignedp);
00552
00553
00554
00555
00556 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
00557 && mode0 != VOIDmode)
00558 xop0 = copy_to_mode_reg (mode0, xop0);
00559
00560 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
00561 && mode1 != VOIDmode)
00562 xop1 = copy_to_mode_reg (mode1, xop1);
00563
00564 if (!insn_data[icode].operand[3].predicate (xop2, mode2)
00565 && mode2 != VOIDmode)
00566 xop2 = copy_to_mode_reg (mode2, xop2);
00567
00568 pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
00569
00570 emit_insn (pat);
00571 return temp;
00572 }
00573
00574
00575
00576
00577
00578
00579 static rtx
00580 simplify_expand_binop (enum machine_mode mode, optab binoptab,
00581 rtx op0, rtx op1, rtx target, int unsignedp,
00582 enum optab_methods methods)
00583 {
00584 if (CONSTANT_P (op0) && CONSTANT_P (op1))
00585 {
00586 rtx x = simplify_binary_operation (binoptab->code, mode, op0, op1);
00587
00588 if (x)
00589 return x;
00590 }
00591
00592 return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
00593 }
00594
00595
00596
00597
00598 bool
00599 force_expand_binop (enum machine_mode mode, optab binoptab,
00600 rtx op0, rtx op1, rtx target, int unsignedp,
00601 enum optab_methods methods)
00602 {
00603 rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
00604 target, unsignedp, methods);
00605 if (x == 0)
00606 return false;
00607 if (x != target)
00608 emit_move_insn (target, x);
00609 return true;
00610 }
00611
00612
00613
00614 rtx
00615 expand_vec_shift_expr (tree vec_shift_expr, rtx target)
00616 {
00617 enum insn_code icode;
00618 rtx rtx_op1, rtx_op2;
00619 enum machine_mode mode1;
00620 enum machine_mode mode2;
00621 enum machine_mode mode = TYPE_MODE (TREE_TYPE (vec_shift_expr));
00622 tree vec_oprnd = TREE_OPERAND (vec_shift_expr, 0);
00623 tree shift_oprnd = TREE_OPERAND (vec_shift_expr, 1);
00624 optab shift_optab;
00625 rtx pat;
00626
00627 switch (TREE_CODE (vec_shift_expr))
00628 {
00629 case VEC_RSHIFT_EXPR:
00630 shift_optab = vec_shr_optab;
00631 break;
00632 case VEC_LSHIFT_EXPR:
00633 shift_optab = vec_shl_optab;
00634 break;
00635 default:
00636 gcc_unreachable ();
00637 }
00638
00639 icode = (int) shift_optab->handlers[(int) mode].insn_code;
00640 gcc_assert (icode != CODE_FOR_nothing);
00641
00642 mode1 = insn_data[icode].operand[1].mode;
00643 mode2 = insn_data[icode].operand[2].mode;
00644
00645 rtx_op1 = expand_expr (vec_oprnd, NULL_RTX, VOIDmode, EXPAND_NORMAL);
00646 if (!(*insn_data[icode].operand[1].predicate) (rtx_op1, mode1)
00647 && mode1 != VOIDmode)
00648 rtx_op1 = force_reg (mode1, rtx_op1);
00649
00650 rtx_op2 = expand_expr (shift_oprnd, NULL_RTX, VOIDmode, EXPAND_NORMAL);
00651 if (!(*insn_data[icode].operand[2].predicate) (rtx_op2, mode2)
00652 && mode2 != VOIDmode)
00653 rtx_op2 = force_reg (mode2, rtx_op2);
00654
00655 if (!target
00656 || ! (*insn_data[icode].operand[0].predicate) (target, mode))
00657 target = gen_reg_rtx (mode);
00658
00659
00660 pat = GEN_FCN (icode) (target, rtx_op1, rtx_op2);
00661 gcc_assert (pat);
00662 emit_insn (pat);
00663
00664 return target;
00665 }
00666
00667
00668
00669
00670
00671
00672
00673 static bool
00674 expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
00675 rtx outof_target, rtx into_target,
00676 int unsignedp, enum optab_methods methods)
00677 {
00678 if (into_target != 0)
00679 if (!force_expand_binop (word_mode, binoptab, outof_input, superword_op1,
00680 into_target, unsignedp, methods))
00681 return false;
00682
00683 if (outof_target != 0)
00684 {
00685
00686
00687 if (binoptab != ashr_optab)
00688 emit_move_insn (outof_target, CONST0_RTX (word_mode));
00689 else
00690 if (!force_expand_binop (word_mode, binoptab,
00691 outof_input, GEN_INT (BITS_PER_WORD - 1),
00692 outof_target, unsignedp, methods))
00693 return false;
00694 }
00695 return true;
00696 }
00697
00698
00699
00700
00701
00702 static bool
00703 expand_subword_shift (enum machine_mode op1_mode, optab binoptab,
00704 rtx outof_input, rtx into_input, rtx op1,
00705 rtx outof_target, rtx into_target,
00706 int unsignedp, enum optab_methods methods,
00707 unsigned HOST_WIDE_INT shift_mask)
00708 {
00709 optab reverse_unsigned_shift, unsigned_shift;
00710 rtx tmp, carries;
00711
00712 reverse_unsigned_shift = (binoptab == ashl_optab ? lshr_optab : ashl_optab);
00713 unsigned_shift = (binoptab == ashl_optab ? ashl_optab : lshr_optab);
00714
00715
00716
00717
00718 if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD)
00719 {
00720 carries = outof_input;
00721 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
00722 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
00723 0, true, methods);
00724 }
00725 else
00726 {
00727
00728
00729
00730
00731
00732 carries = expand_binop (word_mode, reverse_unsigned_shift,
00733 outof_input, const1_rtx, 0, unsignedp, methods);
00734 if (shift_mask == BITS_PER_WORD - 1)
00735 {
00736 tmp = immed_double_const (-1, -1, op1_mode);
00737 tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp,
00738 0, true, methods);
00739 }
00740 else
00741 {
00742 tmp = immed_double_const (BITS_PER_WORD - 1, 0, op1_mode);
00743 tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1,
00744 0, true, methods);
00745 }
00746 }
00747 if (tmp == 0 || carries == 0)
00748 return false;
00749 carries = expand_binop (word_mode, reverse_unsigned_shift,
00750 carries, tmp, 0, unsignedp, methods);
00751 if (carries == 0)
00752 return false;
00753
00754
00755
00756 tmp = expand_binop (word_mode, unsigned_shift, into_input, op1,
00757 into_target, unsignedp, methods);
00758 if (tmp == 0)
00759 return false;
00760
00761
00762 if (!force_expand_binop (word_mode, ior_optab, tmp, carries,
00763 into_target, unsignedp, methods))
00764 return false;
00765
00766
00767 if (outof_target != 0)
00768 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
00769 outof_target, unsignedp, methods))
00770 return false;
00771
00772 return true;
00773 }
00774
00775
00776 #ifdef HAVE_conditional_move
00777
00778
00779
00780
00781
00782
00783 static bool
00784 expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab,
00785 enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
00786 rtx outof_input, rtx into_input,
00787 rtx subword_op1, rtx superword_op1,
00788 rtx outof_target, rtx into_target,
00789 int unsignedp, enum optab_methods methods,
00790 unsigned HOST_WIDE_INT shift_mask)
00791 {
00792 rtx outof_superword, into_superword;
00793
00794
00795
00796 outof_superword = outof_target != 0 ? gen_reg_rtx (word_mode) : 0;
00797 if (outof_target != 0 && subword_op1 == superword_op1)
00798 {
00799
00800
00801 into_superword = outof_target;
00802 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
00803 outof_superword, 0, unsignedp, methods))
00804 return false;
00805 }
00806 else
00807 {
00808 into_superword = gen_reg_rtx (word_mode);
00809 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
00810 outof_superword, into_superword,
00811 unsignedp, methods))
00812 return false;
00813 }
00814
00815
00816 if (!expand_subword_shift (op1_mode, binoptab,
00817 outof_input, into_input, subword_op1,
00818 outof_target, into_target,
00819 unsignedp, methods, shift_mask))
00820 return false;
00821
00822
00823
00824 if (!emit_conditional_move (into_target, cmp_code, cmp1, cmp2, op1_mode,
00825 into_target, into_superword, word_mode, false))
00826 return false;
00827
00828 if (outof_target != 0)
00829 if (!emit_conditional_move (outof_target, cmp_code, cmp1, cmp2, op1_mode,
00830 outof_target, outof_superword,
00831 word_mode, false))
00832 return false;
00833
00834 return true;
00835 }
00836 #endif
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 static bool
00868 expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
00869 rtx outof_input, rtx into_input, rtx op1,
00870 rtx outof_target, rtx into_target,
00871 int unsignedp, enum optab_methods methods,
00872 unsigned HOST_WIDE_INT shift_mask)
00873 {
00874 rtx superword_op1, tmp, cmp1, cmp2;
00875 rtx subword_label, done_label;
00876 enum rtx_code cmp_code;
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 if (shift_mask >= BITS_PER_WORD
00887 && outof_target != 0
00888 && !CONSTANT_P (op1))
00889 {
00890 if (!expand_doubleword_shift (op1_mode, binoptab,
00891 outof_input, into_input, op1,
00892 0, into_target,
00893 unsignedp, methods, shift_mask))
00894 return false;
00895 if (!force_expand_binop (word_mode, binoptab, outof_input, op1,
00896 outof_target, unsignedp, methods))
00897 return false;
00898 return true;
00899 }
00900
00901
00902
00903
00904
00905 tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode);
00906 if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1)
00907 {
00908
00909
00910 cmp1 = simplify_expand_binop (op1_mode, and_optab, op1, tmp,
00911 0, true, methods);
00912 cmp2 = CONST0_RTX (op1_mode);
00913 cmp_code = EQ;
00914 superword_op1 = op1;
00915 }
00916 else
00917 {
00918
00919 cmp1 = simplify_expand_binop (op1_mode, sub_optab, op1, tmp,
00920 0, true, methods);
00921 cmp2 = CONST0_RTX (op1_mode);
00922 cmp_code = LT;
00923 superword_op1 = cmp1;
00924 }
00925 if (cmp1 == 0)
00926 return false;
00927
00928
00929
00930 tmp = simplify_relational_operation (cmp_code, SImode, op1_mode, cmp1, cmp2);
00931 if (tmp != 0 && GET_CODE (tmp) == CONST_INT)
00932 {
00933 if (tmp == const0_rtx)
00934 return expand_superword_shift (binoptab, outof_input, superword_op1,
00935 outof_target, into_target,
00936 unsignedp, methods);
00937 else
00938 return expand_subword_shift (op1_mode, binoptab,
00939 outof_input, into_input, op1,
00940 outof_target, into_target,
00941 unsignedp, methods, shift_mask);
00942 }
00943
00944 #ifdef HAVE_conditional_move
00945
00946 {
00947 rtx start = get_last_insn ();
00948 if (expand_doubleword_shift_condmove (op1_mode, binoptab,
00949 cmp_code, cmp1, cmp2,
00950 outof_input, into_input,
00951 op1, superword_op1,
00952 outof_target, into_target,
00953 unsignedp, methods, shift_mask))
00954 return true;
00955 delete_insns_since (start);
00956 }
00957 #endif
00958
00959
00960 subword_label = gen_label_rtx ();
00961 done_label = gen_label_rtx ();
00962
00963 NO_DEFER_POP;
00964 do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
00965 0, 0, subword_label);
00966 OK_DEFER_POP;
00967
00968 if (!expand_superword_shift (binoptab, outof_input, superword_op1,
00969 outof_target, into_target,
00970 unsignedp, methods))
00971 return false;
00972
00973 emit_jump_insn (gen_jump (done_label));
00974 emit_barrier ();
00975 emit_label (subword_label);
00976
00977 if (!expand_subword_shift (op1_mode, binoptab,
00978 outof_input, into_input, op1,
00979 outof_target, into_target,
00980 unsignedp, methods, shift_mask))
00981 return false;
00982
00983 emit_label (done_label);
00984 return true;
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 static rtx
01044 expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
01045 bool umulp, enum optab_methods methods)
01046 {
01047 int low = (WORDS_BIG_ENDIAN ? 1 : 0);
01048 int high = (WORDS_BIG_ENDIAN ? 0 : 1);
01049 rtx wordm1 = umulp ? NULL_RTX : GEN_INT (BITS_PER_WORD - 1);
01050 rtx product, adjust, product_high, temp;
01051
01052 rtx op0_high = operand_subword_force (op0, high, mode);
01053 rtx op0_low = operand_subword_force (op0, low, mode);
01054 rtx op1_high = operand_subword_force (op1, high, mode);
01055 rtx op1_low = operand_subword_force (op1, low, mode);
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 if (!umulp)
01068 {
01069
01070 temp = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
01071 NULL_RTX, 1, methods);
01072 if (temp)
01073 op0_high = expand_binop (word_mode, add_optab, op0_high, temp,
01074 NULL_RTX, 0, OPTAB_DIRECT);
01075 else
01076 {
01077 temp = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
01078 NULL_RTX, 0, methods);
01079 if (!temp)
01080 return NULL_RTX;
01081 op0_high = expand_binop (word_mode, sub_optab, op0_high, temp,
01082 NULL_RTX, 0, OPTAB_DIRECT);
01083 }
01084
01085 if (!op0_high)
01086 return NULL_RTX;
01087 }
01088
01089 adjust = expand_binop (word_mode, smul_optab, op0_high, op1_low,
01090 NULL_RTX, 0, OPTAB_DIRECT);
01091 if (!adjust)
01092 return NULL_RTX;
01093
01094
01095
01096 if (!umulp)
01097 {
01098
01099 temp = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
01100 NULL_RTX, 1, methods);
01101 if (temp)
01102 op1_high = expand_binop (word_mode, add_optab, op1_high, temp,
01103 NULL_RTX, 0, OPTAB_DIRECT);
01104 else
01105 {
01106 temp = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
01107 NULL_RTX, 0, methods);
01108 if (!temp)
01109 return NULL_RTX;
01110 op1_high = expand_binop (word_mode, sub_optab, op1_high, temp,
01111 NULL_RTX, 0, OPTAB_DIRECT);
01112 }
01113
01114 if (!op1_high)
01115 return NULL_RTX;
01116 }
01117
01118 temp = expand_binop (word_mode, smul_optab, op1_high, op0_low,
01119 NULL_RTX, 0, OPTAB_DIRECT);
01120 if (!temp)
01121 return NULL_RTX;
01122
01123
01124
01125 adjust = expand_binop (word_mode, add_optab, adjust, temp,
01126 adjust, 0, OPTAB_DIRECT);
01127
01128 if (target && !REG_P (target))
01129 target = NULL_RTX;
01130
01131 if (umulp)
01132 product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
01133 target, 1, OPTAB_DIRECT);
01134 else
01135 product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
01136 target, 1, OPTAB_DIRECT);
01137
01138 if (!product)
01139 return NULL_RTX;
01140
01141 product_high = operand_subword (product, high, 1, mode);
01142 adjust = expand_binop (word_mode, add_optab, product_high, adjust,
01143 REG_P (product_high) ? product_high : adjust,
01144 0, OPTAB_DIRECT);
01145 emit_move_insn (product_high, adjust);
01146 return product;
01147 }
01148
01149
01150
01151
01152 rtx
01153 expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
01154 rtx op1, rtx target, int unsignedp,
01155 enum optab_methods methods)
01156 {
01157 optab binop = code_to_optab[(int) code];
01158 gcc_assert (binop);
01159
01160 return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
01161 }
01162
01163
01164
01165
01166 static bool
01167 swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
01168 {
01169 int op0_prec = commutative_operand_precedence (op0);
01170 int op1_prec = commutative_operand_precedence (op1);
01171
01172 if (op0_prec < op1_prec)
01173 return true;
01174
01175 if (op0_prec > op1_prec)
01176 return false;
01177
01178
01179
01180 if (target == 0 || REG_P (target))
01181 return (REG_P (op1) && !REG_P (op0)) || target == op1;
01182 else
01183 return rtx_equal_p (op1, target);
01184 }
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198 rtx
01199 expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
01200 rtx target, int unsignedp, enum optab_methods methods)
01201 {
01202 enum optab_methods next_methods
01203 = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
01204 ? OPTAB_WIDEN : methods);
01205 enum mode_class class;
01206 enum machine_mode wider_mode;
01207 rtx temp;
01208 int commutative_op = 0;
01209 int shift_op = (binoptab->code == ASHIFT
01210 || binoptab->code == ASHIFTRT
01211 || binoptab->code == LSHIFTRT
01212 || binoptab->code == ROTATE
01213 || binoptab->code == ROTATERT);
01214 rtx entry_last = get_last_insn ();
01215 rtx last;
01216 bool first_pass_p = true;
01217
01218 class = GET_MODE_CLASS (mode);
01219
01220
01221
01222
01223 if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
01224 {
01225 op1 = negate_rtx (mode, op1);
01226 binoptab = add_optab;
01227 }
01228
01229
01230
01231 if (CONSTANT_P (op0) && optimize
01232 && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
01233 {
01234 if (GET_MODE (op0) != VOIDmode)
01235 op0 = convert_modes (mode, VOIDmode, op0, unsignedp);
01236 op0 = force_reg (mode, op0);
01237 }
01238
01239 if (CONSTANT_P (op1) && optimize
01240 && ! shift_op && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
01241 {
01242 if (GET_MODE (op1) != VOIDmode)
01243 op1 = convert_modes (mode, VOIDmode, op1, unsignedp);
01244 op1 = force_reg (mode, op1);
01245 }
01246
01247
01248 last = get_last_insn ();
01249
01250
01251
01252
01253
01254 if (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
01255 || binoptab == smul_widen_optab
01256 || binoptab == umul_widen_optab
01257 || binoptab == smul_highpart_optab
01258 || binoptab == umul_highpart_optab)
01259 {
01260 commutative_op = 1;
01261
01262 if (swap_commutative_operands_with_target (target, op0, op1))
01263 {
01264 temp = op1;
01265 op1 = op0;
01266 op0 = temp;
01267 }
01268 }
01269
01270 retry:
01271
01272
01273
01274 if (methods != OPTAB_MUST_WIDEN
01275 && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
01276 {
01277 int icode = (int) binoptab->handlers[(int) mode].insn_code;
01278 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
01279 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
01280 rtx pat;
01281 rtx xop0 = op0, xop1 = op1;
01282
01283 if (target)
01284 temp = target;
01285 else
01286 temp = gen_reg_rtx (mode);
01287
01288
01289
01290 if (commutative_op)
01291 {
01292 if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
01293 && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
01294 {
01295 rtx tmp;
01296
01297 tmp = op0; op0 = op1; op1 = tmp;
01298 tmp = xop0; xop0 = xop1; xop1 = tmp;
01299 }
01300 }
01301
01302
01303
01304
01305
01306
01307
01308 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
01309 xop0 = convert_modes (mode0,
01310 GET_MODE (op0) != VOIDmode
01311 ? GET_MODE (op0)
01312 : mode,
01313 xop0, unsignedp);
01314
01315 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
01316 xop1 = convert_modes (mode1,
01317 GET_MODE (op1) != VOIDmode
01318 ? GET_MODE (op1)
01319 : mode,
01320 xop1, unsignedp);
01321
01322
01323
01324
01325 if (!insn_data[icode].operand[1].predicate (xop0, mode0)
01326 && mode0 != VOIDmode)
01327 xop0 = copy_to_mode_reg (mode0, xop0);
01328
01329 if (!insn_data[icode].operand[2].predicate (xop1, mode1)
01330 && mode1 != VOIDmode)
01331 xop1 = copy_to_mode_reg (mode1, xop1);
01332
01333 if (!insn_data[icode].operand[0].predicate (temp, mode))
01334 temp = gen_reg_rtx (mode);
01335
01336 pat = GEN_FCN (icode) (temp, xop0, xop1);
01337 if (pat)
01338 {
01339
01340
01341
01342 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
01343 && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
01344 {
01345 delete_insns_since (last);
01346 return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
01347 unsignedp, methods);
01348 }
01349
01350 emit_insn (pat);
01351 return temp;
01352 }
01353 else
01354 delete_insns_since (last);
01355 }
01356
01357
01358
01359
01360 if (first_pass_p
01361 && (binoptab == rotl_optab || binoptab == rotr_optab)
01362 && class == MODE_INT
01363 && GET_CODE (op1) == CONST_INT
01364 && INTVAL (op1) > 0
01365 && (unsigned int) INTVAL (op1) < GET_MODE_BITSIZE (mode))
01366 {
01367 first_pass_p = false;
01368 op1 = GEN_INT (GET_MODE_BITSIZE (mode) - INTVAL (op1));
01369 binoptab = binoptab == rotl_optab ? rotr_optab : rotl_optab;
01370 goto retry;
01371 }
01372
01373
01374
01375
01376 if (binoptab == smul_optab
01377 && GET_MODE_WIDER_MODE (mode) != VOIDmode
01378 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
01379 ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
01380 != CODE_FOR_nothing))
01381 {
01382 temp = expand_binop (GET_MODE_WIDER_MODE (mode),
01383 unsignedp ? umul_widen_optab : smul_widen_optab,
01384 op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
01385
01386 if (temp != 0)
01387 {
01388 if (GET_MODE_CLASS (mode) == MODE_INT
01389 && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
01390 GET_MODE_BITSIZE (GET_MODE (temp))))
01391 return gen_lowpart (mode, temp);
01392 else
01393 return convert_to_mode (mode, temp, unsignedp);
01394 }
01395 }
01396
01397
01398
01399
01400
01401 if (CLASS_HAS_WIDER_MODES_P (class)
01402 && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
01403 for (wider_mode = GET_MODE_WIDER_MODE (mode);
01404 wider_mode != VOIDmode;
01405 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
01406 {
01407 if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
01408 || (binoptab == smul_optab
01409 && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
01410 && (((unsignedp ? umul_widen_optab : smul_widen_optab)
01411 ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
01412 != CODE_FOR_nothing)))
01413 {
01414 rtx xop0 = op0, xop1 = op1;
01415 int no_extend = 0;
01416
01417
01418
01419
01420
01421 if ((binoptab == ior_optab || binoptab == and_optab
01422 || binoptab == xor_optab
01423 || binoptab == add_optab || binoptab == sub_optab
01424 || binoptab == smul_optab || binoptab == ashl_optab)
01425 && class == MODE_INT)
01426 no_extend = 1;
01427
01428 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
01429
01430
01431 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
01432 no_extend && binoptab != ashl_optab);
01433
01434 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
01435 unsignedp, OPTAB_DIRECT);
01436 if (temp)
01437 {
01438 if (class != MODE_INT
01439 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
01440 GET_MODE_BITSIZE (wider_mode)))
01441 {
01442 if (target == 0)
01443 target = gen_reg_rtx (mode);
01444 convert_move (target, temp, 0);
01445 return target;
01446 }
01447 else
01448 return gen_lowpart (mode, temp);
01449 }
01450 else
01451 delete_insns_since (last);
01452 }
01453 }
01454
01455
01456 if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
01457 && class == MODE_INT
01458 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
01459 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
01460 {
01461 int i;
01462 rtx insns;
01463 rtx equiv_value;
01464
01465
01466
01467 if (target == 0 || target == op0 || target == op1)
01468 target = gen_reg_rtx (mode);
01469
01470 start_sequence ();
01471
01472
01473 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
01474 {
01475 rtx target_piece = operand_subword (target, i, 1, mode);
01476 rtx x = expand_binop (word_mode, binoptab,
01477 operand_subword_force (op0, i, mode),
01478 operand_subword_force (op1, i, mode),
01479 target_piece, unsignedp, next_methods);
01480
01481 if (x == 0)
01482 break;
01483
01484 if (target_piece != x)
01485 emit_move_insn (target_piece, x);
01486 }
01487
01488 insns = get_insns ();
01489 end_sequence ();
01490
01491 if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
01492 {
01493 if (binoptab->code != UNKNOWN)
01494 equiv_value
01495 = gen_rtx_fmt_ee (binoptab->code, mode,
01496 copy_rtx (op0), copy_rtx (op1));
01497 else
01498 equiv_value = 0;
01499
01500 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
01501 return target;
01502 }
01503 }
01504
01505
01506 if ((binoptab == lshr_optab || binoptab == ashl_optab
01507 || binoptab == ashr_optab)
01508 && class == MODE_INT
01509 && (GET_CODE (op1) == CONST_INT || !optimize_size)
01510 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
01511 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
01512 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
01513 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
01514 {
01515 unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
01516 enum machine_mode op1_mode;
01517
01518 double_shift_mask = targetm.shift_truncation_mask (mode);
01519 shift_mask = targetm.shift_truncation_mask (word_mode);
01520 op1_mode = GET_MODE (op1) != VOIDmode ? GET_MODE (op1) : word_mode;
01521
01522
01523 if (double_shift_mask > 0 && GET_CODE (op1) == CONST_INT)
01524 op1 = GEN_INT (INTVAL (op1) & double_shift_mask);
01525
01526 if (op1 == CONST0_RTX (op1_mode))
01527 return op0;
01528
01529
01530
01531 if (double_shift_mask == 0
01532 || (shift_mask == BITS_PER_WORD - 1
01533 && double_shift_mask == BITS_PER_WORD * 2 - 1))
01534 {
01535 rtx insns, equiv_value;
01536 rtx into_target, outof_target;
01537 rtx into_input, outof_input;
01538 int left_shift, outof_word;
01539
01540
01541
01542 if (target == 0 || target == op0 || target == op1)
01543 target = gen_reg_rtx (mode);
01544
01545 start_sequence ();
01546
01547
01548
01549
01550
01551
01552 left_shift = binoptab == ashl_optab;
01553 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
01554
01555 outof_target = operand_subword (target, outof_word, 1, mode);
01556 into_target = operand_subword (target, 1 - outof_word, 1, mode);
01557
01558 outof_input = operand_subword_force (op0, outof_word, mode);
01559 into_input = operand_subword_force (op0, 1 - outof_word, mode);
01560
01561 if (expand_doubleword_shift (op1_mode, binoptab,
01562 outof_input, into_input, op1,
01563 outof_target, into_target,
01564 unsignedp, next_methods, shift_mask))
01565 {
01566 insns = get_insns ();
01567 end_sequence ();
01568
01569 equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
01570 emit_no_conflict_block (insns, target, op0, op1, equiv_value);
01571 return target;
01572 }
01573 end_sequence ();
01574 }
01575 }
01576
01577
01578 if ((binoptab == rotl_optab || binoptab == rotr_optab)
01579 && class == MODE_INT
01580 && GET_CODE (op1) == CONST_INT
01581 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
01582 && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
01583 && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
01584 {
01585 rtx insns;
01586 rtx into_target, outof_target;
01587 rtx into_input, outof_input;
01588 rtx inter;
01589 int shift_count, left_shift, outof_word;
01590
01591
01592
01593
01594
01595
01596
01597 if (target == 0 || target == op0 || target == op1 || ! REG_P (target))
01598 target = gen_reg_rtx (mode);
01599
01600 start_sequence ();
01601
01602 shift_count = INTVAL (op1);
01603
01604
01605
01606
01607
01608
01609 left_shift = (binoptab == rotl_optab);
01610 outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
01611
01612 outof_target = operand_subword (target, outof_word, 1, mode);
01613 into_target = operand_subword (target, 1 - outof_word, 1, mode);
01614
01615 outof_input = operand_subword_force (op0, outof_word, mode);
01616 into_input = operand_subword_force (op0, 1 - outof_word, mode);
01617
01618 if (shift_count == BITS_PER_WORD)
01619 {
01620
01621 emit_move_insn (outof_target, into_input);
01622 emit_move_insn (into_target, outof_input);
01623 inter = const0_rtx;
01624 }
01625 else
01626 {
01627 rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
01628 rtx first_shift_count, second_shift_count;
01629 optab reverse_unsigned_shift, unsigned_shift;
01630
01631 reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
01632 ? lshr_optab : ashl_optab);
01633
01634 unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
01635 ? ashl_optab : lshr_optab);
01636
01637 if (shift_count > BITS_PER_WORD)
01638 {
01639 first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
01640 second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
01641 }
01642 else
01643 {
01644 first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
01645 second_shift_count = GEN_INT (shift_count);
01646 }
01647
01648 into_temp1 = expand_binop (word_mode, unsigned_shift,
01649 outof_input, first_shift_count,
01650 NULL_RTX, unsignedp, next_methods);
01651 into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
01652 into_input, second_shift_count,
01653 NULL_RTX, unsignedp, next_methods);
01654
01655 if (into_temp1 != 0 && into_temp2 != 0)
01656 inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
01657 into_target, unsignedp, next_methods);
01658 else
01659 inter = 0;
01660
01661 if (inter != 0 && inter != into_target)
01662 emit_move_insn (into_target, inter);
01663
01664 outof_temp1 = expand_binop (word_mode, unsigned_shift,
01665 into_input, first_shift_count,
01666 NULL_RTX, unsignedp, next_methods);
01667 outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
01668 outof_input, second_shift_count,
01669 NULL_RTX, unsignedp, next_methods);
01670
01671 if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
01672 inter = expand_binop (word_mode, ior_optab,
01673 outof_temp1, outof_temp2,
01674 outof_target, unsignedp, next_methods);
01675
01676 if (inter != 0 && inter != outof_target)
01677 emit_move_insn (outof_target, inter);
01678 }
01679
01680 insns = get_insns ();
01681 end_sequence ();
01682
01683 if (inter != 0)
01684 {
01685
01686
01687
01688
01689
01690 emit_insn (insns);
01691 return target;
01692 }
01693 }
01694
01695
01696 if ((binoptab == add_optab || binoptab == sub_optab)
01697 && class == MODE_INT
01698 && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
01699 && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
01700 {
01701 unsigned int i;
01702 optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
01703 const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
01704 rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
01705 rtx xop0, xop1, xtarget;
01706
01707
01708
01709
01710 #if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
01711 int normalizep = STORE_FLAG_VALUE;
01712 #else
01713 int normalizep = 1;
01714 #endif
01715
01716
01717 xop0 = force_reg (mode, op0);
01718 xop1 = force_reg (mode, op1);
01719
01720 xtarget = gen_reg_rtx (mode);
01721
01722 if (target == 0 || !REG_P (target))
01723 target = xtarget;
01724
01725
01726 if (REG_P (target))
01727 emit_insn (gen_rtx_CLOBBER (VOIDmode, xtarget));
01728
01729
01730 for (i = 0; i < nwords; i++)
01731 {
01732 int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
01733 rtx target_piece = operand_subword (xtarget, index, 1, mode);
01734 rtx op0_piece = operand_subword_force (xop0, index, mode);
01735 rtx op1_piece = operand_subword_force (xop1, index, mode);
01736 rtx x;
01737
01738
01739 x = expand_binop (word_mode, binoptab,
01740 op0_piece, op1_piece,
01741 target_piece, unsignedp, next_methods);
01742 if (x == 0)
01743 break;
01744
01745 if (i + 1 < nwords)
01746 {
01747
01748 carry_out = gen_reg_rtx (word_mode);
01749 carry_out = emit_store_flag_force (carry_out,
01750 (binoptab == add_optab
01751 ? LT : GT),
01752 x, op0_piece,
01753 word_mode, 1, normalizep);
01754 }
01755
01756 if (i > 0)
01757 {
01758 rtx newx;
01759
01760
01761 newx = expand_binop (word_mode,
01762 normalizep == 1 ? binoptab : otheroptab,
01763 x, carry_in,
01764 NULL_RTX, 1, next_methods);
01765
01766 if (i + 1 < nwords)
01767 {
01768
01769 rtx carry_tmp = gen_reg_rtx (word_mode);
01770 carry_tmp = emit_store_flag_force (carry_tmp,
01771 (binoptab == add_optab
01772 ? LT : GT),
01773 newx, x,
01774 word_mode, 1, normalizep);
01775
01776
01777 carry_out = expand_binop (word_mode, ior_optab,
01778 carry_out, carry_tmp,
01779 carry_out, 0, next_methods);
01780 if (carry_out == 0)
01781 break;
01782 }
01783 emit_move_insn (target_piece, newx);
01784 }
01785 else
01786 {
01787 if (x != target_piece)
01788 emit_move_insn (target_piece, x);
01789 }
01790
01791 carry_in = carry_out;
01792 }
01793
01794 if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
01795 {
01796 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
01797 || ! rtx_equal_p (target, xtarget))
01798 {
01799 rtx temp = emit_move_insn (target, xtarget);
01800
01801 set_unique_reg_note (temp,
01802 REG_EQUAL,
01803 gen_rtx_fmt_ee (binoptab->code, mode,
01804 copy_rtx (xop0),
01805 copy_rtx (xop1)));
01806 }
01807 else
01808 target = xtarget;
01809
01810 return target;
01811 }
01812
01813 else
01814 delete_insns_since (last);
01815 }
01816
01817
01818
01819
01820
01821
01822 if (binoptab == smul_optab
01823 && class == MODE_INT
01824 && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
01825 && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
01826 && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
01827 {
01828 rtx product = NULL_RTX;
01829
01830 if (umul_widen_optab->handlers[(int) mode].insn_code
01831 != CODE_FOR_nothing)
01832 {
01833 product = expand_doubleword_mult (mode, op0, op1, target,
01834 true, methods);
01835 if (!product)
01836 delete_insns_since (last);
01837 }
01838
01839 if (product == NULL_RTX
01840 && smul_widen_optab->handlers[(int) mode].insn_code
01841 != CODE_FOR_nothing)
01842 {
01843 product = expand_doubleword_mult (mode, op0, op1, target,
01844 false, methods);
01845 if (!product)
01846 delete_insns_since (last);
01847 }
01848
01849 if (product != NULL_RTX)
01850 {
01851 if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
01852 {
01853 temp = emit_move_insn (target ? target : product, product);
01854 set_unique_reg_note (temp,
01855 REG_EQUAL,
01856 gen_rtx_fmt_ee (MULT, mode,
01857 copy_rtx (op0),
01858 copy_rtx (op1)));
01859 }
01860 return product;
01861 }
01862 }
01863
01864
01865
01866
01867 if (binoptab->handlers[(int) mode].libfunc
01868 && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
01869 {
01870 rtx insns;
01871 rtx op1x = op1;
01872 enum machine_mode op1_mode = mode;
01873 rtx value;
01874
01875 start_sequence ();
01876
01877 if (shift_op)
01878 {
01879 op1_mode = word_mode;
01880
01881
01882 op1x = convert_to_mode (word_mode, op1, 1);
01883 }
01884
01885 if (GET_MODE (op0) != VOIDmode
01886 && GET_MODE (op0) != mode)
01887 op0 = convert_to_mode (mode, op0, unsignedp);
01888
01889
01890
01891 value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
01892 NULL_RTX, LCT_CONST, mode, 2,
01893 op0, mode, op1x, op1_mode);
01894
01895 insns = get_insns ();
01896 end_sequence ();
01897
01898 target = gen_reg_rtx (mode);
01899 emit_libcall_block (insns, target, value,
01900 gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
01901
01902 return target;
01903 }
01904
01905 delete_insns_since (last);
01906
01907
01908
01909 if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
01910 || methods == OPTAB_MUST_WIDEN))
01911 {
01912
01913 delete_insns_since (entry_last);
01914 return 0;
01915 }
01916
01917
01918
01919
01920 methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
01921
01922
01923
01924
01925 if (CLASS_HAS_WIDER_MODES_P (class))
01926 {
01927 for (wider_mode = GET_MODE_WIDER_MODE (mode);
01928 wider_mode != VOIDmode;
01929 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
01930 {
01931 if ((binoptab->handlers[(int) wider_mode].insn_code
01932 != CODE_FOR_nothing)
01933 || (methods == OPTAB_LIB
01934 && binoptab->handlers[(int) wider_mode].libfunc))
01935 {
01936 rtx xop0 = op0, xop1 = op1;
01937 int no_extend = 0;
01938
01939
01940
01941
01942
01943 if ((binoptab == ior_optab || binoptab == and_optab
01944 || binoptab == xor_optab
01945 || binoptab == add_optab || binoptab == sub_optab
01946 || binoptab == smul_optab || binoptab == ashl_optab)
01947 && class == MODE_INT)
01948 no_extend = 1;
01949
01950 xop0 = widen_operand (xop0, wider_mode, mode,
01951 unsignedp, no_extend);
01952
01953
01954 xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
01955 no_extend && binoptab != ashl_optab);
01956
01957 temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
01958 unsignedp, methods);
01959 if (temp)
01960 {
01961 if (class != MODE_INT
01962 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
01963 GET_MODE_BITSIZE (wider_mode)))
01964 {
01965 if (target == 0)
01966 target = gen_reg_rtx (mode);
01967 convert_move (target, temp, 0);
01968 return target;
01969 }
01970 else
01971 return gen_lowpart (mode, temp);
01972 }
01973 else
01974 delete_insns_since (last);
01975 }
01976 }
01977 }
01978
01979 delete_insns_since (entry_last);
01980 return 0;
01981 }
01982
01983
01984
01985
01986
01987
01988
01989
01990 rtx
01991 sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
01992 rtx op0, rtx op1, rtx target, int unsignedp,
01993 enum optab_methods methods)
01994 {
01995 rtx temp;
01996 optab direct_optab = unsignedp ? uoptab : soptab;
01997 struct optab wide_soptab;
01998
01999
02000 temp = expand_binop (mode, direct_optab, op0, op1, target,
02001 unsignedp, OPTAB_DIRECT);
02002 if (temp || methods == OPTAB_DIRECT)
02003 return temp;
02004
02005
02006
02007 wide_soptab = *soptab;
02008 wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
02009 wide_soptab.handlers[(int) mode].libfunc = 0;
02010
02011 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
02012 unsignedp, OPTAB_WIDEN);
02013
02014
02015 if (temp == 0 && unsignedp)
02016 temp = expand_binop (mode, uoptab, op0, op1, target,
02017 unsignedp, OPTAB_WIDEN);
02018 if (temp || methods == OPTAB_WIDEN)
02019 return temp;
02020
02021
02022 temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
02023 if (temp || methods == OPTAB_LIB)
02024 return temp;
02025
02026
02027 temp = expand_binop (mode, &wide_soptab, op0, op1, target,
02028 unsignedp, methods);
02029 if (temp != 0)
02030 return temp;
02031 if (unsignedp)
02032 return expand_binop (mode, uoptab, op0, op1, target,
02033 unsignedp, methods);
02034 return 0;
02035 }
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048 int
02049 expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
02050 int unsignedp)
02051 {
02052 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
02053 enum mode_class class;
02054 enum machine_mode wider_mode;
02055 rtx entry_last = get_last_insn ();
02056 rtx last;
02057
02058 class = GET_MODE_CLASS (mode);
02059
02060 if (!targ0)
02061 targ0 = gen_reg_rtx (mode);
02062 if (!targ1)
02063 targ1 = gen_reg_rtx (mode);
02064
02065
02066 last = get_last_insn ();
02067
02068 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
02069 {
02070 int icode = (int) unoptab->handlers[(int) mode].insn_code;
02071 enum machine_mode mode0 = insn_data[icode].operand[2].mode;
02072 rtx pat;
02073 rtx xop0 = op0;
02074
02075 if (GET_MODE (xop0) != VOIDmode
02076 && GET_MODE (xop0) != mode0)
02077 xop0 = convert_to_mode (mode0, xop0, unsignedp);
02078
02079
02080 if (!insn_data[icode].operand[2].predicate (xop0, mode0))
02081 xop0 = copy_to_mode_reg (mode0, xop0);
02082
02083
02084
02085 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
02086 gcc_assert (insn_data[icode].operand[1].predicate (targ1, mode));
02087
02088 pat = GEN_FCN (icode) (targ0, targ1, xop0);
02089 if (pat)
02090 {
02091 emit_insn (pat);
02092 return 1;
02093 }
02094 else
02095 delete_insns_since (last);
02096 }
02097
02098
02099
02100 if (CLASS_HAS_WIDER_MODES_P (class))
02101 {
02102 for (wider_mode = GET_MODE_WIDER_MODE (mode);
02103 wider_mode != VOIDmode;
02104 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
02105 {
02106 if (unoptab->handlers[(int) wider_mode].insn_code
02107 != CODE_FOR_nothing)
02108 {
02109 rtx t0 = gen_reg_rtx (wider_mode);
02110 rtx t1 = gen_reg_rtx (wider_mode);
02111 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
02112
02113 if (expand_twoval_unop (unoptab, cop0, t0, t1, unsignedp))
02114 {
02115 convert_move (targ0, t0, unsignedp);
02116 convert_move (targ1, t1, unsignedp);
02117 return 1;
02118 }
02119 else
02120 delete_insns_since (last);
02121 }
02122 }
02123 }
02124
02125 delete_insns_since (entry_last);
02126 return 0;
02127 }
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141 int
02142 expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
02143 int unsignedp)
02144 {
02145 enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
02146 enum mode_class class;
02147 enum machine_mode wider_mode;
02148 rtx entry_last = get_last_insn ();
02149 rtx last;
02150
02151 class = GET_MODE_CLASS (mode);
02152
02153
02154
02155 if (CONSTANT_P (op0) && optimize
02156 && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
02157 op0 = force_reg (mode, op0);
02158
02159 if (CONSTANT_P (op1) && optimize
02160 && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
02161 op1 = force_reg (mode, op1);
02162
02163 if (!targ0)
02164 targ0 = gen_reg_rtx (mode);
02165 if (!targ1)
02166 targ1 = gen_reg_rtx (mode);
02167
02168
02169 last = get_last_insn ();
02170
02171 if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
02172 {
02173 int icode = (int) binoptab->handlers[(int) mode].insn_code;
02174 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
02175 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
02176 rtx pat;
02177 rtx xop0 = op0, xop1 = op1;
02178
02179
02180
02181
02182
02183
02184
02185 if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
02186 xop0 = convert_modes (mode0,
02187 GET_MODE (op0) != VOIDmode
02188 ? GET_MODE (op0)
02189 : mode,
02190 xop0, unsignedp);
02191
02192 if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
02193 xop1 = convert_modes (mode1,
02194 GET_MODE (op1) != VOIDmode
02195 ? GET_MODE (op1)
02196 : mode,
02197 xop1, unsignedp);
02198
02199
02200 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
02201 xop0 = copy_to_mode_reg (mode0, xop0);
02202
02203 if (!insn_data[icode].operand[2].predicate (xop1, mode1))
02204 xop1 = copy_to_mode_reg (mode1, xop1);
02205
02206
02207
02208 gcc_assert (insn_data[icode].operand[0].predicate (targ0, mode));
02209 gcc_assert (insn_data[icode].operand[3].predicate (targ1, mode));
02210
02211 pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
02212 if (pat)
02213 {
02214 emit_insn (pat);
02215 return 1;
02216 }
02217 else
02218 delete_insns_since (last);
02219 }
02220
02221
02222
02223 if (CLASS_HAS_WIDER_MODES_P (class))
02224 {
02225 for (wider_mode = GET_MODE_WIDER_MODE (mode);
02226 wider_mode != VOIDmode;
02227 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
02228 {
02229 if (binoptab->handlers[(int) wider_mode].insn_code
02230 != CODE_FOR_nothing)
02231 {
02232 rtx t0 = gen_reg_rtx (wider_mode);
02233 rtx t1 = gen_reg_rtx (wider_mode);
02234 rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
02235 rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
02236
02237 if (expand_twoval_binop (binoptab, cop0, cop1,
02238 t0, t1, unsignedp))
02239 {
02240 convert_move (targ0, t0, unsignedp);
02241 convert_move (targ1, t1, unsignedp);
02242 return 1;
02243 }
02244 else
02245 delete_insns_since (last);
02246 }
02247 }
02248 }
02249
02250 delete_insns_since (entry_last);
02251 return 0;
02252 }
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263 bool
02264 expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
02265 rtx targ0, rtx targ1, enum rtx_code code)
02266 {
02267 enum machine_mode mode;
02268 enum machine_mode libval_mode;
02269 rtx libval;
02270 rtx insns;
02271
02272
02273 gcc_assert (!targ0 != !targ1);
02274
02275 mode = GET_MODE (op0);
02276 if (!binoptab->handlers[(int) mode].libfunc)
02277 return false;
02278
02279
02280
02281 libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode),
02282 MODE_INT);
02283 start_sequence ();
02284 libval = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
02285 NULL_RTX, LCT_CONST,
02286 libval_mode, 2,
02287 op0, mode,
02288 op1, mode);
02289
02290 libval = simplify_gen_subreg (mode, libval, libval_mode,
02291 targ0 ? 0 : GET_MODE_SIZE (mode));
02292 insns = get_insns ();
02293 end_sequence ();
02294
02295 emit_libcall_block (insns, targ0 ? targ0 : targ1, libval,
02296 gen_rtx_fmt_ee (code, mode, op0, op1));
02297
02298 return true;
02299 }
02300
02301
02302
02303
02304
02305 rtx
02306 expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
02307 rtx target, int unsignedp)
02308 {
02309 optab unop = code_to_optab[(int) code];
02310 gcc_assert (unop);
02311
02312 return expand_unop (mode, unop, op0, target, unsignedp);
02313 }
02314
02315
02316
02317
02318
02319 static rtx
02320 widen_clz (enum machine_mode mode, rtx op0, rtx target)
02321 {
02322 enum mode_class class = GET_MODE_CLASS (mode);
02323 if (CLASS_HAS_WIDER_MODES_P (class))
02324 {
02325 enum machine_mode wider_mode;
02326 for (wider_mode = GET_MODE_WIDER_MODE (mode);
02327 wider_mode != VOIDmode;
02328 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
02329 {
02330 if (clz_optab->handlers[(int) wider_mode].insn_code
02331 != CODE_FOR_nothing)
02332 {
02333 rtx xop0, temp, last;
02334
02335 last = get_last_insn ();
02336
02337 if (target == 0)
02338 target = gen_reg_rtx (mode);
02339 xop0 = widen_operand (op0, wider_mode, mode, true, false);
02340 temp = expand_unop (wider_mode, clz_optab, xop0, NULL_RTX, true);
02341 if (temp != 0)
02342 temp = expand_binop (wider_mode, sub_optab, temp,
02343 GEN_INT (GET_MODE_BITSIZE (wider_mode)
02344 - GET_MODE_BITSIZE (mode)),
02345 target, true, OPTAB_DIRECT);
02346 if (temp == 0)
02347 delete_insns_since (last);
02348
02349 return temp;
02350 }
02351 }
02352 }
02353 return 0;
02354 }
02355
02356
02357
02358 static rtx
02359 expand_parity (enum machine_mode mode, rtx op0, rtx target)
02360 {
02361 enum mode_class class = GET_MODE_CLASS (mode);
02362 if (CLASS_HAS_WIDER_MODES_P (class))
02363 {
02364 enum machine_mode wider_mode;
02365 for (wider_mode = mode; wider_mode != VOIDmode;
02366 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
02367 {
02368 if (popcount_optab->handlers[(int) wider_mode].insn_code
02369 != CODE_FOR_nothing)
02370 {
02371 rtx xop0, temp, last;
02372
02373 last = get_last_insn ();
02374
02375 if (target == 0)
02376 target = gen_reg_rtx (mode);
02377 xop0 = widen_operand (op0, wider_mode, mode, true, false);
02378 temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
02379 true);
02380 if (temp != 0)
02381 temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
02382 target, true, OPTAB_DIRECT);
02383 if (temp == 0)
02384 delete_insns_since (last);
02385
02386 return temp;
02387 }
02388 }
02389 }
02390 return 0;
02391 }
02392
02393
02394
02395
02396
02397
02398 static rtx
02399 lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val,
02400 enum machine_mode imode)
02401 {
02402 rtx ret;
02403 ret = lowpart_subreg (omode, val, imode);
02404 if (ret == NULL)
02405 {
02406 val = force_reg (imode, val);
02407 ret = lowpart_subreg (omode, val, imode);
02408 gcc_assert (ret != NULL);
02409 }
02410 return ret;
02411 }
02412
02413
02414
02415
02416 static rtx
02417 expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
02418 rtx op0, rtx target)
02419 {
02420 const struct real_format *fmt;
02421 int bitpos, word, nwords, i;
02422 enum machine_mode imode;
02423 HOST_WIDE_INT hi, lo;
02424 rtx temp, insns;
02425
02426
02427 fmt = REAL_MODE_FORMAT (mode);
02428 if (fmt == NULL)
02429 return NULL_RTX;
02430
02431 bitpos = fmt->signbit_rw;
02432 if (bitpos < 0)
02433 return NULL_RTX;
02434
02435
02436 if (code == NEG && !fmt->has_signed_zero)
02437 return NULL_RTX;
02438
02439 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
02440 {
02441 imode = int_mode_for_mode (mode);
02442 if (imode == BLKmode)
02443 return NULL_RTX;
02444 word = 0;
02445 nwords = 1;
02446 }
02447 else
02448 {
02449 imode = word_mode;
02450
02451 if (FLOAT_WORDS_BIG_ENDIAN)
02452 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
02453 else
02454 word = bitpos / BITS_PER_WORD;
02455 bitpos = bitpos % BITS_PER_WORD;
02456 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
02457 }
02458
02459 if (bitpos < HOST_BITS_PER_WIDE_INT)
02460 {
02461 hi = 0;
02462 lo = (HOST_WIDE_INT) 1 << bitpos;
02463 }
02464 else
02465 {
02466 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
02467 lo = 0;
02468 }
02469 if (code == ABS)
02470 lo = ~lo, hi = ~hi;
02471
02472 if (target == 0 || target == op0)
02473 target = gen_reg_rtx (mode);
02474
02475 if (nwords > 1)
02476 {
02477 start_sequence ();
02478
02479 for (i = 0; i < nwords; ++i)
02480 {
02481 rtx targ_piece = operand_subword (target, i, 1, mode);
02482 rtx op0_piece = operand_subword_force (op0, i, mode);
02483
02484 if (i == word)
02485 {
02486 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
02487 op0_piece,
02488 immed_double_const (lo, hi, imode),
02489 targ_piece, 1, OPTAB_LIB_WIDEN);
02490 if (temp != targ_piece)
02491 emit_move_insn (targ_piece, temp);
02492 }
02493 else
02494 emit_move_insn (targ_piece, op0_piece);
02495 }
02496
02497 insns = get_insns ();
02498 end_sequence ();
02499
02500 temp = gen_rtx_fmt_e (code, mode, copy_rtx (op0));
02501 emit_no_conflict_block (insns, target, op0, NULL_RTX, temp);
02502 }
02503 else
02504 {
02505 temp = expand_binop (imode, code == ABS ? and_optab : xor_optab,
02506 gen_lowpart (imode, op0),
02507 immed_double_const (lo, hi, imode),
02508 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
02509 target = lowpart_subreg_maybe_copy (mode, temp, imode);
02510
02511 set_unique_reg_note (get_last_insn (), REG_EQUAL,
02512 gen_rtx_fmt_e (code, mode, copy_rtx (op0)));
02513 }
02514
02515 return target;
02516 }
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529 rtx
02530 expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
02531 int unsignedp)
02532 {
02533 enum mode_class class;
02534 enum machine_mode wider_mode;
02535 rtx temp;
02536 rtx last = get_last_insn ();
02537 rtx pat;
02538
02539 class = GET_MODE_CLASS (mode);
02540
02541 if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
02542 {
02543 int icode = (int) unoptab->handlers[(int) mode].insn_code;
02544 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
02545 rtx xop0 = op0;
02546
02547 if (target)
02548 temp = target;
02549 else
02550 temp = gen_reg_rtx (mode);
02551
02552 if (GET_MODE (xop0) != VOIDmode
02553 && GET_MODE (xop0) != mode0)
02554 xop0 = convert_to_mode (mode0, xop0, unsignedp);
02555
02556
02557
02558 if (!insn_data[icode].operand[1].predicate (xop0, mode0))
02559 xop0 = copy_to_mode_reg (mode0, xop0);
02560
02561 if (!insn_data[icode].operand[0].predicate (temp, mode))
02562 temp = gen_reg_rtx (mode);
02563
02564 pat = GEN_FCN (icode) (temp, xop0);
02565 if (pat)
02566 {
02567 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
02568 && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
02569 {
02570 delete_insns_since (last);
02571 return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
02572 }
02573
02574 emit_insn (pat);
02575
02576 return temp;
02577 }
02578 else
02579 delete_insns_since (last);
02580 }
02581
02582
02583
02584
02585 if (unoptab == clz_optab)
02586 {
02587 temp = widen_clz (mode, op0, target);
02588 if (temp)
02589 return temp;
02590 else
02591 goto try_libcall;
02592 }
02593
02594 if (CLASS_HAS_WIDER_MODES_P (class))
02595 for (wider_mode = GET_MODE_WIDER_MODE (mode);
02596 wider_mode != VOIDmode;
02597 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
02598 {
02599 if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
02600 {
02601 rtx xop0 = op0;
02602
02603
02604
02605
02606
02607 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
02608 (unoptab == neg_optab
02609 || unoptab == one_cmpl_optab)
02610 && class == MODE_INT);
02611
02612 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
02613 unsignedp);
02614
02615 if (temp)
02616 {
02617 if (class != MODE_INT
02618 || !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
02619 GET_MODE_BITSIZE (wider_mode)))
02620 {
02621 if (target == 0)
02622 target = gen_reg_rtx (mode);
02623 convert_move (target, temp, 0);
02624 return target;
02625 }
02626 else
02627 return gen_lowpart (mode, temp);
02628 }
02629 else
02630 delete_insns_since (last);
02631 }
02632 }
02633
02634
02635 if (unoptab == one_cmpl_optab
02636 && class == MODE_INT
02637 && GET_MODE_SIZE (mode) > UNITS_PER_WORD
02638 && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
02639 {
02640 int i;
02641 rtx insns;
02642
02643 if (target == 0 || target == op0)
02644 target = gen_reg_rtx (mode);
02645
02646 start_sequence ();
02647
02648
02649 for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
02650 {
02651 rtx target_piece = operand_subword (target, i, 1, mode);
02652 rtx x = expand_unop (word_mode, unoptab,
02653 operand_subword_force (op0, i, mode),
02654 target_piece, unsignedp);
02655
02656 if (target_piece != x)
02657 emit_move_insn (target_piece, x);
02658 }
02659
02660 insns = get_insns ();
02661 end_sequence ();
02662
02663 emit_no_conflict_block (insns, target, op0, NULL_RTX,
02664 gen_rtx_fmt_e (unoptab->code, mode,
02665 copy_rtx (op0)));
02666 return target;
02667 }
02668
02669 if (unoptab->code == NEG)
02670 {
02671
02672 if (SCALAR_FLOAT_MODE_P (mode))
02673 {
02674 temp = expand_absneg_bit (NEG, mode, op0, target);
02675 if (temp)
02676 return temp;
02677 }
02678
02679
02680
02681 if (!HONOR_SIGNED_ZEROS (mode))
02682 {
02683 temp = expand_binop (mode, (unoptab == negv_optab
02684 ? subv_optab : sub_optab),
02685 CONST0_RTX (mode), op0, target,
02686 unsignedp, OPTAB_DIRECT);
02687 if (temp)
02688 return temp;
02689 }
02690 }
02691
02692
02693 if (unoptab == parity_optab)
02694 {
02695 temp = expand_parity (mode, op0, target);
02696 if (temp)
02697 return temp;
02698 }
02699
02700 try_libcall:
02701
02702 if (unoptab->handlers[(int) mode].libfunc)
02703 {
02704 rtx insns;
02705 rtx value;
02706 enum machine_mode outmode = mode;
02707
02708
02709
02710 if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
02711 || unoptab == popcount_optab || unoptab == parity_optab)
02712 outmode
02713 = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node)));
02714
02715 start_sequence ();
02716
02717
02718
02719 value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
02720 NULL_RTX, LCT_CONST, outmode,
02721 1, op0, mode);
02722 insns = get_insns ();
02723 end_sequence ();
02724
02725 target = gen_reg_rtx (outmode);
02726 emit_libcall_block (insns, target, value,
02727 gen_rtx_fmt_e (unoptab->code, outmode, op0));
02728
02729 return target;
02730 }
02731
02732
02733
02734 if (CLASS_HAS_WIDER_MODES_P (class))
02735 {
02736 for (wider_mode = GET_MODE_WIDER_MODE (mode);
02737 wider_mode != VOIDmode;
02738 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
02739 {
02740 if ((unoptab->handlers[(int) wider_mode].insn_code
02741 != CODE_FOR_nothing)
02742 || unoptab->handlers[(int) wider_mode].libfunc)
02743 {
02744 rtx xop0 = op0;
02745
02746
02747
02748
02749
02750 xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
02751 (unoptab == neg_optab
02752 || unoptab == one_cmpl_optab)
02753 && class == MODE_INT);
02754
02755 temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
02756 unsignedp);
02757
02758
02759
02760 if (unoptab == clz_optab && temp != 0)
02761 temp = expand_binop (wider_mode, sub_optab, temp,
02762 GEN_INT (GET_MODE_BITSIZE (wider_mode)
02763 - GET_MODE_BITSIZE (mode)),
02764 target, true, OPTAB_DIRECT);
02765
02766 if (temp)
02767 {
02768 if (class != MODE_INT)
02769 {
02770 if (target == 0)
02771 target = gen_reg_rtx (mode);
02772 convert_move (target, temp, 0);
02773 return target;
02774 }
02775 else
02776 return gen_lowpart (mode, temp);
02777 }
02778 else
02779 delete_insns_since (last);
02780 }
02781 }
02782 }
02783
02784
02785
02786 if (unoptab->code == NEG && !HONOR_SIGNED_ZEROS (mode))
02787 {
02788 rtx temp;
02789 temp = expand_binop (mode,
02790 unoptab == negv_optab ? subv_optab : sub_optab,
02791 CONST0_RTX (mode), op0,
02792 target, unsignedp, OPTAB_LIB_WIDEN);
02793 if (temp)
02794 return temp;
02795 }
02796
02797 return 0;
02798 }
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809 rtx
02810 expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
02811 int result_unsignedp)
02812 {
02813 rtx temp;
02814
02815 if (! flag_trapv)
02816 result_unsignedp = 1;
02817
02818
02819 temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
02820 op0, target, 0);
02821 if (temp != 0)
02822 return temp;
02823
02824
02825 if (SCALAR_FLOAT_MODE_P (mode))
02826 {
02827 temp = expand_absneg_bit (ABS, mode, op0, target);
02828 if (temp)
02829 return temp;
02830 }
02831
02832
02833 if (smax_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
02834 && !HONOR_SIGNED_ZEROS (mode))
02835 {
02836 rtx last = get_last_insn ();
02837
02838 temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
02839 if (temp != 0)
02840 temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
02841 OPTAB_WIDEN);
02842
02843 if (temp != 0)
02844 return temp;
02845
02846 delete_insns_since (last);
02847 }
02848
02849
02850
02851
02852
02853 if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
02854 {
02855 rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
02856 size_int (GET_MODE_BITSIZE (mode) - 1),
02857 NULL_RTX, 0);
02858
02859 temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
02860 OPTAB_LIB_WIDEN);
02861 if (temp != 0)
02862 temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
02863 temp, extended, target, 0, OPTAB_LIB_WIDEN);
02864
02865 if (temp != 0)
02866 return temp;
02867 }
02868
02869 return NULL_RTX;
02870 }
02871
02872 rtx
02873 expand_abs (enum machine_mode mode, rtx op0, rtx target,
02874 int result_unsignedp, int safe)
02875 {
02876 rtx temp, op1;
02877
02878 if (! flag_trapv)
02879 result_unsignedp = 1;
02880
02881 temp = expand_abs_nojump (mode, op0, target, result_unsignedp);
02882 if (temp != 0)
02883 return temp;
02884
02885
02886
02887
02888
02889 if (op0 == target && REG_P (op0)
02890 && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
02891 safe = 1;
02892
02893 op1 = gen_label_rtx ();
02894 if (target == 0 || ! safe
02895 || GET_MODE (target) != mode
02896 || (MEM_P (target) && MEM_VOLATILE_P (target))
02897 || (REG_P (target)
02898 && REGNO (target) < FIRST_PSEUDO_REGISTER))
02899 target = gen_reg_rtx (mode);
02900
02901 emit_move_insn (target, op0);
02902 NO_DEFER_POP;
02903
02904 do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
02905 NULL_RTX, NULL_RTX, op1);
02906
02907 op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
02908 target, target, 0);
02909 if (op0 != target)
02910 emit_move_insn (target, op0);
02911 emit_label (op1);
02912 OK_DEFER_POP;
02913 return target;
02914 }
02915
02916
02917
02918
02919
02920
02921 static rtx
02922 expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
02923 int bitpos, bool op0_is_abs)
02924 {
02925 enum machine_mode imode;
02926 HOST_WIDE_INT hi, lo;
02927 int word;
02928 rtx label;
02929
02930 if (target == op1)
02931 target = NULL_RTX;
02932
02933 if (!op0_is_abs)
02934 {
02935 op0 = expand_unop (mode, abs_optab, op0, target, 0);
02936 if (op0 == NULL)
02937 return NULL_RTX;
02938 target = op0;
02939 }
02940 else
02941 {
02942 if (target == NULL_RTX)
02943 target = copy_to_reg (op0);
02944 else
02945 emit_move_insn (target, op0);
02946 }
02947
02948 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
02949 {
02950 imode = int_mode_for_mode (mode);
02951 if (imode == BLKmode)
02952 return NULL_RTX;
02953 op1 = gen_lowpart (imode, op1);
02954 }
02955 else
02956 {
02957 imode = word_mode;
02958 if (FLOAT_WORDS_BIG_ENDIAN)
02959 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
02960 else
02961 word = bitpos / BITS_PER_WORD;
02962 bitpos = bitpos % BITS_PER_WORD;
02963 op1 = operand_subword_force (op1, word, mode);
02964 }
02965
02966 if (bitpos < HOST_BITS_PER_WIDE_INT)
02967 {
02968 hi = 0;
02969 lo = (HOST_WIDE_INT) 1 << bitpos;
02970 }
02971 else
02972 {
02973 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
02974 lo = 0;
02975 }
02976
02977 op1 = expand_binop (imode, and_optab, op1,
02978 immed_double_const (lo, hi, imode),
02979 NULL_RTX, 1, OPTAB_LIB_WIDEN);
02980
02981 label = gen_label_rtx ();
02982 emit_cmp_and_jump_insns (op1, const0_rtx, EQ, NULL_RTX, imode, 1, label);
02983
02984 if (GET_CODE (op0) == CONST_DOUBLE)
02985 op0 = simplify_unary_operation (NEG, mode, op0, mode);
02986 else
02987 op0 = expand_unop (mode, neg_optab, op0, target, 0);
02988 if (op0 != target)
02989 emit_move_insn (target, op0);
02990
02991 emit_label (label);
02992
02993 return target;
02994 }
02995
02996
02997
02998
02999
03000
03001 static rtx
03002 expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
03003 int bitpos, bool op0_is_abs)
03004 {
03005 enum machine_mode imode;
03006 HOST_WIDE_INT hi, lo;
03007 int word, nwords, i;
03008 rtx temp, insns;
03009
03010 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
03011 {
03012 imode = int_mode_for_mode (mode);
03013 if (imode == BLKmode)
03014 return NULL_RTX;
03015 word = 0;
03016 nwords = 1;
03017 }
03018 else
03019 {
03020 imode = word_mode;
03021
03022 if (FLOAT_WORDS_BIG_ENDIAN)
03023 word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
03024 else
03025 word = bitpos / BITS_PER_WORD;
03026 bitpos = bitpos % BITS_PER_WORD;
03027 nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD;
03028 }
03029
03030 if (bitpos < HOST_BITS_PER_WIDE_INT)
03031 {
03032 hi = 0;
03033 lo = (HOST_WIDE_INT) 1 << bitpos;
03034 }
03035 else
03036 {
03037 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
03038 lo = 0;
03039 }
03040
03041 if (target == 0 || target == op0 || target == op1)
03042 target = gen_reg_rtx (mode);
03043
03044 if (nwords > 1)
03045 {
03046 start_sequence ();
03047
03048 for (i = 0; i < nwords; ++i)
03049 {
03050 rtx targ_piece = operand_subword (target, i, 1, mode);
03051 rtx op0_piece = operand_subword_force (op0, i, mode);
03052
03053 if (i == word)
03054 {
03055 if (!op0_is_abs)
03056 op0_piece = expand_binop (imode, and_optab, op0_piece,
03057 immed_double_const (~lo, ~hi, imode),
03058 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03059
03060 op1 = expand_binop (imode, and_optab,
03061 operand_subword_force (op1, i, mode),
03062 immed_double_const (lo, hi, imode),
03063 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03064
03065 temp = expand_binop (imode, ior_optab, op0_piece, op1,
03066 targ_piece, 1, OPTAB_LIB_WIDEN);
03067 if (temp != targ_piece)
03068 emit_move_insn (targ_piece, temp);
03069 }
03070 else
03071 emit_move_insn (targ_piece, op0_piece);
03072 }
03073
03074 insns = get_insns ();
03075 end_sequence ();
03076
03077 emit_no_conflict_block (insns, target, op0, op1, NULL_RTX);
03078 }
03079 else
03080 {
03081 op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1),
03082 immed_double_const (lo, hi, imode),
03083 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03084
03085 op0 = gen_lowpart (imode, op0);
03086 if (!op0_is_abs)
03087 op0 = expand_binop (imode, and_optab, op0,
03088 immed_double_const (~lo, ~hi, imode),
03089 NULL_RTX, 1, OPTAB_LIB_WIDEN);
03090
03091 temp = expand_binop (imode, ior_optab, op0, op1,
03092 gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN);
03093 target = lowpart_subreg_maybe_copy (mode, temp, imode);
03094 }
03095
03096 return target;
03097 }
03098
03099
03100
03101
03102
03103 rtx
03104 expand_copysign (rtx op0, rtx op1, rtx target)
03105 {
03106 enum machine_mode mode = GET_MODE (op0);
03107 const struct real_format *fmt;
03108 bool op0_is_abs;
03109 rtx temp;
03110
03111 gcc_assert (SCALAR_FLOAT_MODE_P (mode));
03112 gcc_assert (GET_MODE (op1) == mode);
03113
03114
03115 temp = expand_binop (mode, copysign_optab, op0, op1,
03116 target, 0, OPTAB_DIRECT);
03117 if (temp)
03118 return temp;
03119
03120 fmt = REAL_MODE_FORMAT (mode);
03121 if (fmt == NULL || !fmt->has_signed_zero)
03122 return NULL_RTX;
03123
03124 op0_is_abs = false;
03125 if (GET_CODE (op0) == CONST_DOUBLE)
03126 {
03127 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
03128 op0 = simplify_unary_operation (ABS, mode, op0, mode);
03129 op0_is_abs = true;
03130 }
03131
03132 if (fmt->signbit_ro >= 0
03133 && (GET_CODE (op0) == CONST_DOUBLE
03134 || (neg_optab->handlers[mode].insn_code != CODE_FOR_nothing
03135 && abs_optab->handlers[mode].insn_code != CODE_FOR_nothing)))
03136 {
03137 temp = expand_copysign_absneg (mode, op0, op1, target,
03138 fmt->signbit_ro, op0_is_abs);
03139 if (temp)
03140 return temp;
03141 }
03142
03143 if (fmt->signbit_rw < 0)
03144 return NULL_RTX;
03145 return expand_copysign_bit (mode, op0, op1, target,
03146 fmt->signbit_rw, op0_is_abs);
03147 }
03148
03149
03150
03151
03152
03153
03154
03155 void
03156 emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
03157 {
03158 rtx temp;
03159 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
03160 rtx pat;
03161
03162 temp = target;
03163
03164
03165
03166 if (!insn_data[icode].operand[1].predicate (op0, mode0))
03167 op0 = copy_to_mode_reg (mode0, op0);
03168
03169 if (!insn_data[icode].operand[0].predicate (temp, GET_MODE (temp)))
03170 temp = gen_reg_rtx (GET_MODE (temp));
03171
03172 pat = GEN_FCN (icode) (temp, op0);
03173
03174 if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
03175 add_equal_note (pat, temp, code, op0, NULL_RTX);
03176
03177 emit_insn (pat);
03178
03179 if (temp != target)
03180 emit_move_insn (target, temp);
03181 }
03182
03183 struct no_conflict_data
03184 {
03185 rtx target, first, insn;
03186 bool must_stay;
03187 };
03188
03189
03190
03191
03192
03193 static void
03194 no_conflict_move_test (rtx dest, rtx set, void *p0)
03195 {
03196 struct no_conflict_data *p= p0;
03197
03198
03199 if (reg_overlap_mentioned_p (p->target, dest))
03200 p->must_stay = true;
03201
03202
03203 else if (p->insn == p->first)
03204 return;
03205
03206
03207 else if (reg_overlap_mentioned_p (dest, PATTERN (p->first))
03208 || (CALL_P (p->first) && (find_reg_fusage (p->first, USE, dest)))
03209 || reg_used_between_p (dest, p->first, p->insn)
03210
03211
03212
03213
03214
03215
03216 || (GET_CODE (set) == SET
03217 && (modified_in_p (SET_SRC (set), p->first)
03218 || modified_in_p (SET_DEST (set), p->first)
03219 || modified_between_p (SET_SRC (set), p->first, p->insn)
03220 || modified_between_p (SET_DEST (set), p->first, p->insn))))
03221 p->must_stay = true;
03222 }
03223
03224
03225
03226
03227
03228 static void
03229 maybe_encapsulate_block (rtx first, rtx last, rtx equiv)
03230 {
03231 if (!flag_non_call_exceptions || !may_trap_p (equiv))
03232 {
03233
03234
03235
03236 bool attach_libcall_retval_notes = true;
03237 rtx insn, next = NEXT_INSN (last);
03238
03239 for (insn = first; insn != next; insn = NEXT_INSN (insn))
03240 if (control_flow_insn_p (insn))
03241 {
03242 attach_libcall_retval_notes = false;
03243 break;
03244 }
03245
03246 if (attach_libcall_retval_notes)
03247 {
03248 REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
03249 REG_NOTES (first));
03250 REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
03251 REG_NOTES (last));
03252 }
03253 }
03254 }
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284 rtx
03285 emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv)
03286 {
03287 rtx prev, next, first, last, insn;
03288
03289 if (!REG_P (target) || reload_in_progress)
03290 return emit_insn (insns);
03291 else
03292 for (insn = insns; insn; insn = NEXT_INSN (insn))
03293 if (!NONJUMP_INSN_P (insn)
03294 || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
03295 return emit_insn (insns);
03296
03297
03298
03299 for (insn = insns; insn; insn = next)
03300 {
03301 rtx note;
03302 struct no_conflict_data data;
03303
03304 next = NEXT_INSN (insn);
03305
03306
03307
03308 if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
03309 remove_note (insn, note);
03310 if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
03311 remove_note (insn, note);
03312
03313 data.target = target;
03314 data.first = insns;
03315 data.insn = insn;
03316 data.must_stay = 0;
03317 note_stores (PATTERN (insn), no_conflict_move_test, &data);
03318 if (! data.must_stay)
03319 {
03320 if (PREV_INSN (insn))
03321 NEXT_INSN (PREV_INSN (insn)) = next;
03322 else
03323 insns = next;
03324
03325 if (next)
03326 PREV_INSN (next) = PREV_INSN (insn);
03327
03328 add_insn (insn);
03329 }
03330 }
03331
03332 prev = get_last_insn ();
03333
03334
03335
03336 if (target != op0 && target != op1)
03337 emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
03338
03339 for (insn = insns; insn; insn = next)
03340 {
03341 next = NEXT_INSN (insn);
03342 add_insn (insn);
03343
03344 if (op1 && REG_P (op1))
03345 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
03346 REG_NOTES (insn));
03347
03348 if (op0 && REG_P (op0))
03349 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
03350 REG_NOTES (insn));
03351 }
03352
03353 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
03354 != CODE_FOR_nothing)
03355 {
03356 last = emit_move_insn (target, target);
03357 if (equiv)
03358 set_unique_reg_note (last, REG_EQUAL, equiv);
03359 }
03360 else
03361 {
03362 last = get_last_insn ();
03363
03364
03365
03366
03367
03368
03369 remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
03370 }
03371
03372 if (prev == 0)
03373 first = get_insns ();
03374 else
03375 first = NEXT_INSN (prev);
03376
03377 maybe_encapsulate_block (first, last, equiv);
03378
03379 return last;
03380 }
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407 void
03408 emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
03409 {
03410 rtx final_dest = target;
03411 rtx prev, next, first, last, insn;
03412
03413
03414
03415 if (! REG_P (target) || REG_USERVAR_P (target))
03416 target = gen_reg_rtx (GET_MODE (target));
03417
03418
03419
03420 if (flag_non_call_exceptions && may_trap_p (equiv))
03421 {
03422 for (insn = insns; insn; insn = NEXT_INSN (insn))
03423 if (CALL_P (insn))
03424 {
03425 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
03426
03427 if (note != 0 && INTVAL (XEXP (note, 0)) <= 0)
03428 remove_note (insn, note);
03429 }
03430 }
03431 else
03432
03433
03434
03435
03436 for (insn = insns; insn; insn = NEXT_INSN (insn))
03437 if (CALL_P (insn))
03438 {
03439 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
03440
03441 if (note != 0)
03442 XEXP (note, 0) = constm1_rtx;
03443 else
03444 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx,
03445 REG_NOTES (insn));
03446 }
03447
03448
03449
03450
03451
03452
03453
03454 for (insn = insns; insn; insn = next)
03455 {
03456 rtx set = single_set (insn);
03457 rtx note;
03458
03459
03460
03461 if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
03462 remove_note (insn, note);
03463 if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
03464 remove_note (insn, note);
03465
03466 next = NEXT_INSN (insn);
03467
03468 if (set != 0 && REG_P (SET_DEST (set))
03469 && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
03470 {
03471 struct no_conflict_data data;
03472
03473 data.target = const0_rtx;
03474 data.first = insns;
03475 data.insn = insn;
03476 data.must_stay = 0;
03477 note_stores (PATTERN (insn), no_conflict_move_test, &data);
03478 if (! data.must_stay)
03479 {
03480 if (PREV_INSN (insn))
03481 NEXT_INSN (PREV_INSN (insn)) = next;
03482 else
03483 insns = next;
03484
03485 if (next)
03486 PREV_INSN (next) = PREV_INSN (insn);
03487
03488 add_insn (insn);
03489 }
03490 }
03491
03492
03493
03494 if (LABEL_P (insn))
03495 break;
03496 }
03497
03498 prev = get_last_insn ();
03499
03500
03501
03502 for (insn = insns; insn; insn = next)
03503 {
03504 next = NEXT_INSN (insn);
03505
03506 add_insn (insn);
03507 }
03508
03509 last = emit_move_insn (target, result);
03510 if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
03511 != CODE_FOR_nothing)
03512 set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
03513 else
03514 {
03515
03516
03517
03518
03519
03520 remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
03521 }
03522
03523 if (final_dest != target)
03524 emit_move_insn (final_dest, target);
03525
03526 if (prev == 0)
03527 first = get_insns ();
03528 else
03529 first = NEXT_INSN (prev);
03530
03531 maybe_encapsulate_block (first, last, equiv);
03532 }
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542 int
03543 can_compare_p (enum rtx_code code, enum machine_mode mode,
03544 enum can_compare_purpose purpose)
03545 {
03546 do
03547 {
03548 if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
03549 {
03550 if (purpose == ccp_jump)
03551 return bcc_gen_fctn[(int) code] != NULL;
03552 else if (purpose == ccp_store_flag)
03553 return setcc_gen_code[(int) code] != CODE_FOR_nothing;
03554 else
03555
03556 return 1;
03557 }
03558 if (purpose == ccp_jump
03559 && cbranch_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
03560 return 1;
03561 if (purpose == ccp_cmov
03562 && cmov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
03563 return 1;
03564 if (purpose == ccp_store_flag
03565 && cstore_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
03566 return 1;
03567 mode = GET_MODE_WIDER_MODE (mode);
03568 }
03569 while (mode != VOIDmode);
03570
03571 return 0;
03572 }
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591 static void
03592 prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
03593 enum machine_mode *pmode, int *punsignedp,
03594 enum can_compare_purpose purpose)
03595 {
03596 enum machine_mode mode = *pmode;
03597 rtx x = *px, y = *py;
03598 int unsignedp = *punsignedp;
03599
03600
03601
03602 if (CONSTANT_P (x) && optimize
03603 && rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
03604 x = force_reg (mode, x);
03605
03606 if (CONSTANT_P (y) && optimize
03607 && rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
03608 y = force_reg (mode, y);
03609
03610 #ifdef HAVE_cc0
03611
03612
03613
03614 gcc_assert (!CONSTANT_P (x) || CONSTANT_P (y));
03615 #endif
03616
03617
03618 if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
03619 x = force_reg (mode, x);
03620
03621
03622
03623 if (mode == BLKmode)
03624 {
03625 enum machine_mode cmp_mode, result_mode;
03626 enum insn_code cmp_code;
03627 tree length_type;
03628 rtx libfunc;
03629 rtx result;
03630 rtx opalign
03631 = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
03632
03633 gcc_assert (size);
03634
03635
03636
03637 for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
03638 cmp_mode != VOIDmode;
03639 cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
03640 {
03641 cmp_code = cmpmem_optab[cmp_mode];
03642 if (cmp_code == CODE_FOR_nothing)
03643 cmp_code = cmpstr_optab[cmp_mode];
03644 if (cmp_code == CODE_FOR_nothing)
03645 cmp_code = cmpstrn_optab[cmp_mode];
03646 if (cmp_code == CODE_FOR_nothing)
03647 continue;
03648
03649
03650 if ((GET_CODE (size) == CONST_INT
03651 && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
03652 || (GET_MODE_BITSIZE (GET_MODE (size))
03653 > GET_MODE_BITSIZE (cmp_mode)))
03654 continue;
03655
03656 result_mode = insn_data[cmp_code].operand[0].mode;
03657 result = gen_reg_rtx (result_mode);
03658 size = convert_to_mode (cmp_mode, size, 1);
03659 emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));
03660
03661 *px = result;
03662 *py = const0_rtx;
03663 *pmode = result_mode;
03664 return;
03665 }
03666
03667
03668 libfunc = memcmp_libfunc;
03669 length_type = sizetype;
03670 result_mode = TYPE_MODE (integer_type_node);
03671 cmp_mode = TYPE_MODE (length_type);
03672 size = convert_to_mode (TYPE_MODE (length_type), size,
03673 TYPE_UNSIGNED (length_type));
03674
03675 result = emit_library_call_value (libfunc, 0, LCT_PURE_MAKE_BLOCK,
03676 result_mode, 3,
03677 XEXP (x, 0), Pmode,
03678 XEXP (y, 0), Pmode,
03679 size, cmp_mode);
03680 *px = result;
03681 *py = const0_rtx;
03682 *pmode = result_mode;
03683 return;
03684 }
03685
03686
03687
03688 if (flag_non_call_exceptions)
03689 {
03690 if (may_trap_p (x))
03691 x = force_reg (mode, x);
03692 if (may_trap_p (y))
03693 y = force_reg (mode, y);
03694 }
03695
03696 *px = x;
03697 *py = y;
03698 if (can_compare_p (*pcomparison, mode, purpose))
03699 return;
03700
03701
03702
03703 if (cmp_optab->handlers[(int) mode].libfunc && !SCALAR_FLOAT_MODE_P (mode))
03704 {
03705 rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
03706 rtx result;
03707
03708
03709
03710 if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
03711 libfunc = ucmp_optab->handlers[(int) mode].libfunc;
03712
03713 result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
03714 word_mode, 2, x, mode, y, mode);
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724 *px = result;
03725 *pmode = word_mode;
03726 *py = const1_rtx;
03727
03728 if (!TARGET_LIB_INT_CMP_BIASED)
03729 {
03730 if (*punsignedp)
03731 *px = plus_constant (result, 1);
03732 else
03733 *py = const0_rtx;
03734 }
03735 return;
03736 }
03737
03738 gcc_assert (SCALAR_FLOAT_MODE_P (mode));
03739 prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
03740 }
03741
03742
03743
03744
03745
03746
03747 static rtx
03748 prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode,
03749 enum machine_mode wider_mode, int unsignedp)
03750 {
03751 if (mode != wider_mode)
03752 x = convert_modes (wider_mode, mode, x, unsignedp);
03753
03754 if (!insn_data[icode].operand[opnum].predicate
03755 (x, insn_data[icode].operand[opnum].mode))
03756 {
03757 if (no_new_pseudos)
03758 return NULL_RTX;
03759 x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
03760 }
03761
03762 return x;
03763 }
03764
03765
03766
03767
03768
03769
03770 static void
03771 emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode,
03772 enum rtx_code comparison, int unsignedp, rtx label)
03773 {
03774 rtx test = gen_rtx_fmt_ee (comparison, mode, x, y);
03775 enum mode_class class = GET_MODE_CLASS (mode);
03776 enum machine_mode wider_mode = mode;
03777
03778
03779 do
03780 {
03781 enum insn_code icode;
03782 PUT_MODE (test, wider_mode);
03783
03784 if (label)
03785 {
03786 icode = cbranch_optab->handlers[(int) wider_mode].insn_code;
03787
03788 if (icode != CODE_FOR_nothing
03789 && insn_data[icode].operand[0].predicate (test, wider_mode))
03790 {
03791 x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp);
03792 y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp);
03793 emit_jump_insn (GEN_FCN (icode) (test, x, y, label));
03794 return;
03795 }
03796 }
03797
03798
03799 icode = (int) tst_optab->handlers[(int) wider_mode].insn_code;
03800 if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
03801 {
03802 x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
03803 emit_insn (GEN_FCN (icode) (x));
03804 if (label)
03805 emit_jump_insn (bcc_gen_fctn[(int) comparison] (label));
03806 return;
03807 }
03808
03809
03810
03811 icode = (int) cmp_optab->handlers[(int) wider_mode].insn_code;
03812 if (icode != CODE_FOR_nothing)
03813 {
03814 x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
03815 y = prepare_operand (icode, y, 1, mode, wider_mode, unsignedp);
03816 emit_insn (GEN_FCN (icode) (x, y));
03817 if (label)
03818 emit_jump_insn (bcc_gen_fctn[(int) comparison] (label));
03819 return;
03820 }
03821
03822 if (!CLASS_HAS_WIDER_MODES_P (class))
03823 break;
03824
03825 wider_mode = GET_MODE_WIDER_MODE (wider_mode);
03826 }
03827 while (wider_mode != VOIDmode);
03828
03829 gcc_unreachable ();
03830 }
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849 void
03850 emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
03851 enum machine_mode mode, int unsignedp, rtx label)
03852 {
03853 rtx op0 = x, op1 = y;
03854
03855
03856 if (swap_commutative_operands_p (x, y))
03857 {
03858
03859
03860 gcc_assert (label);
03861
03862 op0 = y, op1 = x;
03863 comparison = swap_condition (comparison);
03864 }
03865
03866 #ifdef HAVE_cc0
03867
03868
03869 if (CONSTANT_P (op0))
03870 op0 = force_reg (mode, op0);
03871 #endif
03872
03873 if (unsignedp)
03874 comparison = unsigned_condition (comparison);
03875
03876 prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp,
03877 ccp_jump);
03878 emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
03879 }
03880
03881
03882
03883 void
03884 emit_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
03885 enum machine_mode mode, int unsignedp)
03886 {
03887 emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, 0);
03888 }
03889
03890
03891
03892
03893 static void
03894 prepare_float_lib_cmp (rtx *px, rtx *py, enum rtx_code *pcomparison,
03895 enum machine_mode *pmode, int *punsignedp)
03896 {
03897 enum rtx_code comparison = *pcomparison;
03898 enum rtx_code swapped = swap_condition (comparison);
03899 enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
03900 rtx x = *px;
03901 rtx y = *py;
03902 enum machine_mode orig_mode = GET_MODE (x);
03903 enum machine_mode mode;
03904 rtx value, target, insns, equiv;
03905 rtx libfunc = 0;
03906 bool reversed_p = false;
03907
03908 for (mode = orig_mode;
03909 mode != VOIDmode;
03910 mode = GET_MODE_WIDER_MODE (mode))
03911 {
03912 if ((libfunc = code_to_optab[comparison]->handlers[mode].libfunc))
03913 break;
03914
03915 if ((libfunc = code_to_optab[swapped]->handlers[mode].libfunc))
03916 {
03917 rtx tmp;
03918 tmp = x; x = y; y = tmp;
03919 comparison = swapped;
03920 break;
03921 }
03922
03923 if ((libfunc = code_to_optab[reversed]->handlers[mode].libfunc)
03924 && FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, reversed))
03925 {
03926 comparison = reversed;
03927 reversed_p = true;
03928 break;
03929 }
03930 }
03931
03932 gcc_assert (mode != VOIDmode);
03933
03934 if (mode != orig_mode)
03935 {
03936 x = convert_to_mode (mode, x, 0);
03937 y = convert_to_mode (mode, y, 0);
03938 }
03939
03940
03941
03942
03943 if (comparison == UNORDERED)
03944 {
03945 rtx temp = simplify_gen_relational (NE, word_mode, mode, x, x);
03946 equiv = simplify_gen_relational (NE, word_mode, mode, y, y);
03947 equiv = simplify_gen_ternary (IF_THEN_ELSE, word_mode, word_mode,
03948 temp, const_true_rtx, equiv);
03949 }
03950 else
03951 {
03952 equiv = simplify_gen_relational (comparison, word_mode, mode, x, y);
03953 if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
03954 {
03955 rtx true_rtx, false_rtx;
03956
03957 switch (comparison)
03958 {
03959 case EQ:
03960 true_rtx = const0_rtx;
03961 false_rtx = const_true_rtx;
03962 break;
03963
03964 case NE:
03965 true_rtx = const_true_rtx;
03966 false_rtx = const0_rtx;
03967 break;
03968
03969 case GT:
03970 true_rtx = const1_rtx;
03971 false_rtx = const0_rtx;
03972 break;
03973
03974 case GE:
03975 true_rtx = const0_rtx;
03976 false_rtx = constm1_rtx;
03977 break;
03978
03979 case LT:
03980 true_rtx = constm1_rtx;
03981 false_rtx = const0_rtx;
03982 break;
03983
03984 case LE:
03985 true_rtx = const0_rtx;
03986 false_rtx = const1_rtx;
03987 break;
03988
03989 default:
03990 gcc_unreachable ();
03991 }
03992 equiv = simplify_gen_ternary (IF_THEN_ELSE, word_mode, word_mode,
03993 equiv, true_rtx, false_rtx);
03994 }
03995 }
03996
03997 start_sequence ();
03998 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
03999 word_mode, 2, x, mode, y, mode);
04000 insns = get_insns ();
04001 end_sequence ();
04002
04003 target = gen_reg_rtx (word_mode);
04004 emit_libcall_block (insns, target, value, equiv);
04005
04006 if (comparison == UNORDERED
04007 || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
04008 comparison = reversed_p ? EQ : NE;
04009
04010 *px = target;
04011 *py = const0_rtx;
04012 *pmode = word_mode;
04013 *pcomparison = comparison;
04014 *punsignedp = 0;
04015 }
04016
04017
04018
04019 void
04020 emit_indirect_jump (rtx loc)
04021 {
04022 if (!insn_data[(int) CODE_FOR_indirect_jump].operand[0].predicate
04023 (loc, Pmode))
04024 loc = copy_to_mode_reg (Pmode, loc);
04025
04026 emit_jump_insn (gen_indirect_jump (loc));
04027 emit_barrier ();
04028 }
04029
04030 #ifdef HAVE_conditional_move
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046 rtx
04047 emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
04048 enum machine_mode cmode, rtx op2, rtx op3,
04049 enum machine_mode mode, int unsignedp)
04050 {
04051 rtx tem, subtarget, comparison, insn;
04052 enum insn_code icode;
04053 enum rtx_code reversed;
04054
04055
04056
04057
04058 if (swap_commutative_operands_p (op0, op1))
04059 {
04060 tem = op0;
04061 op0 = op1;
04062 op1 = tem;
04063 code = swap_condition (code);
04064 }
04065
04066
04067
04068
04069 if (code == LT && op1 == const1_rtx)
04070 code = LE, op1 = const0_rtx;
04071 else if (code == GT && op1 == constm1_rtx)
04072 code = GE, op1 = const0_rtx;
04073
04074 if (cmode == VOIDmode)
04075 cmode = GET_MODE (op0);
04076
04077 if (swap_commutative_operands_p (op2, op3)
04078 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
04079 != UNKNOWN))
04080 {
04081 tem = op2;
04082 op2 = op3;
04083 op3 = tem;
04084 code = reversed;
04085 }
04086
04087 if (mode == VOIDmode)
04088 mode = GET_MODE (op2);
04089
04090 icode = movcc_gen_code[mode];
04091
04092 if (icode == CODE_FOR_nothing)
04093 return 0;
04094
04095 if (!target)
04096 target = gen_reg_rtx (mode);
04097
04098 subtarget = target;
04099
04100
04101
04102 if (!insn_data[icode].operand[0].predicate
04103 (subtarget, insn_data[icode].operand[0].mode))
04104 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
04105
04106 if (!insn_data[icode].operand[2].predicate
04107 (op2, insn_data[icode].operand[2].mode))
04108 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
04109
04110 if (!insn_data[icode].operand[3].predicate
04111 (op3, insn_data[icode].operand[3].mode))
04112 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
04113
04114
04115
04116
04117 comparison
04118 = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX);
04119
04120
04121
04122
04123
04124 if (GET_CODE (comparison) != code)
04125 return NULL_RTX;
04126
04127 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
04128
04129
04130 if (insn == 0)
04131 return 0;
04132
04133 emit_insn (insn);
04134
04135 if (subtarget != target)
04136 convert_move (target, subtarget, 0);
04137
04138 return target;
04139 }
04140
04141
04142
04143
04144
04145
04146
04147
04148
04149 int
04150 can_conditionally_move_p (enum machine_mode mode)
04151 {
04152 if (movcc_gen_code[mode] != CODE_FOR_nothing)
04153 return 1;
04154
04155 return 0;
04156 }
04157
04158 #endif
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169
04170
04171
04172
04173
04174 rtx
04175 emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
04176 enum machine_mode cmode, rtx op2, rtx op3,
04177 enum machine_mode mode, int unsignedp)
04178 {
04179 rtx tem, subtarget, comparison, insn;
04180 enum insn_code icode;
04181 enum rtx_code reversed;
04182
04183
04184
04185
04186 if (swap_commutative_operands_p (op0, op1))
04187 {
04188 tem = op0;
04189 op0 = op1;
04190 op1 = tem;
04191 code = swap_condition (code);
04192 }
04193
04194
04195
04196
04197 if (code == LT && op1 == const1_rtx)
04198 code = LE, op1 = const0_rtx;
04199 else if (code == GT && op1 == constm1_rtx)
04200 code = GE, op1 = const0_rtx;
04201
04202 if (cmode == VOIDmode)
04203 cmode = GET_MODE (op0);
04204
04205 if (swap_commutative_operands_p (op2, op3)
04206 && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
04207 != UNKNOWN))
04208 {
04209 tem = op2;
04210 op2 = op3;
04211 op3 = tem;
04212 code = reversed;
04213 }
04214
04215 if (mode == VOIDmode)
04216 mode = GET_MODE (op2);
04217
04218 icode = addcc_optab->handlers[(int) mode].insn_code;
04219
04220 if (icode == CODE_FOR_nothing)
04221 return 0;
04222
04223 if (!target)
04224 target = gen_reg_rtx (mode);
04225
04226
04227
04228 if (!insn_data[icode].operand[0].predicate
04229 (target, insn_data[icode].operand[0].mode))
04230 subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
04231 else
04232 subtarget = target;
04233
04234 if (!insn_data[icode].operand[2].predicate
04235 (op2, insn_data[icode].operand[2].mode))
04236 op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
04237
04238 if (!insn_data[icode].operand[3].predicate
04239 (op3, insn_data[icode].operand[3].mode))
04240 op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
04241
04242
04243
04244
04245 comparison
04246 = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX);
04247
04248
04249
04250
04251
04252 if (GET_CODE (comparison) != code)
04253 return NULL_RTX;
04254
04255 insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
04256
04257
04258 if (insn == 0)
04259 return 0;
04260
04261 emit_insn (insn);
04262
04263 if (subtarget != target)
04264 convert_move (target, subtarget, 0);
04265
04266 return target;
04267 }
04268
04269
04270
04271
04272
04273
04274
04275 rtx
04276 gen_add2_insn (rtx x, rtx y)
04277 {
04278 int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
04279
04280 gcc_assert (insn_data[icode].operand[0].predicate
04281 (x, insn_data[icode].operand[0].mode));
04282 gcc_assert (insn_data[icode].operand[1].predicate
04283 (x, insn_data[icode].operand[1].mode));
04284 gcc_assert (insn_data[icode].operand[2].predicate
04285 (y, insn_data[icode].operand[2].mode));
04286
04287 return GEN_FCN (icode) (x, x, y);
04288 }
04289
04290
04291
04292 rtx
04293 gen_add3_insn (rtx r0, rtx r1, rtx c)
04294 {
04295 int icode = (int) add_optab->handlers[(int) GET_MODE (r0)].insn_code;
04296
04297 if (icode == CODE_FOR_nothing
04298 || !(insn_data[icode].operand[0].predicate
04299 (r0, insn_data[icode].operand[0].mode))
04300 || !(insn_data[icode].operand[1].predicate
04301 (r1, insn_data[icode].operand[1].mode))
04302 || !(insn_data[icode].operand[2].predicate
04303 (c, insn_data[icode].operand[2].mode)))
04304 return NULL_RTX;
04305
04306 return GEN_FCN (icode) (r0, r1, c);
04307 }
04308
04309 int
04310 have_add2_insn (rtx x, rtx y)
04311 {
04312 int icode;
04313
04314 gcc_assert (GET_MODE (x) != VOIDmode);
04315
04316 icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
04317
04318 if (icode == CODE_FOR_nothing)
04319 return 0;
04320
04321 if (!(insn_data[icode].operand[0].predicate
04322 (x, insn_data[icode].operand[0].mode))
04323 || !(insn_data[icode].operand[1].predicate
04324 (x, insn_data[icode].operand[1].mode))
04325 || !(insn_data[icode].operand[2].predicate
04326 (y, insn_data[icode].operand[2].mode)))
04327 return 0;
04328
04329 return 1;
04330 }
04331
04332
04333
04334 rtx
04335 gen_sub2_insn (rtx x, rtx y)
04336 {
04337 int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
04338
04339 gcc_assert (insn_data[icode].operand[0].predicate
04340 (x, insn_data[icode].operand[0].mode));
04341 gcc_assert (insn_data[icode].operand[1].predicate
04342 (x, insn_data[icode].operand[1].mode));
04343 gcc_assert (insn_data[icode].operand[2].predicate
04344 (y, insn_data[icode].operand[2].mode));
04345
04346 return GEN_FCN (icode) (x, x, y);
04347 }
04348
04349
04350
04351 rtx
04352 gen_sub3_insn (rtx r0, rtx r1, rtx c)
04353 {
04354 int icode = (int) sub_optab->handlers[(int) GET_MODE (r0)].insn_code;
04355
04356 if (icode == CODE_FOR_nothing
04357 || !(insn_data[icode].operand[0].predicate
04358 (r0, insn_data[icode].operand[0].mode))
04359 || !(insn_data[icode].operand[1].predicate
04360 (r1, insn_data[icode].operand[1].mode))
04361 || !(insn_data[icode].operand[2].predicate
04362 (c, insn_data[icode].operand[2].mode)))
04363 return NULL_RTX;
04364
04365 return GEN_FCN (icode) (r0, r1, c);
04366 }
04367
04368 int
04369 have_sub2_insn (rtx x, rtx y)
04370 {
04371 int icode;
04372
04373 gcc_assert (GET_MODE (x) != VOIDmode);
04374
04375 icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
04376
04377 if (icode == CODE_FOR_nothing)
04378 return 0;
04379
04380 if (!(insn_data[icode].operand[0].predicate
04381 (x, insn_data[icode].operand[0].mode))
04382 || !(insn_data[icode].operand[1].predicate
04383 (x, insn_data[icode].operand[1].mode))
04384 || !(insn_data[icode].operand[2].predicate
04385 (y, insn_data[icode].operand[2].mode)))
04386 return 0;
04387
04388 return 1;
04389 }
04390
04391
04392
04393
04394 rtx
04395 gen_move_insn (rtx x, rtx y)
04396 {
04397 rtx seq;
04398
04399 start_sequence ();
04400 emit_move_insn_1 (x, y);
04401 seq = get_insns ();
04402 end_sequence ();
04403 return seq;
04404 }
04405
04406
04407
04408
04409
04410 enum insn_code
04411 can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode,
04412 int unsignedp)
04413 {
04414 convert_optab tab;
04415 #ifdef HAVE_ptr_extend
04416 if (unsignedp < 0)
04417 return CODE_FOR_ptr_extend;
04418 #endif
04419
04420 tab = unsignedp ? zext_optab : sext_optab;
04421 return tab->handlers[to_mode][from_mode].insn_code;
04422 }
04423
04424
04425
04426
04427 rtx
04428 gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
04429 enum machine_mode mfrom, int unsignedp)
04430 {
04431 enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
04432 return GEN_FCN (icode) (x, y);
04433 }
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444 static enum insn_code
04445 can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
04446 int unsignedp, int *truncp_ptr)
04447 {
04448 convert_optab tab;
04449 enum insn_code icode;
04450
04451 tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
04452 icode = tab->handlers[fixmode][fltmode].insn_code;
04453 if (icode != CODE_FOR_nothing)
04454 {
04455 *truncp_ptr = 0;
04456 return icode;
04457 }
04458
04459
04460
04461
04462 tab = unsignedp ? ufix_optab : sfix_optab;
04463 icode = tab->handlers[fixmode][fltmode].insn_code;
04464 if (icode != CODE_FOR_nothing
04465 && ftrunc_optab->handlers[fltmode].insn_code != CODE_FOR_nothing)
04466 {
04467 *truncp_ptr = 1;
04468 return icode;
04469 }
04470
04471 *truncp_ptr = 0;
04472 return CODE_FOR_nothing;
04473 }
04474
04475 static enum insn_code
04476 can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
04477 int unsignedp)
04478 {
04479 convert_optab tab;
04480
04481 tab = unsignedp ? ufloat_optab : sfloat_optab;
04482 return tab->handlers[fltmode][fixmode].insn_code;
04483 }
04484
04485
04486
04487
04488
04489
04490
04491 void
04492 expand_float (rtx to, rtx from, int unsignedp)
04493 {
04494 enum insn_code icode;
04495 rtx target = to;
04496 enum machine_mode fmode, imode;
04497 bool can_do_signed = false;
04498
04499
04500 gcc_assert (GET_MODE (from) != VOIDmode);
04501
04502
04503
04504
04505
04506
04507 for (fmode = GET_MODE (to); fmode != VOIDmode;
04508 fmode = GET_MODE_WIDER_MODE (fmode))
04509 for (imode = GET_MODE (from); imode != VOIDmode;
04510 imode = GET_MODE_WIDER_MODE (imode))
04511 {
04512 int doing_unsigned = unsignedp;
04513
04514 if (fmode != GET_MODE (to)
04515 && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
04516 continue;
04517
04518 icode = can_float_p (fmode, imode, unsignedp);
04519 if (icode == CODE_FOR_nothing && unsignedp)
04520 {
04521 enum insn_code scode = can_float_p (fmode, imode, 0);
04522 if (scode != CODE_FOR_nothing)
04523 can_do_signed = true;
04524 if (imode != GET_MODE (from))
04525 icode = scode, doing_unsigned = 0;
04526 }
04527
04528 if (icode != CODE_FOR_nothing)
04529 {
04530 if (imode != GET_MODE (from))
04531 from = convert_to_mode (imode, from, unsignedp);
04532
04533 if (fmode != GET_MODE (to))
04534 target = gen_reg_rtx (fmode);
04535
04536 emit_unop_insn (icode, target, from,
04537 doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
04538
04539 if (target != to)
04540 convert_move (to, target, 0);
04541 return;
04542 }
04543 }
04544
04545
04546
04547
04548 if (unsignedp && can_do_signed && !DECIMAL_FLOAT_MODE_P (GET_MODE (to)))
04549 {
04550 rtx label = gen_label_rtx ();
04551 rtx temp;
04552 REAL_VALUE_TYPE offset;
04553
04554
04555
04556
04557
04558 for (fmode = GET_MODE (to); fmode != VOIDmode;
04559 fmode = GET_MODE_WIDER_MODE (fmode))
04560 if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
04561 && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
04562 break;
04563
04564 if (fmode == VOIDmode)
04565 {
04566
04567 fmode = GET_MODE (to);
04568
04569
04570 if ((significand_size (fmode) + 1)
04571 < GET_MODE_BITSIZE (GET_MODE (from)))
04572 {
04573 rtx temp1;
04574 rtx neglabel = gen_label_rtx ();
04575
04576
04577
04578 if (!REG_P (target)
04579 || REGNO (target) < FIRST_PSEUDO_REGISTER
04580 || GET_MODE (target) != fmode)
04581 target = gen_reg_rtx (fmode);
04582
04583 imode = GET_MODE (from);
04584 do_pending_stack_adjust ();
04585
04586
04587 emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
04588 0, neglabel);
04589
04590
04591 expand_float (target, from, 0);
04592 emit_jump_insn (gen_jump (label));
04593 emit_barrier ();
04594
04595
04596
04597
04598
04599
04600 emit_label (neglabel);
04601 temp = expand_binop (imode, and_optab, from, const1_rtx,
04602 NULL_RTX, 1, OPTAB_LIB_WIDEN);
04603 temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
04604 NULL_RTX, 1);
04605 temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
04606 OPTAB_LIB_WIDEN);
04607 expand_float (target, temp, 0);
04608
04609
04610 temp = expand_binop (fmode, add_optab, target, target,
04611 target, 0, OPTAB_LIB_WIDEN);
04612 if (temp != target)
04613 emit_move_insn (target, temp);
04614
04615 do_pending_stack_adjust ();
04616 emit_label (label);
04617 goto done;
04618 }
04619 }
04620
04621
04622
04623
04624 if (GET_MODE (to) != fmode
04625 || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
04626 target = gen_reg_rtx (fmode);
04627
04628
04629 expand_float (target, from, 0);
04630
04631
04632
04633
04634 do_pending_stack_adjust ();
04635 emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
04636 0, label);
04637
04638
04639 real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)));
04640 temp = expand_binop (fmode, add_optab, target,
04641 CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
04642 target, 0, OPTAB_LIB_WIDEN);
04643 if (temp != target)
04644 emit_move_insn (target, temp);
04645
04646 do_pending_stack_adjust ();
04647 emit_label (label);
04648 goto done;
04649 }
04650
04651
04652 {
04653 rtx libfunc;
04654 rtx insns;
04655 rtx value;
04656 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
04657
04658 if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
04659 from = convert_to_mode (SImode, from, unsignedp);
04660
04661 libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
04662 gcc_assert (libfunc);
04663
04664 start_sequence ();
04665
04666 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
04667 GET_MODE (to), 1, from,
04668 GET_MODE (from));
04669 insns = get_insns ();
04670 end_sequence ();
04671
04672 emit_libcall_block (insns, target, value,
04673 gen_rtx_FLOAT (GET_MODE (to), from));
04674 }
04675
04676 done:
04677
04678
04679
04680
04681 if (target != to)
04682 {
04683 if (GET_MODE (target) == GET_MODE (to))
04684 emit_move_insn (to, target);
04685 else
04686 convert_move (to, target, 0);
04687 }
04688 }
04689
04690
04691
04692
04693 void
04694 expand_fix (rtx to, rtx from, int unsignedp)
04695 {
04696 enum insn_code icode;
04697 rtx target = to;
04698 enum machine_mode fmode, imode;
04699 int must_trunc = 0;
04700
04701
04702
04703
04704
04705
04706 for (fmode = GET_MODE (from); fmode != VOIDmode;
04707 fmode = GET_MODE_WIDER_MODE (fmode))
04708 for (imode = GET_MODE (to); imode != VOIDmode;
04709 imode = GET_MODE_WIDER_MODE (imode))
04710 {
04711 int doing_unsigned = unsignedp;
04712
04713 icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
04714 if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
04715 icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
04716
04717 if (icode != CODE_FOR_nothing)
04718 {
04719 if (fmode != GET_MODE (from))
04720 from = convert_to_mode (fmode, from, 0);
04721
04722 if (must_trunc)
04723 {
04724 rtx temp = gen_reg_rtx (GET_MODE (from));
04725 from = expand_unop (GET_MODE (from), ftrunc_optab, from,
04726 temp, 0);
04727 }
04728
04729 if (imode != GET_MODE (to))
04730 target = gen_reg_rtx (imode);
04731
04732 emit_unop_insn (icode, target, from,
04733 doing_unsigned ? UNSIGNED_FIX : FIX);
04734 if (target != to)
04735 convert_move (to, target, unsignedp);
04736 return;
04737 }
04738 }
04739
04740
04741
04742
04743
04744
04745
04746
04747
04748
04749
04750
04751
04752
04753
04754
04755
04756
04757
04758
04759
04760
04761
04762 if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
04763 for (fmode = GET_MODE (from); fmode != VOIDmode;
04764 fmode = GET_MODE_WIDER_MODE (fmode))
04765 if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
04766 &must_trunc))
04767 {
04768 int bitsize;
04769 REAL_VALUE_TYPE offset;
04770 rtx limit, lab1, lab2, insn;
04771
04772 bitsize = GET_MODE_BITSIZE (GET_MODE (to));
04773 real_2expN (&offset, bitsize - 1);
04774 limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
04775 lab1 = gen_label_rtx ();
04776 lab2 = gen_label_rtx ();
04777
04778 if (fmode != GET_MODE (from))
04779 from = convert_to_mode (fmode, from, 0);
04780
04781
04782 do_pending_stack_adjust ();
04783 emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
04784 0, lab1);
04785
04786
04787 expand_fix (to, from, 0);
04788 emit_jump_insn (gen_jump (lab2));
04789 emit_barrier ();
04790
04791
04792
04793
04794 emit_label (lab1);
04795 target = expand_binop (GET_MODE (from), sub_optab, from, limit,
04796 NULL_RTX, 0, OPTAB_LIB_WIDEN);
04797 expand_fix (to, target, 0);
04798 target = expand_binop (GET_MODE (to), xor_optab, to,
04799 gen_int_mode
04800 ((HOST_WIDE_INT) 1 << (bitsize - 1),
04801 GET_MODE (to)),
04802 to, 1, OPTAB_LIB_WIDEN);
04803
04804 if (target != to)
04805 emit_move_insn (to, target);
04806
04807 emit_label (lab2);
04808
04809 if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
04810 != CODE_FOR_nothing)
04811 {
04812
04813 insn = emit_move_insn (to, to);
04814 set_unique_reg_note (insn,
04815 REG_EQUAL,
04816 gen_rtx_fmt_e (UNSIGNED_FIX,
04817 GET_MODE (to),
04818 copy_rtx (from)));
04819 }
04820
04821 return;
04822 }
04823
04824
04825
04826
04827
04828 if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
04829 {
04830 target = gen_reg_rtx (SImode);
04831
04832 expand_fix (target, from, unsignedp);
04833 }
04834 else
04835 {
04836 rtx insns;
04837 rtx value;
04838 rtx libfunc;
04839
04840 convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
04841 libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
04842 gcc_assert (libfunc);
04843
04844 start_sequence ();
04845
04846 value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
04847 GET_MODE (to), 1, from,
04848 GET_MODE (from));
04849 insns = get_insns ();
04850 end_sequence ();
04851
04852 emit_libcall_block (insns, target, value,
04853 gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
04854 GET_MODE (to), from));
04855 }
04856
04857 if (target != to)
04858 {
04859 if (GET_MODE (to) == GET_MODE (target))
04860 emit_move_insn (to, target);
04861 else
04862 convert_move (to, target, 0);
04863 }
04864 }
04865
04866
04867
04868 int
04869 have_insn_for (enum rtx_code code, enum machine_mode mode)
04870 {
04871 return (code_to_optab[(int) code] != 0
04872 && (code_to_optab[(int) code]->handlers[(int) mode].insn_code
04873 != CODE_FOR_nothing));
04874 }
04875
04876
04877 static optab
04878 new_optab (void)
04879 {
04880 int i;
04881 optab op = ggc_alloc (sizeof (struct optab));
04882 for (i = 0; i < NUM_MACHINE_MODES; i++)
04883 {
04884 op->handlers[i].insn_code = CODE_FOR_nothing;
04885 op->handlers[i].libfunc = 0;
04886 }
04887
04888 return op;
04889 }
04890
04891 static convert_optab
04892 new_convert_optab (void)
04893 {
04894 int i, j;
04895 convert_optab op = ggc_alloc (sizeof (struct convert_optab));
04896 for (i = 0; i < NUM_MACHINE_MODES; i++)
04897 for (j = 0; j < NUM_MACHINE_MODES; j++)
04898 {
04899 op->handlers[i][j].insn_code = CODE_FOR_nothing;
04900 op->handlers[i][j].libfunc = 0;
04901 }
04902 return op;
04903 }
04904
04905
04906
04907 static inline optab
04908 init_optab (enum rtx_code code)
04909 {
04910 optab op = new_optab ();
04911 op->code = code;
04912 code_to_optab[(int) code] = op;
04913 return op;
04914 }
04915
04916
04917
04918 static inline optab
04919 init_optabv (enum rtx_code code)
04920 {
04921 optab op = new_optab ();
04922 op->code = code;
04923 return op;
04924 }
04925
04926
04927 static inline convert_optab
04928 init_convert_optab (enum rtx_code code)
04929 {
04930 convert_optab op = new_convert_optab ();
04931 op->code = code;
04932 return op;
04933 }
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952 static void
04953 init_libfuncs (optab optable, int first_mode, int last_mode,
04954 const char *opname, int suffix)
04955 {
04956 int mode;
04957 unsigned opname_len = strlen (opname);
04958
04959 for (mode = first_mode; (int) mode <= (int) last_mode;
04960 mode = (enum machine_mode) ((int) mode + 1))
04961 {
04962 const char *mname = GET_MODE_NAME (mode);
04963 unsigned mname_len = strlen (mname);
04964 char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
04965 char *p;
04966 const char *q;
04967
04968 p = libfunc_name;
04969 *p++ = '_';
04970 *p++ = '_';
04971 for (q = opname; *q; )
04972 *p++ = *q++;
04973 for (q = mname; *q; q++)
04974 *p++ = TOLOWER (*q);
04975 *p++ = suffix;
04976 *p = '\0';
04977
04978 optable->handlers[(int) mode].libfunc
04979 = init_one_libfunc (ggc_alloc_string (libfunc_name, p - libfunc_name));
04980 }
04981 }
04982
04983
04984
04985
04986
04987
04988 static void
04989 init_integral_libfuncs (optab optable, const char *opname, int suffix)
04990 {
04991 int maxsize = 2*BITS_PER_WORD;
04992 if (maxsize < LONG_LONG_TYPE_SIZE)
04993 maxsize = LONG_LONG_TYPE_SIZE;
04994 init_libfuncs (optable, word_mode,
04995 mode_for_size (maxsize, MODE_INT, 0),
04996 opname, suffix);
04997 }
04998
04999
05000
05001
05002
05003
05004 static void
05005 init_floating_libfuncs (optab optable, const char *opname, int suffix)
05006 {
05007 init_libfuncs (optable, MIN_MODE_FLOAT, MAX_MODE_FLOAT, opname, suffix);
05008 init_libfuncs (optable, MIN_MODE_DECIMAL_FLOAT, MAX_MODE_DECIMAL_FLOAT,
05009 opname, suffix);
05010 }
05011
05012
05013
05014
05015
05016
05017 static void
05018 init_interclass_conv_libfuncs (convert_optab tab, const char *opname,
05019 enum mode_class from_class,
05020 enum mode_class to_class)
05021 {
05022 enum machine_mode first_from_mode = GET_CLASS_NARROWEST_MODE (from_class);
05023 enum machine_mode first_to_mode = GET_CLASS_NARROWEST_MODE (to_class);
05024 size_t opname_len = strlen (opname);
05025 size_t max_mname_len = 0;
05026
05027 enum machine_mode fmode, tmode;
05028 const char *fname, *tname;
05029 const char *q;
05030 char *libfunc_name, *suffix;
05031 char *p;
05032
05033 for (fmode = first_from_mode;
05034 fmode != VOIDmode;
05035 fmode = GET_MODE_WIDER_MODE (fmode))
05036 max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (fmode)));
05037
05038 for (tmode = first_to_mode;
05039 tmode != VOIDmode;
05040 tmode = GET_MODE_WIDER_MODE (tmode))
05041 max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (tmode)));
05042
05043 libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1);
05044 libfunc_name[0] = '_';
05045 libfunc_name[1] = '_';
05046 memcpy (&libfunc_name[2], opname, opname_len);
05047 suffix = libfunc_name + opname_len + 2;
05048
05049 for (fmode = first_from_mode; fmode != VOIDmode;
05050 fmode = GET_MODE_WIDER_MODE (fmode))
05051 for (tmode = first_to_mode; tmode != VOIDmode;
05052 tmode = GET_MODE_WIDER_MODE (tmode))
05053 {
05054 fname = GET_MODE_NAME (fmode);
05055 tname = GET_MODE_NAME (tmode);
05056
05057 p = suffix;
05058 for (q = fname; *q; p++, q++)
05059 *p = TOLOWER (*q);
05060 for (q = tname; *q; p++, q++)
05061 *p = TOLOWER (*q);
05062
05063 *p = '\0';
05064
05065 tab->handlers[tmode][fmode].libfunc
05066 = init_one_libfunc (ggc_alloc_string (libfunc_name,
05067 p - libfunc_name));
05068 }
05069 }
05070
05071
05072
05073
05074
05075
05076 static void
05077 init_intraclass_conv_libfuncs (convert_optab tab, const char *opname,
05078 enum mode_class class, bool widening)
05079 {
05080 enum machine_mode first_mode = GET_CLASS_NARROWEST_MODE (class);
05081 size_t opname_len = strlen (opname);
05082 size_t max_mname_len = 0;
05083
05084 enum machine_mode nmode, wmode;
05085 const char *nname, *wname;
05086 const char *q;
05087 char *libfunc_name, *suffix;
05088 char *p;
05089
05090 for (nmode = first_mode; nmode != VOIDmode;
05091 nmode = GET_MODE_WIDER_MODE (nmode))
05092 max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (nmode)));
05093
05094 libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1);
05095 libfunc_name[0] = '_';
05096 libfunc_name[1] = '_';
05097 memcpy (&libfunc_name[2], opname, opname_len);
05098 suffix = libfunc_name + opname_len + 2;
05099
05100 for (nmode = first_mode; nmode != VOIDmode;
05101 nmode = GET_MODE_WIDER_MODE (nmode))
05102 for (wmode = GET_MODE_WIDER_MODE (nmode); wmode != VOIDmode;
05103 wmode = GET_MODE_WIDER_MODE (wmode))
05104 {
05105 nname = GET_MODE_NAME (nmode);
05106 wname = GET_MODE_NAME (wmode);
05107
05108 p = suffix;
05109 for (q = widening ? nname : wname; *q; p++, q++)
05110 *p = TOLOWER (*q);
05111 for (q = widening ? wname : nname; *q; p++, q++)
05112 *p = TOLOWER (*q);
05113
05114 *p++ = '2';
05115 *p = '\0';
05116
05117 tab->handlers[widening ? wmode : nmode]
05118 [widening ? nmode : wmode].libfunc
05119 = init_one_libfunc (ggc_alloc_string (libfunc_name,
05120 p - libfunc_name));
05121 }
05122 }
05123
05124
05125 rtx
05126 init_one_libfunc (const char *name)
05127 {
05128 rtx symbol;
05129
05130
05131
05132
05133
05134 tree decl = build_decl (FUNCTION_DECL, get_identifier (name),
05135 build_function_type (integer_type_node, NULL_TREE));
05136 DECL_ARTIFICIAL (decl) = 1;
05137 DECL_EXTERNAL (decl) = 1;
05138 TREE_PUBLIC (decl) = 1;
05139
05140 symbol = XEXP (DECL_RTL (decl), 0);
05141
05142
05143
05144 SET_SYMBOL_REF_DECL (symbol, 0);
05145
05146 return symbol;
05147 }
05148
05149
05150
05151 void
05152 set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
05153 {
05154 if (name)
05155 optable->handlers[mode].libfunc = init_one_libfunc (name);
05156 else
05157 optable->handlers[mode].libfunc = 0;
05158 }
05159
05160
05161
05162
05163 void
05164 set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
05165 enum machine_mode fmode, const char *name)
05166 {
05167 if (name)
05168 optable->handlers[tmode][fmode].libfunc = init_one_libfunc (name);
05169 else
05170 optable->handlers[tmode][fmode].libfunc = 0;
05171 }
05172
05173
05174
05175
05176 void
05177 init_optabs (void)
05178 {
05179 unsigned int i;
05180
05181
05182
05183 for (i = 0; i < NUM_RTX_CODE; i++)
05184 setcc_gen_code[i] = CODE_FOR_nothing;
05185
05186 #ifdef HAVE_conditional_move
05187 for (i = 0; i < NUM_MACHINE_MODES; i++)
05188 movcc_gen_code[i] = CODE_FOR_nothing;
05189 #endif
05190
05191 for (i = 0; i < NUM_MACHINE_MODES; i++)
05192 {
05193 vcond_gen_code[i] = CODE_FOR_nothing;
05194 vcondu_gen_code[i] = CODE_FOR_nothing;
05195 }
05196
05197 add_optab = init_optab (PLUS);
05198 addv_optab = init_optabv (PLUS);
05199 sub_optab = init_optab (MINUS);
05200 subv_optab = init_optabv (MINUS);
05201 smul_optab = init_optab (MULT);
05202 smulv_optab = init_optabv (MULT);
05203 smul_highpart_optab = init_optab (UNKNOWN);
05204 umul_highpart_optab = init_optab (UNKNOWN);
05205 smul_widen_optab = init_optab (UNKNOWN);
05206 umul_widen_optab = init_optab (UNKNOWN);
05207 usmul_widen_optab = init_optab (UNKNOWN);
05208 sdiv_optab = init_optab (DIV);
05209 sdivv_optab = init_optabv (DIV);
05210 sdivmod_optab = init_optab (UNKNOWN);
05211 udiv_optab = init_optab (UDIV);
05212 udivmod_optab = init_optab (UNKNOWN);
05213 smod_optab = init_optab (MOD);
05214 umod_optab = init_optab (UMOD);
05215 fmod_optab = init_optab (UNKNOWN);
05216 drem_optab = init_optab (UNKNOWN);
05217 ftrunc_optab = init_optab (UNKNOWN);
05218 and_optab = init_optab (AND);
05219 ior_optab = init_optab (IOR);
05220 xor_optab = init_optab (XOR);
05221 ashl_optab = init_optab (ASHIFT);
05222 ashr_optab = init_optab (ASHIFTRT);
05223 lshr_optab = init_optab (LSHIFTRT);
05224 rotl_optab = init_optab (ROTATE);
05225 rotr_optab = init_optab (ROTATERT);
05226 smin_optab = init_optab (SMIN);
05227 smax_optab = init_optab (SMAX);
05228 umin_optab = init_optab (UMIN);
05229 umax_optab = init_optab (UMAX);
05230 pow_optab = init_optab (UNKNOWN);
05231 atan2_optab = init_optab (UNKNOWN);
05232
05233
05234
05235 mov_optab = init_optab (SET);
05236 movstrict_optab = init_optab (STRICT_LOW_PART);
05237 cmp_optab = init_optab (COMPARE);
05238
05239 ucmp_optab = init_optab (UNKNOWN);
05240 tst_optab = init_optab (UNKNOWN);
05241
05242 eq_optab = init_optab (EQ);
05243 ne_optab = init_optab (NE);
05244 gt_optab = init_optab (GT);
05245 ge_optab = init_optab (GE);
05246 lt_optab = init_optab (LT);
05247 le_optab = init_optab (LE);
05248 unord_optab = init_optab (UNORDERED);
05249
05250 neg_optab = init_optab (NEG);
05251 negv_optab = init_optabv (NEG);
05252 abs_optab = init_optab (ABS);
05253 absv_optab = init_optabv (ABS);
05254 addcc_optab = init_optab (UNKNOWN);
05255 one_cmpl_optab = init_optab (NOT);
05256 ffs_optab = init_optab (FFS);
05257 clz_optab = init_optab (CLZ);
05258 ctz_optab = init_optab (CTZ);
05259 popcount_optab = init_optab (POPCOUNT);
05260 parity_optab = init_optab (PARITY);
05261 sqrt_optab = init_optab (SQRT);
05262 floor_optab = init_optab (UNKNOWN);
05263 lfloor_optab = init_optab (UNKNOWN);
05264 ceil_optab = init_optab (UNKNOWN);
05265 lceil_optab = init_optab (UNKNOWN);
05266 round_optab = init_optab (UNKNOWN);
05267 btrunc_optab = init_optab (UNKNOWN);
05268 nearbyint_optab = init_optab (UNKNOWN);
05269 rint_optab = init_optab (UNKNOWN);
05270 lrint_optab = init_optab (UNKNOWN);
05271 sincos_optab = init_optab (UNKNOWN);
05272 sin_optab = init_optab (UNKNOWN);
05273 asin_optab = init_optab (UNKNOWN);
05274 cos_optab = init_optab (UNKNOWN);
05275 acos_optab = init_optab (UNKNOWN);
05276 exp_optab = init_optab (UNKNOWN);
05277 exp10_optab = init_optab (UNKNOWN);
05278 exp2_optab = init_optab (UNKNOWN);
05279 expm1_optab = init_optab (UNKNOWN);
05280 ldexp_optab = init_optab (UNKNOWN);
05281 logb_optab = init_optab (UNKNOWN);
05282 ilogb_optab = init_optab (UNKNOWN);
05283 log_optab = init_optab (UNKNOWN);
05284 log10_optab = init_optab (UNKNOWN);
05285 log2_optab = init_optab (UNKNOWN);
05286 log1p_optab = init_optab (UNKNOWN);
05287 tan_optab = init_optab (UNKNOWN);
05288 atan_optab = init_optab (UNKNOWN);
05289 copysign_optab = init_optab (UNKNOWN);
05290
05291 strlen_optab = init_optab (UNKNOWN);
05292 cbranch_optab = init_optab (UNKNOWN);
05293 cmov_optab = init_optab (UNKNOWN);
05294 cstore_optab = init_optab (UNKNOWN);
05295 push_optab = init_optab (UNKNOWN);
05296
05297 reduc_smax_optab = init_optab (UNKNOWN);
05298 reduc_umax_optab = init_optab (UNKNOWN);
05299 reduc_smin_optab = init_optab (UNKNOWN);
05300 reduc_umin_optab = init_optab (UNKNOWN);
05301 reduc_splus_optab = init_optab (UNKNOWN);
05302 reduc_uplus_optab = init_optab (UNKNOWN);
05303
05304 ssum_widen_optab = init_optab (UNKNOWN);
05305 usum_widen_optab = init_optab (UNKNOWN);
05306 sdot_prod_optab = init_optab (UNKNOWN);
05307 udot_prod_optab = init_optab (UNKNOWN);
05308
05309 vec_extract_optab = init_optab (UNKNOWN);
05310 vec_set_optab = init_optab (UNKNOWN);
05311 vec_init_optab = init_optab (UNKNOWN);
05312 vec_shl_optab = init_optab (UNKNOWN);
05313 vec_shr_optab = init_optab (UNKNOWN);
05314 vec_realign_load_optab = init_optab (UNKNOWN);
05315 movmisalign_optab = init_optab (UNKNOWN);
05316
05317 powi_optab = init_optab (UNKNOWN);
05318
05319
05320 sext_optab = init_convert_optab (SIGN_EXTEND);
05321 zext_optab = init_convert_optab (ZERO_EXTEND);
05322 trunc_optab = init_convert_optab (TRUNCATE);
05323 sfix_optab = init_convert_optab (FIX);
05324 ufix_optab = init_convert_optab (UNSIGNED_FIX);
05325 sfixtrunc_optab = init_convert_optab (UNKNOWN);
05326 ufixtrunc_optab = init_convert_optab (UNKNOWN);
05327 sfloat_optab = init_convert_optab (FLOAT);
05328 ufloat_optab = init_convert_optab (UNSIGNED_FLOAT);
05329
05330 for (i = 0; i < NUM_MACHINE_MODES; i++)
05331 {
05332 movmem_optab[i] = CODE_FOR_nothing;
05333 cmpstr_optab[i] = CODE_FOR_nothing;
05334 cmpstrn_optab[i] = CODE_FOR_nothing;
05335 cmpmem_optab[i] = CODE_FOR_nothing;
05336 setmem_optab[i] = CODE_FOR_nothing;
05337
05338 sync_add_optab[i] = CODE_FOR_nothing;
05339 sync_sub_optab[i] = CODE_FOR_nothing;
05340 sync_ior_optab[i] = CODE_FOR_nothing;
05341 sync_and_optab[i] = CODE_FOR_nothing;
05342 sync_xor_optab[i] = CODE_FOR_nothing;
05343 sync_nand_optab[i] = CODE_FOR_nothing;
05344 sync_old_add_optab[i] = CODE_FOR_nothing;
05345 sync_old_sub_optab[i] = CODE_FOR_nothing;
05346 sync_old_ior_optab[i] = CODE_FOR_nothing;
05347 sync_old_and_optab[i] = CODE_FOR_nothing;
05348 sync_old_xor_optab[i] = CODE_FOR_nothing;
05349 sync_old_nand_optab[i] = CODE_FOR_nothing;
05350 sync_new_add_optab[i] = CODE_FOR_nothing;
05351 sync_new_sub_optab[i] = CODE_FOR_nothing;
05352 sync_new_ior_optab[i] = CODE_FOR_nothing;
05353 sync_new_and_optab[i] = CODE_FOR_nothing;
05354 sync_new_xor_optab[i] = CODE_FOR_nothing;
05355 sync_new_nand_optab[i] = CODE_FOR_nothing;
05356 sync_compare_and_swap[i] = CODE_FOR_nothing;
05357 sync_compare_and_swap_cc[i] = CODE_FOR_nothing;
05358 sync_lock_test_and_set[i] = CODE_FOR_nothing;
05359 sync_lock_release[i] = CODE_FOR_nothing;
05360
05361 reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
05362 }
05363
05364
05365 init_all_optabs ();
05366
05367
05368 init_integral_libfuncs (add_optab, "add", '3');
05369 init_floating_libfuncs (add_optab, "add", '3');
05370 init_integral_libfuncs (addv_optab, "addv", '3');
05371 init_floating_libfuncs (addv_optab, "add", '3');
05372 init_integral_libfuncs (sub_optab, "sub", '3');
05373 init_floating_libfuncs (sub_optab, "sub", '3');
05374 init_integral_libfuncs (subv_optab, "subv", '3');
05375 init_floating_libfuncs (subv_optab, "sub", '3');
05376 init_integral_libfuncs (smul_optab, "mul", '3');
05377 init_floating_libfuncs (smul_optab, "mul", '3');
05378 init_integral_libfuncs (smulv_optab, "mulv", '3');
05379 init_floating_libfuncs (smulv_optab, "mul", '3');
05380 init_integral_libfuncs (sdiv_optab, "div", '3');
05381 init_floating_libfuncs (sdiv_optab, "div", '3');
05382 init_integral_libfuncs (sdivv_optab, "divv", '3');
05383 init_integral_libfuncs (udiv_optab, "udiv", '3');
05384 init_integral_libfuncs (sdivmod_optab, "divmod", '4');
05385 init_integral_libfuncs (udivmod_optab, "udivmod", '4');
05386 init_integral_libfuncs (smod_optab, "mod", '3');
05387 init_integral_libfuncs (umod_optab, "umod", '3');
05388 init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
05389 init_integral_libfuncs (and_optab, "and", '3');
05390 init_integral_libfuncs (ior_optab, "ior", '3');
05391 init_integral_libfuncs (xor_optab, "xor", '3');
05392 init_integral_libfuncs (ashl_optab, "ashl", '3');
05393 init_integral_libfuncs (ashr_optab, "ashr", '3');
05394 init_integral_libfuncs (lshr_optab, "lshr", '3');
05395 init_integral_libfuncs (smin_optab, "min", '3');
05396 init_floating_libfuncs (smin_optab, "min", '3');
05397 init_integral_libfuncs (smax_optab, "max", '3');
05398 init_floating_libfuncs (smax_optab, "max", '3');
05399 init_integral_libfuncs (umin_optab, "umin", '3');
05400 init_integral_libfuncs (umax_optab, "umax", '3');
05401 init_integral_libfuncs (neg_optab, "neg", '2');
05402 init_floating_libfuncs (neg_optab, "neg", '2');
05403 init_integral_libfuncs (negv_optab, "negv", '2');
05404 init_floating_libfuncs (negv_optab, "neg", '2');
05405 init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
05406 init_integral_libfuncs (ffs_optab, "ffs", '2');
05407 init_integral_libfuncs (clz_optab, "clz", '2');
05408 init_integral_libfuncs (ctz_optab, "ctz", '2');
05409 init_integral_libfuncs (popcount_optab, "popcount", '2');
05410 init_integral_libfuncs (parity_optab, "parity", '2');
05411
05412
05413
05414 init_integral_libfuncs (cmp_optab, "cmp", '2');
05415 init_integral_libfuncs (ucmp_optab, "ucmp", '2');
05416 init_floating_libfuncs (cmp_optab, "cmp", '2');
05417
05418
05419 init_floating_libfuncs (eq_optab, "eq", '2');
05420 init_floating_libfuncs (ne_optab, "ne", '2');
05421 init_floating_libfuncs (gt_optab, "gt", '2');
05422 init_floating_libfuncs (ge_optab, "ge", '2');
05423 init_floating_libfuncs (lt_optab, "lt", '2');
05424 init_floating_libfuncs (le_optab, "le", '2');
05425 init_floating_libfuncs (unord_optab, "unord", '2');
05426
05427 init_floating_libfuncs (powi_optab, "powi", '2');
05428
05429
05430 init_interclass_conv_libfuncs (sfloat_optab, "float",
05431 MODE_INT, MODE_FLOAT);
05432 init_interclass_conv_libfuncs (sfloat_optab, "float",
05433 MODE_INT, MODE_DECIMAL_FLOAT);
05434 init_interclass_conv_libfuncs (ufloat_optab, "floatun",
05435 MODE_INT, MODE_FLOAT);
05436 init_interclass_conv_libfuncs (ufloat_optab, "floatun",
05437 MODE_INT, MODE_DECIMAL_FLOAT);
05438 init_interclass_conv_libfuncs (sfix_optab, "fix",
05439 MODE_FLOAT, MODE_INT);
05440 init_interclass_conv_libfuncs (sfix_optab, "fix",
05441 MODE_DECIMAL_FLOAT, MODE_INT);
05442 init_interclass_conv_libfuncs (ufix_optab, "fixuns",
05443 MODE_FLOAT, MODE_INT);
05444 init_interclass_conv_libfuncs (ufix_optab, "fixuns",
05445 MODE_DECIMAL_FLOAT, MODE_INT);
05446 init_interclass_conv_libfuncs (ufloat_optab, "floatuns",
05447 MODE_INT, MODE_DECIMAL_FLOAT);
05448
05449
05450 init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true);
05451 init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_DECIMAL_FLOAT, true);
05452 init_interclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, MODE_DECIMAL_FLOAT);
05453 init_interclass_conv_libfuncs (sext_optab, "extend", MODE_DECIMAL_FLOAT, MODE_FLOAT);
05454 init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, false);
05455 init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_DECIMAL_FLOAT, false);
05456 init_interclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, MODE_DECIMAL_FLOAT);
05457 init_interclass_conv_libfuncs (trunc_optab, "trunc", MODE_DECIMAL_FLOAT, MODE_FLOAT);
05458
05459
05460
05461 if (complex_double_type_node)
05462 abs_optab->handlers[TYPE_MODE (complex_double_type_node)].libfunc
05463 = init_one_libfunc ("cabs");
05464
05465
05466 ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc
05467 = init_one_libfunc ("ffs");
05468
05469 abort_libfunc = init_one_libfunc ("abort");
05470 memcpy_libfunc = init_one_libfunc ("memcpy");
05471 memmove_libfunc = init_one_libfunc ("memmove");
05472 memcmp_libfunc = init_one_libfunc ("memcmp");
05473 memset_libfunc = init_one_libfunc ("memset");
05474 setbits_libfunc = init_one_libfunc ("__setbits");
05475
05476 #ifndef DONT_USE_BUILTIN_SETJMP
05477 setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
05478 longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
05479 #else
05480 setjmp_libfunc = init_one_libfunc ("setjmp");
05481 longjmp_libfunc = init_one_libfunc ("longjmp");
05482 #endif
05483 unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
05484 unwind_sjlj_unregister_libfunc
05485 = init_one_libfunc ("_Unwind_SjLj_Unregister");
05486
05487
05488 profile_function_entry_libfunc
05489 = init_one_libfunc ("__cyg_profile_func_enter");
05490 profile_function_exit_libfunc
05491 = init_one_libfunc ("__cyg_profile_func_exit");
05492
05493 gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
05494
05495 if (HAVE_conditional_trap)
05496 trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
05497
05498
05499 targetm.init_libfuncs ();
05500 }
05501
05502 #ifdef DEBUG
05503
05504
05505
05506
05507 static void
05508 debug_optab_libfuncs (void)
05509 {
05510 int i;
05511 int j;
05512 int k;
05513
05514
05515 for (i = 0; i != (int) OTI_MAX; i++)
05516 for (j = 0; j < NUM_MACHINE_MODES; ++j)
05517 {
05518 optab o;
05519 struct optab_handlers *h;
05520
05521 o = optab_table[i];
05522 h = &o->handlers[j];
05523 if (h->libfunc)
05524 {
05525 gcc_assert (GET_CODE (h->libfunc) = SYMBOL_REF);
05526 fprintf (stderr, "%s\t%s:\t%s\n",
05527 GET_RTX_NAME (o->code),
05528 GET_MODE_NAME (j),
05529 XSTR (h->libfunc, 0));
05530 }
05531 }
05532
05533
05534 for (i = 0; i < (int) COI_MAX; ++i)
05535 for (j = 0; j < NUM_MACHINE_MODES; ++j)
05536 for (k = 0; k < NUM_MACHINE_MODES; ++k)
05537 {
05538 convert_optab o;
05539 struct optab_handlers *h;
05540
05541 o = &convert_optab_table[i];
05542 h = &o->handlers[j][k];
05543 if (h->libfunc)
05544 {
05545 gcc_assert (GET_CODE (h->libfunc) = SYMBOL_REF);
05546 fprintf (stderr, "%s\t%s\t%s:\t%s\n",
05547 GET_RTX_NAME (o->code),
05548 GET_MODE_NAME (j),
05549 GET_MODE_NAME (k),
05550 XSTR (h->libfunc, 0));
05551 }
05552 }
05553 }
05554
05555 #endif
05556
05557
05558
05559
05560
05561 rtx
05562 gen_cond_trap (enum rtx_code code ATTRIBUTE_UNUSED, rtx op1,
05563 rtx op2 ATTRIBUTE_UNUSED, rtx tcode ATTRIBUTE_UNUSED)
05564 {
05565 enum machine_mode mode = GET_MODE (op1);
05566 enum insn_code icode;
05567 rtx insn;
05568
05569 if (!HAVE_conditional_trap)
05570 return 0;
05571
05572 if (mode == VOIDmode)
05573 return 0;
05574
05575 icode = cmp_optab->handlers[(int) mode].insn_code;
05576 if (icode == CODE_FOR_nothing)
05577 return 0;
05578
05579 start_sequence ();
05580 op1 = prepare_operand (icode, op1, 0, mode, mode, 0);
05581 op2 = prepare_operand (icode, op2, 1, mode, mode, 0);
05582 if (!op1 || !op2)
05583 {
05584 end_sequence ();
05585 return 0;
05586 }
05587 emit_insn (GEN_FCN (icode) (op1, op2));
05588
05589 PUT_CODE (trap_rtx, code);
05590 gcc_assert (HAVE_conditional_trap);
05591 insn = gen_conditional_trap (trap_rtx, tcode);
05592 if (insn)
05593 {
05594 emit_insn (insn);
05595 insn = get_insns ();
05596 }
05597 end_sequence ();
05598
05599 return insn;
05600 }
05601
05602
05603
05604
05605 static enum rtx_code
05606 get_rtx_code (enum tree_code tcode, bool unsignedp)
05607 {
05608 enum rtx_code code;
05609 switch (tcode)
05610 {
05611 case EQ_EXPR:
05612 code = EQ;
05613 break;
05614 case NE_EXPR:
05615 code = NE;
05616 break;
05617 case LT_EXPR:
05618 code = unsignedp ? LTU : LT;
05619 break;
05620 case LE_EXPR:
05621 code = unsignedp ? LEU : LE;
05622 break;
05623 case GT_EXPR:
05624 code = unsignedp ? GTU : GT;
05625 break;
05626 case GE_EXPR:
05627 code = unsignedp ? GEU : GE;
05628 break;
05629
05630 case UNORDERED_EXPR:
05631 code = UNORDERED;
05632 break;
05633 case ORDERED_EXPR:
05634 code = ORDERED;
05635 break;
05636 case UNLT_EXPR:
05637 code = UNLT;
05638 break;
05639 case UNLE_EXPR:
05640 code = UNLE;
05641 break;
05642 case UNGT_EXPR:
05643 code = UNGT;
05644 break;
05645 case UNGE_EXPR:
05646 code = UNGE;
05647 break;
05648 case UNEQ_EXPR:
05649 code = UNEQ;
05650 break;
05651 case LTGT_EXPR:
05652 code = LTGT;
05653 break;
05654
05655 default:
05656 gcc_unreachable ();
05657 }
05658 return code;
05659 }
05660
05661
05662
05663
05664 static rtx
05665 vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
05666 {
05667 enum rtx_code rcode;
05668 tree t_op0, t_op1;
05669 rtx rtx_op0, rtx_op1;
05670
05671
05672
05673 gcc_assert (COMPARISON_CLASS_P (cond));
05674
05675 rcode = get_rtx_code (TREE_CODE (cond), unsignedp);
05676 t_op0 = TREE_OPERAND (cond, 0);
05677 t_op1 = TREE_OPERAND (cond, 1);
05678
05679
05680 rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)), 1);
05681 rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)), 1);
05682
05683 if (!insn_data[icode].operand[4].predicate (rtx_op0, GET_MODE (rtx_op0))
05684 && GET_MODE (rtx_op0) != VOIDmode)
05685 rtx_op0 = force_reg (GET_MODE (rtx_op0), rtx_op0);
05686
05687 if (!insn_data[icode].operand[5].predicate (rtx_op1, GET_MODE (rtx_op1))
05688 && GET_MODE (rtx_op1) != VOIDmode)
05689 rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
05690
05691 return gen_rtx_fmt_ee (rcode, VOIDmode, rtx_op0, rtx_op1);
05692 }
05693
05694
05695
05696 static inline enum insn_code
05697 get_vcond_icode (tree expr, enum machine_mode mode)
05698 {
05699 enum insn_code icode = CODE_FOR_nothing;
05700
05701 if (TYPE_UNSIGNED (TREE_TYPE (expr)))
05702 icode = vcondu_gen_code[mode];
05703 else
05704 icode = vcond_gen_code[mode];
05705 return icode;
05706 }
05707
05708
05709
05710
05711 bool
05712 expand_vec_cond_expr_p (tree expr, enum machine_mode vmode)
05713 {
05714 if (get_vcond_icode (expr, vmode) == CODE_FOR_nothing)
05715 return false;
05716 return true;
05717 }
05718
05719
05720
05721 rtx
05722 expand_vec_cond_expr (tree vec_cond_expr, rtx target)
05723 {
05724 enum insn_code icode;
05725 rtx comparison, rtx_op1, rtx_op2, cc_op0, cc_op1;
05726 enum machine_mode mode = TYPE_MODE (TREE_TYPE (vec_cond_expr));
05727 bool unsignedp = TYPE_UNSIGNED (TREE_TYPE (vec_cond_expr));
05728
05729 icode = get_vcond_icode (vec_cond_expr, mode);
05730 if (icode == CODE_FOR_nothing)
05731 return 0;
05732
05733 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
05734 target = gen_reg_rtx (mode);
05735
05736
05737 comparison = vector_compare_rtx (TREE_OPERAND (vec_cond_expr, 0),
05738 unsignedp, icode);
05739 cc_op0 = XEXP (comparison, 0);
05740 cc_op1 = XEXP (comparison, 1);
05741
05742 rtx_op1 = expand_expr (TREE_OPERAND (vec_cond_expr, 1),
05743 NULL_RTX, VOIDmode, EXPAND_NORMAL);
05744 if (!insn_data[icode].operand[1].predicate (rtx_op1, mode)
05745 && mode != VOIDmode)
05746 rtx_op1 = force_reg (mode, rtx_op1);
05747
05748 rtx_op2 = expand_expr (TREE_OPERAND (vec_cond_expr, 2),
05749 NULL_RTX, VOIDmode, EXPAND_NORMAL);
05750 if (!insn_data[icode].operand[2].predicate (rtx_op2, mode)
05751 && mode != VOIDmode)
05752 rtx_op2 = force_reg (mode, rtx_op2);
05753
05754
05755 emit_insn (GEN_FCN (icode) (target, rtx_op1, rtx_op2,
05756 comparison, cc_op0, cc_op1));
05757
05758 return target;
05759 }
05760
05761
05762
05763
05764
05765
05766
05767
05768 static rtx
05769 expand_val_compare_and_swap_1 (rtx mem, rtx old_val, rtx new_val,
05770 rtx target, enum insn_code icode)
05771 {
05772 enum machine_mode mode = GET_MODE (mem);
05773 rtx insn;
05774
05775 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
05776 target = gen_reg_rtx (mode);
05777
05778 if (GET_MODE (old_val) != VOIDmode && GET_MODE (old_val) != mode)
05779 old_val = convert_modes (mode, GET_MODE (old_val), old_val, 1);
05780 if (!insn_data[icode].operand[2].predicate (old_val, mode))
05781 old_val = force_reg (mode, old_val);
05782
05783 if (GET_MODE (new_val) != VOIDmode && GET_MODE (new_val) != mode)
05784 new_val = convert_modes (mode, GET_MODE (new_val), new_val, 1);
05785 if (!insn_data[icode].operand[3].predicate (new_val, mode))
05786 new_val = force_reg (mode, new_val);
05787
05788 insn = GEN_FCN (icode) (target, mem, old_val, new_val);
05789 if (insn == NULL_RTX)
05790 return NULL_RTX;
05791 emit_insn (insn);
05792
05793 return target;
05794 }
05795
05796
05797
05798 rtx
05799 expand_val_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
05800 {
05801 enum machine_mode mode = GET_MODE (mem);
05802 enum insn_code icode = sync_compare_and_swap[mode];
05803
05804 if (icode == CODE_FOR_nothing)
05805 return NULL_RTX;
05806
05807 return expand_val_compare_and_swap_1 (mem, old_val, new_val, target, icode);
05808 }
05809
05810
05811
05812
05813
05814 rtx
05815 expand_bool_compare_and_swap (rtx mem, rtx old_val, rtx new_val, rtx target)
05816 {
05817 enum machine_mode mode = GET_MODE (mem);
05818 enum insn_code icode;
05819 rtx subtarget, label0, label1;
05820
05821
05822
05823
05824 icode = sync_compare_and_swap_cc[mode];
05825 switch (icode)
05826 {
05827 default:
05828 subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
05829 NULL_RTX, icode);
05830 if (subtarget != NULL_RTX)
05831 break;
05832
05833
05834 case CODE_FOR_nothing:
05835 icode = sync_compare_and_swap[mode];
05836 if (icode == CODE_FOR_nothing)
05837 return NULL_RTX;
05838
05839
05840
05841 if (MEM_P (old_val))
05842 old_val = force_reg (mode, old_val);
05843
05844 subtarget = expand_val_compare_and_swap_1 (mem, old_val, new_val,
05845 NULL_RTX, icode);
05846 if (subtarget == NULL_RTX)
05847 return NULL_RTX;
05848
05849 emit_cmp_insn (subtarget, old_val, EQ, const0_rtx, mode, true);
05850 }
05851
05852
05853
05854
05855 if (STORE_FLAG_VALUE == 1)
05856 {
05857 icode = setcc_gen_code[EQ];
05858 if (icode != CODE_FOR_nothing)
05859 {
05860 enum machine_mode cmode = insn_data[icode].operand[0].mode;
05861 rtx insn;
05862
05863 subtarget = target;
05864 if (!insn_data[icode].operand[0].predicate (target, cmode))
05865 subtarget = gen_reg_rtx (cmode);
05866
05867 insn = GEN_FCN (icode) (subtarget);
05868 if (insn)
05869 {
05870 emit_insn (insn);
05871 if (GET_MODE (target) != GET_MODE (subtarget))
05872 {
05873 convert_move (target, subtarget, 1);
05874 subtarget = target;
05875 }
05876 return subtarget;
05877 }
05878 }
05879 }
05880
05881
05882
05883
05884
05885 label0 = gen_label_rtx ();
05886 label1 = gen_label_rtx ();
05887
05888 emit_jump_insn (bcc_gen_fctn[EQ] (label0));
05889 emit_move_insn (target, const0_rtx);
05890 emit_jump_insn (gen_jump (label1));
05891 emit_barrier ();
05892 emit_label (label0);
05893 emit_move_insn (target, const1_rtx);
05894 emit_label (label1);
05895
05896 return target;
05897 }
05898
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908 static bool
05909 expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
05910 {
05911 enum machine_mode mode = GET_MODE (mem);
05912 enum insn_code icode;
05913 rtx label, cmp_reg, subtarget;
05914
05915
05916
05917
05918
05919
05920
05921
05922
05923
05924
05925
05926
05927
05928 label = gen_label_rtx ();
05929 cmp_reg = gen_reg_rtx (mode);
05930
05931 emit_move_insn (cmp_reg, mem);
05932 emit_label (label);
05933 emit_move_insn (old_reg, cmp_reg);
05934 if (seq)
05935 emit_insn (seq);
05936
05937
05938
05939
05940 icode = sync_compare_and_swap_cc[mode];
05941 switch (icode)
05942 {
05943 default:
05944 subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
05945 cmp_reg, icode);
05946 if (subtarget != NULL_RTX)
05947 {
05948 gcc_assert (subtarget == cmp_reg);
05949 break;
05950 }
05951
05952
05953 case CODE_FOR_nothing:
05954 icode = sync_compare_and_swap[mode];
05955 if (icode == CODE_FOR_nothing)
05956 return false;
05957
05958 subtarget = expand_val_compare_and_swap_1 (mem, old_reg, new_reg,
05959 cmp_reg, icode);
05960 if (subtarget == NULL_RTX)
05961 return false;
05962 if (subtarget != cmp_reg)
05963 emit_move_insn (cmp_reg, subtarget);
05964
05965 emit_cmp_insn (cmp_reg, old_reg, EQ, const0_rtx, mode, true);
05966 }
05967
05968
05969 emit_jump_insn (bcc_gen_fctn[NE] (label));
05970
05971 return true;
05972 }
05973
05974
05975
05976
05977
05978 rtx
05979 expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
05980 {
05981 enum machine_mode mode = GET_MODE (mem);
05982 enum insn_code icode;
05983 rtx insn;
05984
05985
05986 switch (code)
05987 {
05988 case PLUS:
05989 icode = sync_add_optab[mode];
05990 break;
05991 case IOR:
05992 icode = sync_ior_optab[mode];
05993 break;
05994 case XOR:
05995 icode = sync_xor_optab[mode];
05996 break;
05997 case AND:
05998 icode = sync_and_optab[mode];
05999 break;
06000 case NOT:
06001 icode = sync_nand_optab[mode];
06002 break;
06003
06004 case MINUS:
06005 icode = sync_sub_optab[mode];
06006 if (icode == CODE_FOR_nothing)
06007 {
06008 icode = sync_add_optab[mode];
06009 if (icode != CODE_FOR_nothing)
06010 {
06011 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
06012 code = PLUS;
06013 }
06014 }
06015 break;
06016
06017 default:
06018 gcc_unreachable ();
06019 }
06020
06021
06022 if (icode != CODE_FOR_nothing)
06023 {
06024 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
06025 val = convert_modes (mode, GET_MODE (val), val, 1);
06026 if (!insn_data[icode].operand[1].predicate (val, mode))
06027 val = force_reg (mode, val);
06028
06029 insn = GEN_FCN (icode) (mem, val);
06030 if (insn)
06031 {
06032 emit_insn (insn);
06033 return const0_rtx;
06034 }
06035 }
06036
06037
06038
06039 if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
06040 {
06041 rtx t0 = gen_reg_rtx (mode), t1;
06042
06043 start_sequence ();
06044
06045 t1 = t0;
06046 if (code == NOT)
06047 {
06048 t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
06049 code = AND;
06050 }
06051 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
06052 true, OPTAB_LIB_WIDEN);
06053
06054 insn = get_insns ();
06055 end_sequence ();
06056
06057 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
06058 return const0_rtx;
06059 }
06060
06061 return NULL_RTX;
06062 }
06063
06064
06065
06066
06067
06068
06069
06070 rtx
06071 expand_sync_fetch_operation (rtx mem, rtx val, enum rtx_code code,
06072 bool after, rtx target)
06073 {
06074 enum machine_mode mode = GET_MODE (mem);
06075 enum insn_code old_code, new_code, icode;
06076 bool compensate;
06077 rtx insn;
06078
06079
06080 switch (code)
06081 {
06082 case PLUS:
06083 old_code = sync_old_add_optab[mode];
06084 new_code = sync_new_add_optab[mode];
06085 break;
06086 case IOR:
06087 old_code = sync_old_ior_optab[mode];
06088 new_code = sync_new_ior_optab[mode];
06089 break;
06090 case XOR:
06091 old_code = sync_old_xor_optab[mode];
06092 new_code = sync_new_xor_optab[mode];
06093 break;
06094 case AND:
06095 old_code = sync_old_and_optab[mode];
06096 new_code = sync_new_and_optab[mode];
06097 break;
06098 case NOT:
06099 old_code = sync_old_nand_optab[mode];
06100 new_code = sync_new_nand_optab[mode];
06101 break;
06102
06103 case MINUS:
06104 old_code = sync_old_sub_optab[mode];
06105 new_code = sync_new_sub_optab[mode];
06106 if (old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
06107 {
06108 old_code = sync_old_add_optab[mode];
06109 new_code = sync_new_add_optab[mode];
06110 if (old_code != CODE_FOR_nothing || new_code != CODE_FOR_nothing)
06111 {
06112 val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
06113 code = PLUS;
06114 }
06115 }
06116 break;
06117
06118 default:
06119 gcc_unreachable ();
06120 }
06121
06122
06123
06124
06125
06126
06127
06128 compensate = false;
06129 if (after)
06130 {
06131 icode = new_code;
06132 if (icode == CODE_FOR_nothing)
06133 {
06134 icode = old_code;
06135 if (icode != CODE_FOR_nothing)
06136 compensate = true;
06137 }
06138 }
06139 else
06140 {
06141 icode = old_code;
06142 if (icode == CODE_FOR_nothing
06143 && (code == PLUS || code == MINUS || code == XOR))
06144 {
06145 icode = new_code;
06146 if (icode != CODE_FOR_nothing)
06147 compensate = true;
06148 }
06149 }
06150
06151
06152 if (icode != CODE_FOR_nothing)
06153 {
06154 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
06155 target = gen_reg_rtx (mode);
06156
06157 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
06158 val = convert_modes (mode, GET_MODE (val), val, 1);
06159 if (!insn_data[icode].operand[2].predicate (val, mode))
06160 val = force_reg (mode, val);
06161
06162 insn = GEN_FCN (icode) (target, mem, val);
06163 if (insn)
06164 {
06165 emit_insn (insn);
06166
06167
06168
06169 if (compensate)
06170 {
06171 if (!after)
06172 {
06173 if (code == PLUS)
06174 code = MINUS;
06175 else if (code == MINUS)
06176 code = PLUS;
06177 }
06178
06179 if (code == NOT)
06180 target = expand_simple_unop (mode, NOT, target, NULL_RTX, true);
06181 target = expand_simple_binop (mode, code, target, val, NULL_RTX,
06182 true, OPTAB_LIB_WIDEN);
06183 }
06184
06185 return target;
06186 }
06187 }
06188
06189
06190
06191 if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
06192 {
06193 rtx t0 = gen_reg_rtx (mode), t1;
06194
06195 if (!target || !register_operand (target, mode))
06196 target = gen_reg_rtx (mode);
06197
06198 start_sequence ();
06199
06200 if (!after)
06201 emit_move_insn (target, t0);
06202 t1 = t0;
06203 if (code == NOT)
06204 {
06205 t1 = expand_simple_unop (mode, NOT, t1, NULL_RTX, true);
06206 code = AND;
06207 }
06208 t1 = expand_simple_binop (mode, code, t1, val, NULL_RTX,
06209 true, OPTAB_LIB_WIDEN);
06210 if (after)
06211 emit_move_insn (target, t1);
06212
06213 insn = get_insns ();
06214 end_sequence ();
06215
06216 if (t1 != NULL && expand_compare_and_swap_loop (mem, t0, t1, insn))
06217 return target;
06218 }
06219
06220 return NULL_RTX;
06221 }
06222
06223
06224
06225
06226
06227
06228
06229
06230 rtx
06231 expand_sync_lock_test_and_set (rtx mem, rtx val, rtx target)
06232 {
06233 enum machine_mode mode = GET_MODE (mem);
06234 enum insn_code icode;
06235 rtx insn;
06236
06237
06238 icode = sync_lock_test_and_set[mode];
06239 if (icode != CODE_FOR_nothing)
06240 {
06241 if (!target || !insn_data[icode].operand[0].predicate (target, mode))
06242 target = gen_reg_rtx (mode);
06243
06244 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
06245 val = convert_modes (mode, GET_MODE (val), val, 1);
06246 if (!insn_data[icode].operand[2].predicate (val, mode))
06247 val = force_reg (mode, val);
06248
06249 insn = GEN_FCN (icode) (target, mem, val);
06250 if (insn)
06251 {
06252 emit_insn (insn);
06253 return target;
06254 }
06255 }
06256
06257
06258 if (sync_compare_and_swap[mode] != CODE_FOR_nothing)
06259 {
06260 if (!target || !register_operand (target, mode))
06261 target = gen_reg_rtx (mode);
06262 if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
06263 val = convert_modes (mode, GET_MODE (val), val, 1);
06264 if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
06265 return target;
06266 }
06267
06268 return NULL_RTX;
06269 }
06270
06271 #include "gt-optabs.h"