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