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