#include "config.h"
#include "system.h"
+#include "toplev.h"
/* Include insn-config.h before expr.h so that HAVE_conditional_move
is properly defined. */
#include "insn-config.h"
#include "rtl.h"
#include "tree.h"
+#include "tm_p.h"
#include "flags.h"
#include "insn-flags.h"
#include "insn-codes.h"
+#include "function.h"
#include "expr.h"
#include "recog.h"
#include "reload.h"
+#include "ggc.h"
/* Each optab contains info on how this target machine
can perform a particular operation
See expr.h for documentation of these optabs. */
-optab add_optab;
-optab sub_optab;
-optab smul_optab;
-optab smul_highpart_optab;
-optab umul_highpart_optab;
-optab smul_widen_optab;
-optab umul_widen_optab;
-optab sdiv_optab;
-optab sdivmod_optab;
-optab udiv_optab;
-optab udivmod_optab;
-optab smod_optab;
-optab umod_optab;
-optab flodiv_optab;
-optab ftrunc_optab;
-optab and_optab;
-optab ior_optab;
-optab xor_optab;
-optab ashl_optab;
-optab lshr_optab;
-optab ashr_optab;
-optab rotl_optab;
-optab rotr_optab;
-optab smin_optab;
-optab smax_optab;
-optab umin_optab;
-optab umax_optab;
-
-optab mov_optab;
-optab movstrict_optab;
-
-optab neg_optab;
-optab abs_optab;
-optab one_cmpl_optab;
-optab ffs_optab;
-optab sqrt_optab;
-optab sin_optab;
-optab cos_optab;
-
-optab cmp_optab;
-optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
-optab tst_optab;
-
-optab strlen_optab;
+optab optab_table[OTI_MAX];
+
+rtx libfunc_table[LTI_MAX];
/* Tables of patterns for extending one integer mode to another. */
enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
/* Contains the optab used for each rtx code. */
optab code_to_optab[NUM_RTX_CODE + 1];
-/* SYMBOL_REF rtx's for the library functions that are called
- implicitly and not via optabs. */
-
-rtx extendsfdf2_libfunc;
-rtx extendsfxf2_libfunc;
-rtx extendsftf2_libfunc;
-rtx extenddfxf2_libfunc;
-rtx extenddftf2_libfunc;
-
-rtx truncdfsf2_libfunc;
-rtx truncxfsf2_libfunc;
-rtx trunctfsf2_libfunc;
-rtx truncxfdf2_libfunc;
-rtx trunctfdf2_libfunc;
-
-rtx memcpy_libfunc;
-rtx bcopy_libfunc;
-rtx memcmp_libfunc;
-rtx bcmp_libfunc;
-rtx memset_libfunc;
-rtx bzero_libfunc;
-
-rtx throw_libfunc;
-rtx rethrow_libfunc;
-rtx sjthrow_libfunc;
-rtx sjpopnthrow_libfunc;
-rtx terminate_libfunc;
-rtx setjmp_libfunc;
-rtx longjmp_libfunc;
-rtx eh_rtime_match_libfunc;
-
-rtx eqhf2_libfunc;
-rtx nehf2_libfunc;
-rtx gthf2_libfunc;
-rtx gehf2_libfunc;
-rtx lthf2_libfunc;
-rtx lehf2_libfunc;
-
-rtx eqsf2_libfunc;
-rtx nesf2_libfunc;
-rtx gtsf2_libfunc;
-rtx gesf2_libfunc;
-rtx ltsf2_libfunc;
-rtx lesf2_libfunc;
-
-rtx eqdf2_libfunc;
-rtx nedf2_libfunc;
-rtx gtdf2_libfunc;
-rtx gedf2_libfunc;
-rtx ltdf2_libfunc;
-rtx ledf2_libfunc;
-
-rtx eqxf2_libfunc;
-rtx nexf2_libfunc;
-rtx gtxf2_libfunc;
-rtx gexf2_libfunc;
-rtx ltxf2_libfunc;
-rtx lexf2_libfunc;
-
-rtx eqtf2_libfunc;
-rtx netf2_libfunc;
-rtx gttf2_libfunc;
-rtx getf2_libfunc;
-rtx lttf2_libfunc;
-rtx letf2_libfunc;
-
-rtx floatsisf_libfunc;
-rtx floatdisf_libfunc;
-rtx floattisf_libfunc;
-
-rtx floatsidf_libfunc;
-rtx floatdidf_libfunc;
-rtx floattidf_libfunc;
-
-rtx floatsixf_libfunc;
-rtx floatdixf_libfunc;
-rtx floattixf_libfunc;
-
-rtx floatsitf_libfunc;
-rtx floatditf_libfunc;
-rtx floattitf_libfunc;
-
-rtx fixsfsi_libfunc;
-rtx fixsfdi_libfunc;
-rtx fixsfti_libfunc;
-
-rtx fixdfsi_libfunc;
-rtx fixdfdi_libfunc;
-rtx fixdfti_libfunc;
-
-rtx fixxfsi_libfunc;
-rtx fixxfdi_libfunc;
-rtx fixxfti_libfunc;
-
-rtx fixtfsi_libfunc;
-rtx fixtfdi_libfunc;
-rtx fixtfti_libfunc;
-
-rtx fixunssfsi_libfunc;
-rtx fixunssfdi_libfunc;
-rtx fixunssfti_libfunc;
-
-rtx fixunsdfsi_libfunc;
-rtx fixunsdfdi_libfunc;
-rtx fixunsdfti_libfunc;
-
-rtx fixunsxfsi_libfunc;
-rtx fixunsxfdi_libfunc;
-rtx fixunsxfti_libfunc;
-
-rtx fixunstfsi_libfunc;
-rtx fixunstfdi_libfunc;
-rtx fixunstfti_libfunc;
-
-rtx chkr_check_addr_libfunc;
-rtx chkr_set_right_libfunc;
-rtx chkr_copy_bitmap_libfunc;
-rtx chkr_check_exec_libfunc;
-rtx chkr_check_str_libfunc;
-
-rtx profile_function_entry_libfunc;
-rtx profile_function_exit_libfunc;
-
/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
gives the gen_function to make a branch to test that condition. */
static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
static rtx widen_operand PROTO((rtx, enum machine_mode,
enum machine_mode, int, int));
+static int expand_cmplxdiv_straight PROTO((rtx, rtx, rtx, rtx,
+ rtx, rtx, enum machine_mode,
+ int, enum optab_methods,
+ enum mode_class, optab));
+static int expand_cmplxdiv_wide PROTO((rtx, rtx, rtx, rtx,
+ rtx, rtx, enum machine_mode,
+ int, enum optab_methods,
+ enum mode_class, optab));
static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode,
int, int *));
static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode,
#ifdef HAVE_conditional_trap
static void init_traps PROTO((void));
#endif
+static void emit_cmp_and_jump_insn_1 PROTO((rtx, rtx, enum machine_mode,
+ enum rtx_code, int, rtx));
+static void prepare_float_lib_cmp PROTO((rtx *, rtx *, enum rtx_code *,
+ enum machine_mode *, int *));
\f
/* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
the result of operation CODE applied to OP0 (and OP1 if it is a binary
return result;
}
\f
+/* Generate code to perform a straightforward complex divide. */
+
+static int
+expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
+ unsignedp, methods, class, binoptab)
+ rtx real0, real1, imag0, imag1, realr, imagr;
+ enum machine_mode submode;
+ int unsignedp;
+ enum optab_methods methods;
+ enum mode_class class;
+ optab binoptab;
+{
+ rtx divisor;
+ rtx real_t, imag_t;
+ rtx temp1, temp2;
+ rtx res;
+
+ /* Don't fetch these from memory more than once. */
+ real0 = force_reg (submode, real0);
+ real1 = force_reg (submode, real1);
+
+ if (imag0 != 0)
+ imag0 = force_reg (submode, imag0);
+
+ imag1 = force_reg (submode, imag1);
+
+ /* Divisor: c*c + d*d. */
+ temp1 = expand_binop (submode, smul_optab, real1, real1,
+ NULL_RTX, unsignedp, methods);
+
+ temp2 = expand_binop (submode, smul_optab, imag1, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ divisor = expand_binop (submode, add_optab, temp1, temp2,
+ NULL_RTX, unsignedp, methods);
+ if (divisor == 0)
+ return 0;
+
+ if (imag0 == 0)
+ {
+ /* Mathematically, ((a)(c-id))/divisor. */
+ /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
+
+ /* Calculate the dividend. */
+ real_t = expand_binop (submode, smul_optab, real0, real1,
+ NULL_RTX, unsignedp, methods);
+
+ imag_t = expand_binop (submode, smul_optab, real0, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+
+ imag_t = expand_unop (submode, neg_optab, imag_t,
+ NULL_RTX, unsignedp);
+ }
+ else
+ {
+ /* Mathematically, ((a+ib)(c-id))/divider. */
+ /* Calculate the dividend. */
+ temp1 = expand_binop (submode, smul_optab, real0, real1,
+ NULL_RTX, unsignedp, methods);
+
+ temp2 = expand_binop (submode, smul_optab, imag0, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ real_t = expand_binop (submode, add_optab, temp1, temp2,
+ NULL_RTX, unsignedp, methods);
+
+ temp1 = expand_binop (submode, smul_optab, imag0, real1,
+ NULL_RTX, unsignedp, methods);
+
+ temp2 = expand_binop (submode, smul_optab, real0, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ imag_t = expand_binop (submode, sub_optab, temp1, temp2,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, real_t, divisor,
+ realr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real_t, divisor, realr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != realr)
+ emit_move_insn (realr, res);
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, imag_t, divisor,
+ imagr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag_t, divisor, imagr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != imagr)
+ emit_move_insn (imagr, res);
+
+ return 1;
+}
+\f
+/* Generate code to perform a wide-input-range-acceptable complex divide. */
+
+static int
+expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
+ unsignedp, methods, class, binoptab)
+ rtx real0, real1, imag0, imag1, realr, imagr;
+ enum machine_mode submode;
+ int unsignedp;
+ enum optab_methods methods;
+ enum mode_class class;
+ optab binoptab;
+{
+ rtx ratio, divisor;
+ rtx real_t, imag_t;
+ rtx temp1, temp2, lab1, lab2;
+ enum machine_mode mode;
+ int align;
+ rtx res;
+
+ /* Don't fetch these from memory more than once. */
+ real0 = force_reg (submode, real0);
+ real1 = force_reg (submode, real1);
+
+ if (imag0 != 0)
+ imag0 = force_reg (submode, imag0);
+
+ imag1 = force_reg (submode, imag1);
+
+ /* XXX What's an "unsigned" complex number? */
+ if (unsignedp)
+ {
+ temp1 = real1;
+ temp2 = imag1;
+ }
+ else
+ {
+ temp1 = expand_abs (submode, real1, NULL_RTX, 1);
+ temp2 = expand_abs (submode, imag1, NULL_RTX, 1);
+ }
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ mode = GET_MODE (temp1);
+ align = GET_MODE_ALIGNMENT (mode);
+ lab1 = gen_label_rtx ();
+ emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
+ mode, unsignedp, align, lab1);
+
+ /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
+
+ if (class == MODE_COMPLEX_FLOAT)
+ ratio = expand_binop (submode, binoptab, imag1, real1,
+ NULL_RTX, unsignedp, methods);
+ else
+ ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag1, real1, NULL_RTX, unsignedp);
+
+ if (ratio == 0)
+ return 0;
+
+ /* Calculate divisor. */
+
+ temp1 = expand_binop (submode, smul_optab, imag1, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ divisor = expand_binop (submode, add_optab, temp1, real1,
+ NULL_RTX, unsignedp, methods);
+
+ if (divisor == 0)
+ return 0;
+
+ /* Calculate dividend. */
+
+ if (imag0 == 0)
+ {
+ real_t = real0;
+
+ /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
+
+ imag_t = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (imag_t == 0)
+ return 0;
+
+ imag_t = expand_unop (submode, neg_optab, imag_t,
+ NULL_RTX, unsignedp);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+ else
+ {
+ /* Compute (a+ib)/(c+id) as
+ (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
+
+ temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ real_t = expand_binop (submode, add_optab, temp1, real0,
+ NULL_RTX, unsignedp, methods);
+
+ temp1 = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ imag_t = expand_binop (submode, sub_optab, imag0, temp1,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, real_t, divisor,
+ realr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real_t, divisor, realr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != realr)
+ emit_move_insn (realr, res);
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, imag_t, divisor,
+ imagr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag_t, divisor, imagr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != imagr)
+ emit_move_insn (imagr, res);
+
+ lab2 = gen_label_rtx ();
+ emit_jump_insn (gen_jump (lab2));
+ emit_barrier ();
+
+ emit_label (lab1);
+
+ /* |d| > |c|; use ratio c/d to scale dividend and divisor. */
+
+ if (class == MODE_COMPLEX_FLOAT)
+ ratio = expand_binop (submode, binoptab, real1, imag1,
+ NULL_RTX, unsignedp, methods);
+ else
+ ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real1, imag1, NULL_RTX, unsignedp);
+
+ if (ratio == 0)
+ return 0;
+
+ /* Calculate divisor. */
+
+ temp1 = expand_binop (submode, smul_optab, real1, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ divisor = expand_binop (submode, add_optab, temp1, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (divisor == 0)
+ return 0;
+
+ /* Calculate dividend. */
+
+ if (imag0 == 0)
+ {
+ /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
+
+ real_t = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ imag_t = expand_unop (submode, neg_optab, real0,
+ NULL_RTX, unsignedp);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+ else
+ {
+ /* Compute (a+ib)/(c+id) as
+ (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
+
+ temp1 = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ real_t = expand_binop (submode, add_optab, temp1, imag0,
+ NULL_RTX, unsignedp, methods);
+
+ temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ imag_t = expand_binop (submode, sub_optab, temp1, real0,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, real_t, divisor,
+ realr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real_t, divisor, realr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != realr)
+ emit_move_insn (realr, res);
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, imag_t, divisor,
+ imagr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag_t, divisor, imagr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != imagr)
+ emit_move_insn (imagr, res);
+
+ emit_label (lab2);
+
+ return 1;
+}
+\f
/* Generate code to perform an operation specified by BINOPTAB
on operands OP0 and OP1, with result having machine-mode MODE.
&& binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
int icode = (int) binoptab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
- enum machine_mode mode1 = insn_operand_mode[icode][2];
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+ enum machine_mode mode1 = insn_data[icode].operand[2].mode;
rtx pat;
rtx xop0 = op0, xop1 = op1;
/* Now, if insn's predicates don't allow our operands, put them into
pseudo regs. */
- if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)
+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0)
&& mode0 != VOIDmode)
xop0 = copy_to_mode_reg (mode0, xop0);
- if (! (*insn_operand_predicate[icode][2]) (xop1, mode1)
+ if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1)
&& mode1 != VOIDmode)
xop1 = copy_to_mode_reg (mode1, xop1);
- if (! (*insn_operand_predicate[icode][0]) (temp, mode))
+ if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
temp = gen_reg_rtx (mode);
pat = GEN_FCN (icode) (temp, xop0, xop1);
rtx carry_tmp = gen_reg_rtx (word_mode);
optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
- rtx carry_in, carry_out;
+ rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
rtx xop0, xop1;
/* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
carry_out = gen_reg_rtx (word_mode);
carry_out = emit_store_flag_force (carry_out,
(binoptab == add_optab
- ? LTU : GTU),
+ ? LT : GT),
x, op0_piece,
word_mode, 1, normalizep);
}
/* Get out carry from adding/subtracting carry in. */
carry_tmp = emit_store_flag_force (carry_tmp,
binoptab == add_optab
- ? LTU : GTU,
+ ? LT : GT,
x, carry_in,
word_mode, 1, normalizep);
copy_rtx (xop0),
copy_rtx (xop1)));
}
+
return target;
}
+
else
delete_insns_since (last);
}
rtx op1_high = operand_subword_force (op1, high, mode);
rtx op1_low = operand_subword_force (op1, low, mode);
rtx product = 0;
- rtx op0_xhigh;
- rtx op1_xhigh;
+ rtx op0_xhigh = NULL_RTX;
+ rtx op1_xhigh = NULL_RTX;
/* If the target is the same as one of the inputs, don't use it. This
prevents problems with the REG_EQUAL note. */
copy_rtx (op0),
copy_rtx (op1)));
}
+
return product;
}
}
start_sequence ();
- realr = gen_realpart (submode, target);
+ realr = gen_realpart (submode, target);
imagr = gen_imagpart (submode, target);
if (GET_MODE (op0) == mode)
{
- real0 = gen_realpart (submode, op0);
+ real0 = gen_realpart (submode, op0);
imag0 = gen_imagpart (submode, op0);
}
else
if (GET_MODE (op1) == mode)
{
- real1 = gen_realpart (submode, op1);
+ real1 = gen_realpart (submode, op1);
imag1 = gen_imagpart (submode, op1);
}
else
}
else
{
- /* Divisor is of complex type:
- X/(a+ib) */
- rtx divisor;
- rtx real_t, imag_t;
- rtx temp1, temp2;
-
- /* Don't fetch these from memory more than once. */
- real0 = force_reg (submode, real0);
- real1 = force_reg (submode, real1);
-
- if (imag0 != 0)
- imag0 = force_reg (submode, imag0);
-
- imag1 = force_reg (submode, imag1);
-
- /* Divisor: c*c + d*d */
- temp1 = expand_binop (submode, smul_optab, real1, real1,
- NULL_RTX, unsignedp, methods);
-
- temp2 = expand_binop (submode, smul_optab, imag1, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (temp1 == 0 || temp2 == 0)
- break;
-
- divisor = expand_binop (submode, add_optab, temp1, temp2,
- NULL_RTX, unsignedp, methods);
- if (divisor == 0)
- break;
-
- if (imag0 == 0)
+ switch (flag_complex_divide_method)
{
- /* ((a)(c-id))/divisor */
- /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
-
- /* Calculate the dividend */
- real_t = expand_binop (submode, smul_optab, real0, real1,
- NULL_RTX, unsignedp, methods);
-
- imag_t = expand_binop (submode, smul_optab, real0, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (real_t == 0 || imag_t == 0)
- break;
-
- imag_t = expand_unop (submode, neg_optab, imag_t,
- NULL_RTX, unsignedp);
- }
- else
- {
- /* ((a+ib)(c-id))/divider */
- /* Calculate the dividend */
- temp1 = expand_binop (submode, smul_optab, real0, real1,
- NULL_RTX, unsignedp, methods);
-
- temp2 = expand_binop (submode, smul_optab, imag0, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (temp1 == 0 || temp2 == 0)
- break;
-
- real_t = expand_binop (submode, add_optab, temp1, temp2,
- NULL_RTX, unsignedp, methods);
-
- temp1 = expand_binop (submode, smul_optab, imag0, real1,
- NULL_RTX, unsignedp, methods);
-
- temp2 = expand_binop (submode, smul_optab, real0, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (temp1 == 0 || temp2 == 0)
- break;
+ case 0:
+ ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1,
+ realr, imagr, submode,
+ unsignedp, methods,
+ class, binoptab);
+ break;
- imag_t = expand_binop (submode, sub_optab, temp1, temp2,
- NULL_RTX, unsignedp, methods);
+ case 1:
+ ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1,
+ realr, imagr, submode,
+ unsignedp, methods,
+ class, binoptab);
+ break;
- if (real_t == 0 || imag_t == 0)
- break;
+ default:
+ abort ();
}
-
- if (class == MODE_COMPLEX_FLOAT)
- res = expand_binop (submode, binoptab, real_t, divisor,
- realr, unsignedp, methods);
- else
- res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
- real_t, divisor, realr, unsignedp);
-
- if (res == 0)
- break;
- else if (res != realr)
- emit_move_insn (realr, res);
-
- if (class == MODE_COMPLEX_FLOAT)
- res = expand_binop (submode, binoptab, imag_t, divisor,
- imagr, unsignedp, methods);
- else
- res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
- imag_t, divisor, imagr, unsignedp);
-
- if (res == 0)
- break;
- else if (res != imagr)
- emit_move_insn (imagr, res);
-
- ok = 1;
}
break;
if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
int icode = (int) binoptab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
- enum machine_mode mode1 = insn_operand_mode[icode][2];
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+ enum machine_mode mode1 = insn_data[icode].operand[2].mode;
rtx pat;
rtx xop0 = op0, xop1 = op1;
xop1 = convert_to_mode (mode1, xop1, unsignedp);
/* Now, if insn doesn't accept these operands, put them into pseudos. */
- if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
xop0 = copy_to_mode_reg (mode0, xop0);
- if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
+ if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1))
xop1 = copy_to_mode_reg (mode1, xop1);
/* We could handle this, but we should always be called with a pseudo
for our targets and all insns should take them as outputs. */
- if (! (*insn_operand_predicate[icode][0]) (targ0, mode)
- || ! (*insn_operand_predicate[icode][3]) (targ1, mode))
+ if (! (*insn_data[icode].operand[0].predicate) (targ0, mode)
+ || ! (*insn_data[icode].operand[3].predicate) (targ1, mode))
abort ();
pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
int icode = (int) unoptab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
rtx xop0 = op0;
if (target)
/* Now, if insn doesn't accept our operand, put it into a pseudo. */
- if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
xop0 = copy_to_mode_reg (mode0, xop0);
- if (! (*insn_operand_predicate[icode][0]) (temp, mode))
+ if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
temp = gen_reg_rtx (mode);
pat = GEN_FCN (icode) (temp, xop0);
if (temp != 0)
return temp;
+ /* If we have a MAX insn, we can do this as MAX (x, -x). */
+ if (smax_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ {
+ rtx last = get_last_insn ();
+
+ temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
+ if (temp != 0)
+ temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
+ OPTAB_WIDEN);
+
+ if (temp != 0)
+ return temp;
+
+ delete_insns_since (last);
+ }
+
/* If this machine has expensive jumps, we can do integer absolute
value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
- where W is the width of MODE. */
+ where W is the width of MODE. But don't do this if the machine has
+ conditional arithmetic since the branches will be converted into
+ a conditional negation insn. */
+#ifndef HAVE_conditional_arithmetic
if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
{
rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
if (temp != 0)
return temp;
}
+#endif
/* If that does not win, use conditional jump and negate. */
/* If this mode is an integer too wide to compare properly,
compare word by word. Rely on CSE to optimize constant cases. */
- if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode))
+ if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump))
do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx,
NULL_RTX, op1);
else
- {
- temp = compare_from_rtx (target, CONST0_RTX (mode), GE, 0, mode,
- NULL_RTX, 0);
- if (temp == const1_rtx)
- return target;
- else if (temp != const0_rtx)
- {
- if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0)
- emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op1));
- else
- abort ();
- }
- }
+ do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
+ NULL_RTX, 0, NULL_RTX, op1);
op0 = expand_unop (mode, neg_optab, target, target, 0);
if (op0 != target)
if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
int icode = (int) abs_optab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
rtx xop0 = op0;
if (target)
/* Now, if insn doesn't accept our operand, put it into a pseudo. */
- if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
xop0 = copy_to_mode_reg (mode0, xop0);
- if (! (*insn_operand_predicate[icode][0]) (temp, submode))
+ if (! (*insn_data[icode].operand[0].predicate) (temp, submode))
temp = gen_reg_rtx (submode);
pat = GEN_FCN (icode) (temp, xop0);
enum rtx_code code;
{
register rtx temp;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
rtx pat;
temp = target = protect_from_queue (target, 1);
/* Now, if insn does not accept our operands, put them into pseudos. */
- if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
op0 = copy_to_mode_reg (mode0, op0);
- if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
+ if (! (*insn_data[icode].operand[0].predicate) (temp, GET_MODE (temp))
|| (flag_force_mem && GET_CODE (temp) == MEM))
temp = gen_reg_rtx (GET_MODE (temp));
next = NEXT_INSN (insn);
- if (GET_CODE (PATTERN (insn)) == SET)
+ if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == USE
+ || GET_CODE (PATTERN (insn)) == CLOBBER)
set = PATTERN (insn);
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
{
rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
if (note == NULL_RTX)
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (0),
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
REG_NOTES (insn));
}
}
emit_move_insn (x, const1_rtx);
}
-/* Generate code to compare X with Y
- so that the condition codes are set.
+/* Nonzero if we can perform a comparison of mode MODE straightforwardly.
+ If FOR_JUMP is nonzero, we will be generating a jump based on this
+ comparison, otherwise a store-flags operation. */
+
+int
+can_compare_p (mode, purpose)
+ enum machine_mode mode;
+ enum can_compare_purpose purpose;
+{
+ do
+ {
+ if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ return 1;
+ if (purpose == ccp_jump
+ && cbranch_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ return 1;
+ if (purpose == ccp_cmov
+ && cmov_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ return 1;
+ if (purpose == ccp_store_flag
+ && cstore_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ return 1;
- MODE is the mode of the inputs (in case they are const_int).
- UNSIGNEDP nonzero says that X and Y are unsigned;
+ mode = GET_MODE_WIDER_MODE (mode);
+ }
+ while (mode != VOIDmode);
+
+ return 0;
+}
+
+/* This function is called when we are going to emit a compare instruction that
+ compares the values found in *PX and *PY, using the rtl operator COMPARISON.
+
+ *PMODE is the mode of the inputs (in case they are const_int).
+ *PUNSIGNEDP nonzero says that the operands are unsigned;
this matters if they need to be widened.
- If they have mode BLKmode, then SIZE specifies the size of both X and Y,
- and ALIGN specifies the known shared alignment of X and Y.
+ If they have mode BLKmode, then SIZE specifies the size of both operands,
+ and ALIGN specifies the known shared alignment of the operands.
- COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
- It is ignored for fixed-point and block comparisons;
- it is used only for floating-point comparisons. */
+ This function performs all the setup necessary so that the caller only has
+ to emit a single comparison insn. This setup can involve doing a BLKmode
+ comparison or emitting a library call to perform the comparison if no insn
+ is available to handle it.
+ The values which are passed in through pointers can be modified; the caller
+ should perform the comparison on the modified values. */
void
-emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
- rtx x, y;
- enum rtx_code comparison;
+prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align,
+ purpose)
+ rtx *px, *py;
+ enum rtx_code *pcomparison;
rtx size;
- enum machine_mode mode;
- int unsignedp;
+ enum machine_mode *pmode;
+ int *punsignedp;
int align;
+ enum can_compare_purpose purpose;
{
+ enum machine_mode mode = *pmode;
+ rtx x = *px, y = *py;
+ int unsignedp = *punsignedp;
enum mode_class class;
- enum machine_mode wider_mode;
class = GET_MODE_CLASS (mode);
if (mode == BLKmode)
{
+ rtx result;
+ enum machine_mode result_mode;
+
emit_queue ();
x = protect_from_queue (x, 0);
y = protect_from_queue (y, 0);
&& GET_CODE (size) == CONST_INT
&& INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
{
- enum machine_mode result_mode
- = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
- rtx result = gen_reg_rtx (result_mode);
+ result_mode = insn_data[(int) CODE_FOR_cmpstrqi].operand[0].mode;
+ result = gen_reg_rtx (result_mode);
emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align)));
- emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
- result_mode, 0, 0);
}
else
#endif
&& GET_CODE (size) == CONST_INT
&& INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
{
- enum machine_mode result_mode
- = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
- rtx result = gen_reg_rtx (result_mode);
+ result_mode = insn_data[(int) CODE_FOR_cmpstrhi].operand[0].mode;
+ result = gen_reg_rtx (result_mode);
emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align)));
- emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
- result_mode, 0, 0);
}
else
#endif
#ifdef HAVE_cmpstrsi
if (HAVE_cmpstrsi)
{
- enum machine_mode result_mode
- = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
- rtx result = gen_reg_rtx (result_mode);
+ result_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
+ result = gen_reg_rtx (result_mode);
size = protect_from_queue (size, 0);
emit_insn (gen_cmpstrsi (result, x, y,
convert_to_mode (SImode, size, 1),
GEN_INT (align)));
- emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX,
- result_mode, 0, 0);
}
else
#endif
{
- rtx result;
-
#ifdef TARGET_MEM_FUNCTIONS
emit_library_call (memcmp_libfunc, 0,
TYPE_MODE (integer_type_node), 3,
register so reload doesn't clobber the value if it needs
the return register for a spill reg. */
result = gen_reg_rtx (TYPE_MODE (integer_type_node));
+ result_mode = TYPE_MODE (integer_type_node);
emit_move_insn (result,
- hard_libcall_value (TYPE_MODE (integer_type_node)));
- emit_cmp_insn (result,
- const0_rtx, comparison, NULL_RTX,
- TYPE_MODE (integer_type_node), 0, 0);
+ hard_libcall_value (result_mode));
}
+ *px = result;
+ *py = const0_rtx;
+ *pmode = result_mode;
return;
}
- /* Handle some compares against zero. */
-
- if (y == CONST0_RTX (mode)
- && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- int icode = (int) tst_optab->handlers[(int) mode].insn_code;
-
- emit_queue ();
- x = protect_from_queue (x, 0);
- y = protect_from_queue (y, 0);
-
- /* Now, if insn does accept these operands, put them into pseudos. */
- if (! (*insn_operand_predicate[icode][0])
- (x, insn_operand_mode[icode][0]))
- x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
-
- emit_insn (GEN_FCN (icode) (x));
- return;
- }
-
- /* Handle compares for which there is a directly suitable insn. */
-
- if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
-
- emit_queue ();
- x = protect_from_queue (x, 0);
- y = protect_from_queue (y, 0);
-
- /* Now, if insn doesn't accept these operands, put them into pseudos. */
- if (! (*insn_operand_predicate[icode][0])
- (x, insn_operand_mode[icode][0]))
- x = copy_to_mode_reg (insn_operand_mode[icode][0], x);
-
- if (! (*insn_operand_predicate[icode][1])
- (y, insn_operand_mode[icode][1]))
- y = copy_to_mode_reg (insn_operand_mode[icode][1], y);
-
- emit_insn (GEN_FCN (icode) (x, y));
- return;
- }
-
- /* Try widening if we can find a direct insn that way. */
-
- if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
- {
- for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
- wider_mode = GET_MODE_WIDER_MODE (wider_mode))
- {
- if (cmp_optab->handlers[(int) wider_mode].insn_code
- != CODE_FOR_nothing)
- {
- x = protect_from_queue (x, 0);
- y = protect_from_queue (y, 0);
- x = convert_modes (wider_mode, mode, x, unsignedp);
- y = convert_modes (wider_mode, mode, y, unsignedp);
- emit_cmp_insn (x, y, comparison, NULL_RTX,
- wider_mode, unsignedp, align);
- return;
- }
- }
- }
+ *px = x;
+ *py = y;
+ if (can_compare_p (mode, purpose))
+ return;
/* Handle a lib call just for the mode we are using. */
- if (cmp_optab->handlers[(int) mode].libfunc
- && class != MODE_FLOAT)
+ if (cmp_optab->handlers[(int) mode].libfunc && class != MODE_FLOAT)
{
rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
rtx result;
/* Integer comparison returns a result that must be compared against 1,
so that even if we do an unsigned compare afterward,
there is still a value that can represent the result "less than". */
- emit_cmp_insn (result, const1_rtx,
- comparison, NULL_RTX, word_mode, unsignedp, 0);
+ *px = result;
+ *py = const1_rtx;
+ *pmode = word_mode;
return;
}
if (class == MODE_FLOAT)
- emit_float_lib_cmp (x, y, comparison);
+ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
else
abort ();
}
+/* Before emitting an insn with code ICODE, make sure that X, which is going
+ to be used for operand OPNUM of the insn, is converted from mode MODE to
+ WIDER_MODE (UNSIGNEDP determines whether it is a unsigned conversion), and
+ that it is accepted by the operand predicate. Return the new value. */
+rtx
+prepare_operand (icode, x, opnum, mode, wider_mode, unsignedp)
+ int icode;
+ rtx x;
+ int opnum;
+ enum machine_mode mode, wider_mode;
+ int unsignedp;
+{
+ x = protect_from_queue (x, 0);
+
+ if (mode != wider_mode)
+ x = convert_modes (wider_mode, mode, x, unsignedp);
+
+ if (! (*insn_data[icode].operand[opnum].predicate)
+ (x, insn_data[icode].operand[opnum].mode))
+ x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
+ return x;
+}
+
+/* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
+ we can do the comparison.
+ The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may
+ be NULL_RTX which indicates that only a comparison is to be generated. */
+
+static void
+emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label)
+ rtx x, y;
+ enum machine_mode mode;
+ enum rtx_code comparison;
+ int unsignedp;
+ rtx label;
+{
+ rtx test = gen_rtx_fmt_ee (comparison, mode, x, y);
+ enum mode_class class = GET_MODE_CLASS (mode);
+ enum machine_mode wider_mode = mode;
+
+ /* Try combined insns first. */
+ do
+ {
+ enum insn_code icode;
+ PUT_MODE (test, wider_mode);
+
+ if (label)
+ {
+ icode = cbranch_optab->handlers[(int)wider_mode].insn_code;
+
+ if (icode != CODE_FOR_nothing
+ && (*insn_data[icode].operand[0].predicate) (test, wider_mode))
+ {
+ x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp);
+ y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp);
+ emit_jump_insn (GEN_FCN (icode) (test, x, y, label));
+ return;
+ }
+ }
+
+ /* Handle some compares against zero. */
+ icode = (int) tst_optab->handlers[(int) wider_mode].insn_code;
+ if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
+ {
+ x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
+ emit_insn (GEN_FCN (icode) (x));
+ if (label)
+ emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
+ return;
+ }
+
+ /* Handle compares for which there is a directly suitable insn. */
+
+ icode = (int) cmp_optab->handlers[(int) wider_mode].insn_code;
+ if (icode != CODE_FOR_nothing)
+ {
+ x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
+ y = prepare_operand (icode, y, 1, mode, wider_mode, unsignedp);
+ emit_insn (GEN_FCN (icode) (x, y));
+ if (label)
+ emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
+ return;
+ }
+
+ if (class != MODE_INT && class != MODE_FLOAT
+ && class != MODE_COMPLEX_FLOAT)
+ break;
+
+ wider_mode = GET_MODE_WIDER_MODE (wider_mode);
+ } while (wider_mode != VOIDmode);
+
+ abort ();
+}
+
/* Generate code to compare X with Y so that the condition codes are
set and to jump to LABEL if the condition is true. If X is a
constant and Y is not a constant, then the comparison is swapped to
rtx op0;
rtx op1;
- if (CONSTANT_P (x))
+ if ((CONSTANT_P (x) && ! CONSTANT_P (y))
+ || (GET_CODE (x) == CONST_INT && GET_CODE (y) != CONST_INT))
{
/* Swap operands and condition to ensure canonical RTL. */
op0 = y;
op0 = x;
op1 = y;
}
- emit_cmp_insn (op0, op1, comparison, size, mode, unsignedp, align);
+#ifdef HAVE_cc0
+ /* If OP0 is still a constant, then both X and Y must be constants. Force
+ X into a register to avoid aborting in emit_cmp_insn due to non-canonical
+ RTL. */
+ if (CONSTANT_P (op0))
+ op0 = force_reg (mode, op0);
+#endif
+
+ emit_queue ();
if (unsignedp)
comparison = unsigned_condition (comparison);
- emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
+ prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, align,
+ ccp_jump);
+ emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
}
-
-/* Nonzero if a compare of mode MODE can be done straightforwardly
- (without splitting it into pieces). */
-
-int
-can_compare_p (mode)
+/* Like emit_cmp_and_jump_insns, but generate only the comparison. */
+void
+emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
+ rtx x, y;
+ enum rtx_code comparison;
+ rtx size;
enum machine_mode mode;
+ int unsignedp;
+ int align;
{
- do
- {
- if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
- return 1;
- mode = GET_MODE_WIDER_MODE (mode);
- } while (mode != VOIDmode);
-
- return 0;
+ emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, 0);
}
\f
/* Emit a library call comparison between floating point X and Y.
COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
-void
-emit_float_lib_cmp (x, y, comparison)
- rtx x, y;
- enum rtx_code comparison;
+static void
+prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
+ rtx *px, *py;
+ enum rtx_code *pcomparison;
+ enum machine_mode *pmode;
+ int *punsignedp;
{
+ enum rtx_code comparison = *pcomparison;
+ rtx x = *px, y = *py;
enum machine_mode mode = GET_MODE (x);
rtx libfunc = 0;
rtx result;
{
x = protect_from_queue (x, 0);
y = protect_from_queue (y, 0);
- x = convert_to_mode (wider_mode, x, 0);
- y = convert_to_mode (wider_mode, y, 0);
- emit_float_lib_cmp (x, y, comparison);
+ *px = convert_to_mode (wider_mode, x, 0);
+ *py = convert_to_mode (wider_mode, y, 0);
+ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
return;
}
}
the return register for a spill reg. */
result = gen_reg_rtx (word_mode);
emit_move_insn (result, hard_libcall_value (word_mode));
-
- emit_cmp_insn (result, const0_rtx, comparison,
- NULL_RTX, word_mode, 0, 0);
+ *px = result;
+ *py = const0_rtx;
+ *pmode = word_mode;
+#ifdef FLOAT_LIB_COMPARE_RETURNS_BOOL
+ if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
+ *pcomparison = NE;
+#endif
+ *punsignedp = 0;
}
\f
/* Generate code to indirectly jump to a location given in the rtx LOC. */
emit_indirect_jump (loc)
rtx loc;
{
- if (! ((*insn_operand_predicate[(int)CODE_FOR_indirect_jump][0])
+ if (! ((*insn_data[(int)CODE_FOR_indirect_jump].operand[0].predicate)
(loc, Pmode)))
loc = copy_to_mode_reg (Pmode, loc);
code = swap_condition (code);
}
+ /* get_condition will prefer to generate LT and GT even if the old
+ comparison was against zero, so undo that canonicalization here since
+ comparisons against zero are cheaper. */
+ if (code == LT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == 1)
+ code = LE, op1 = const0_rtx;
+ else if (code == GT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == -1)
+ code = GE, op1 = const0_rtx;
+
if (cmode == VOIDmode)
cmode = GET_MODE (op0);
/* If the insn doesn't accept these operands, put them in pseudos. */
- if (! (*insn_operand_predicate[icode][0])
- (subtarget, insn_operand_mode[icode][0]))
- subtarget = gen_reg_rtx (insn_operand_mode[icode][0]);
+ if (! (*insn_data[icode].operand[0].predicate)
+ (subtarget, insn_data[icode].operand[0].mode))
+ subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
- if (! (*insn_operand_predicate[icode][2])
- (op2, insn_operand_mode[icode][2]))
- op2 = copy_to_mode_reg (insn_operand_mode[icode][2], op2);
+ if (! (*insn_data[icode].operand[2].predicate)
+ (op2, insn_data[icode].operand[2].mode))
+ op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
- if (! (*insn_operand_predicate[icode][3])
- (op3, insn_operand_mode[icode][3]))
- op3 = copy_to_mode_reg (insn_operand_mode[icode][3], op3);
+ if (! (*insn_data[icode].operand[3].predicate)
+ (op3, insn_data[icode].operand[3].mode))
+ op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
/* Everything should now be in the suitable form, so emit the compare insn
and then the conditional move. */
{
int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
- if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
- || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
- || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
+ if (! ((*insn_data[icode].operand[0].predicate)
+ (x, insn_data[icode].operand[0].mode))
+ || ! ((*insn_data[icode].operand[1].predicate)
+ (x, insn_data[icode].operand[1].mode))
+ || ! ((*insn_data[icode].operand[2].predicate)
+ (y, insn_data[icode].operand[2].mode)))
abort ();
return (GEN_FCN (icode) (x, x, y));
{
int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
- if (! (*insn_operand_predicate[icode][0]) (x, insn_operand_mode[icode][0])
- || ! (*insn_operand_predicate[icode][1]) (x, insn_operand_mode[icode][1])
- || ! (*insn_operand_predicate[icode][2]) (y, insn_operand_mode[icode][2]))
+ if (! ((*insn_data[icode].operand[0].predicate)
+ (x, insn_data[icode].operand[0].mode))
+ || ! ((*insn_data[icode].operand[1].predicate)
+ (x, insn_data[icode].operand[1].mode))
+ || ! ((*insn_data[icode].operand[2].predicate)
+ (y, insn_data[icode].operand[2].mode)))
abort ();
return (GEN_FCN (icode) (x, x, y));
do_pending_stack_adjust ();
/* Test whether the sign bit is set. */
- emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0);
- emit_jump_insn (gen_blt (neglabel));
+ emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
+ 0, 0, neglabel);
/* The sign bit is not set. Convert as signed. */
expand_float (target, from, 0);
GET_MODE (to),
copy_rtx (from)));
}
+
return;
}
#endif
for (mode = first_mode; (int) mode <= (int) last_mode;
mode = (enum machine_mode) ((int) mode + 1))
{
- register char *mname = mode_name[(int) mode];
+ register const char *mname = GET_MODE_NAME(mode);
register unsigned mname_len = strlen (mname);
register char *libfunc_name
- = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
+ = ggc_alloc_string (NULL, 2 + opname_len + mname_len + 1 + 1);
register char *p;
register const char *q;
for (q = opname; *q; )
*p++ = *q++;
for (q = mname; *q; q++)
- *p++ = tolower ((unsigned char)*q);
+ *p++ = TOLOWER (*q);
*p++ = suffix;
*p++ = '\0';
+
optable->handlers[(int) mode].libfunc
= gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
}
init_libfuncs (optable, SFmode, TFmode, opname, suffix);
}
+rtx
+init_one_libfunc (name)
+ register const char *name;
+{
+ if (ggc_p)
+ name = ggc_alloc_string (name, -1);
+ return gen_rtx_SYMBOL_REF (Pmode, name);
+}
+
+/* Mark ARG (which is really an OPTAB *) for GC. */
+
+void
+mark_optab (arg)
+ void *arg;
+{
+ optab o = *(optab *) arg;
+ int i;
+
+ for (i = 0; i < NUM_MACHINE_MODES; ++i)
+ ggc_mark_rtx (o->handlers[i].libfunc);
+}
/* Call this once to initialize the contents of the optabs
appropriately for the current target machine. */
sin_optab = init_optab (UNKNOWN);
cos_optab = init_optab (UNKNOWN);
strlen_optab = init_optab (UNKNOWN);
+ cbranch_optab = init_optab (UNKNOWN);
+ cmov_optab = init_optab (UNKNOWN);
+ cstore_optab = init_optab (UNKNOWN);
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
#endif
-#ifdef EXTRA_CC_MODES
- init_mov_optab ();
-#endif
-
/* Initialize the optabs with the names of the library functions. */
init_integral_libfuncs (add_optab, "add", '3');
init_floating_libfuncs (add_optab, "add", '3');
#ifdef MULSI3_LIBCALL
smul_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, MULSI3_LIBCALL);
+ = init_one_libfunc (MULSI3_LIBCALL);
#endif
#ifdef MULDI3_LIBCALL
smul_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, MULDI3_LIBCALL);
+ = init_one_libfunc (MULDI3_LIBCALL);
#endif
#ifdef DIVSI3_LIBCALL
sdiv_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, DIVSI3_LIBCALL);
+ = init_one_libfunc (DIVSI3_LIBCALL);
#endif
#ifdef DIVDI3_LIBCALL
sdiv_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, DIVDI3_LIBCALL);
+ = init_one_libfunc (DIVDI3_LIBCALL);
#endif
#ifdef UDIVSI3_LIBCALL
udiv_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, UDIVSI3_LIBCALL);
+ = init_one_libfunc (UDIVSI3_LIBCALL);
#endif
#ifdef UDIVDI3_LIBCALL
udiv_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, UDIVDI3_LIBCALL);
+ = init_one_libfunc (UDIVDI3_LIBCALL);
#endif
#ifdef MODSI3_LIBCALL
smod_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, MODSI3_LIBCALL);
+ = init_one_libfunc (MODSI3_LIBCALL);
#endif
#ifdef MODDI3_LIBCALL
smod_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, MODDI3_LIBCALL);
+ = init_one_libfunc (MODDI3_LIBCALL);
#endif
#ifdef UMODSI3_LIBCALL
umod_optab->handlers[(int) SImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, UMODSI3_LIBCALL);
+ = init_one_libfunc (UMODSI3_LIBCALL);
#endif
#ifdef UMODDI3_LIBCALL
umod_optab->handlers[(int) DImode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, UMODDI3_LIBCALL);
+ = init_one_libfunc (UMODDI3_LIBCALL);
#endif
/* Use cabs for DC complex abs, since systems generally have cabs.
Don't define any libcall for SCmode, so that cabs will be used. */
abs_optab->handlers[(int) DCmode].libfunc
- = gen_rtx_SYMBOL_REF (Pmode, "cabs");
+ = init_one_libfunc ("cabs");
/* The ffs function operates on `int'. */
#ifndef INT_TYPE_SIZE
#define INT_TYPE_SIZE BITS_PER_WORD
#endif
- ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)] .libfunc
- = gen_rtx_SYMBOL_REF (Pmode, "ffs");
-
- extendsfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfdf2");
- extendsfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsfxf2");
- extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extendsftf2");
- extenddfxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddfxf2");
- extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__extenddftf2");
-
- truncdfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncdfsf2");
- truncxfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfsf2");
- trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfsf2");
- truncxfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__truncxfdf2");
- trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__trunctfdf2");
-
- memcpy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcpy");
- bcopy_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bcopy");
- memcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memcmp");
- bcmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gcc_bcmp");
- memset_libfunc = gen_rtx_SYMBOL_REF (Pmode, "memset");
- bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero");
-
- throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw");
- rethrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__rethrow");
- sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow");
- sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow");
- terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate");
- eh_rtime_match_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match");
+ ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc
+ = init_one_libfunc ("ffs");
+
+ extendsfdf2_libfunc = init_one_libfunc ("__extendsfdf2");
+ extendsfxf2_libfunc = init_one_libfunc ("__extendsfxf2");
+ extendsftf2_libfunc = init_one_libfunc ("__extendsftf2");
+ extenddfxf2_libfunc = init_one_libfunc ("__extenddfxf2");
+ extenddftf2_libfunc = init_one_libfunc ("__extenddftf2");
+
+ truncdfsf2_libfunc = init_one_libfunc ("__truncdfsf2");
+ truncxfsf2_libfunc = init_one_libfunc ("__truncxfsf2");
+ trunctfsf2_libfunc = init_one_libfunc ("__trunctfsf2");
+ truncxfdf2_libfunc = init_one_libfunc ("__truncxfdf2");
+ trunctfdf2_libfunc = init_one_libfunc ("__trunctfdf2");
+
+ memcpy_libfunc = init_one_libfunc ("memcpy");
+ bcopy_libfunc = init_one_libfunc ("bcopy");
+ memcmp_libfunc = init_one_libfunc ("memcmp");
+ bcmp_libfunc = init_one_libfunc ("__gcc_bcmp");
+ memset_libfunc = init_one_libfunc ("memset");
+ bzero_libfunc = init_one_libfunc ("bzero");
+
+ throw_libfunc = init_one_libfunc ("__throw");
+ rethrow_libfunc = init_one_libfunc ("__rethrow");
+ sjthrow_libfunc = init_one_libfunc ("__sjthrow");
+ sjpopnthrow_libfunc = init_one_libfunc ("__sjpopnthrow");
+ terminate_libfunc = init_one_libfunc ("__terminate");
+ eh_rtime_match_libfunc = init_one_libfunc ("__eh_rtime_match");
#ifndef DONT_USE_BUILTIN_SETJMP
- setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_setjmp");
- longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_longjmp");
+ setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
+ longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
#else
- setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "setjmp");
- longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "longjmp");
+ setjmp_libfunc = init_one_libfunc ("setjmp");
+ longjmp_libfunc = init_one_libfunc ("longjmp");
#endif
- eqhf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqhf2");
- nehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nehf2");
- gthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gthf2");
- gehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gehf2");
- lthf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lthf2");
- lehf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lehf2");
-
- eqsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqsf2");
- nesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nesf2");
- gtsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtsf2");
- gesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gesf2");
- ltsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltsf2");
- lesf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lesf2");
-
- eqdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqdf2");
- nedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nedf2");
- gtdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtdf2");
- gedf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gedf2");
- ltdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltdf2");
- ledf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ledf2");
-
- eqxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqxf2");
- nexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__nexf2");
- gtxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gtxf2");
- gexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gexf2");
- ltxf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ltxf2");
- lexf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lexf2");
-
- eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eqtf2");
- netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__netf2");
- gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__gttf2");
- getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__getf2");
- lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__lttf2");
- letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__letf2");
-
- floatsisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsisf");
- floatdisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdisf");
- floattisf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattisf");
-
- floatsidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsidf");
- floatdidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdidf");
- floattidf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattidf");
-
- floatsixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsixf");
- floatdixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatdixf");
- floattixf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattixf");
-
- floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatsitf");
- floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floatditf");
- floattitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__floattitf");
-
- fixsfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfsi");
- fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfdi");
- fixsfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixsfti");
-
- fixdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfsi");
- fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfdi");
- fixdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixdfti");
-
- fixxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfsi");
- fixxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfdi");
- fixxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixxfti");
-
- fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfsi");
- fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfdi");
- fixtfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixtfti");
-
- fixunssfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfsi");
- fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfdi");
- fixunssfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunssfti");
-
- fixunsdfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfsi");
- fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfdi");
- fixunsdfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsdfti");
-
- fixunsxfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfsi");
- fixunsxfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfdi");
- fixunsxfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunsxfti");
-
- fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfsi");
- fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfdi");
- fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti");
+ eqhf2_libfunc = init_one_libfunc ("__eqhf2");
+ nehf2_libfunc = init_one_libfunc ("__nehf2");
+ gthf2_libfunc = init_one_libfunc ("__gthf2");
+ gehf2_libfunc = init_one_libfunc ("__gehf2");
+ lthf2_libfunc = init_one_libfunc ("__lthf2");
+ lehf2_libfunc = init_one_libfunc ("__lehf2");
+
+ eqsf2_libfunc = init_one_libfunc ("__eqsf2");
+ nesf2_libfunc = init_one_libfunc ("__nesf2");
+ gtsf2_libfunc = init_one_libfunc ("__gtsf2");
+ gesf2_libfunc = init_one_libfunc ("__gesf2");
+ ltsf2_libfunc = init_one_libfunc ("__ltsf2");
+ lesf2_libfunc = init_one_libfunc ("__lesf2");
+
+ eqdf2_libfunc = init_one_libfunc ("__eqdf2");
+ nedf2_libfunc = init_one_libfunc ("__nedf2");
+ gtdf2_libfunc = init_one_libfunc ("__gtdf2");
+ gedf2_libfunc = init_one_libfunc ("__gedf2");
+ ltdf2_libfunc = init_one_libfunc ("__ltdf2");
+ ledf2_libfunc = init_one_libfunc ("__ledf2");
+
+ eqxf2_libfunc = init_one_libfunc ("__eqxf2");
+ nexf2_libfunc = init_one_libfunc ("__nexf2");
+ gtxf2_libfunc = init_one_libfunc ("__gtxf2");
+ gexf2_libfunc = init_one_libfunc ("__gexf2");
+ ltxf2_libfunc = init_one_libfunc ("__ltxf2");
+ lexf2_libfunc = init_one_libfunc ("__lexf2");
+
+ eqtf2_libfunc = init_one_libfunc ("__eqtf2");
+ netf2_libfunc = init_one_libfunc ("__netf2");
+ gttf2_libfunc = init_one_libfunc ("__gttf2");
+ getf2_libfunc = init_one_libfunc ("__getf2");
+ lttf2_libfunc = init_one_libfunc ("__lttf2");
+ letf2_libfunc = init_one_libfunc ("__letf2");
+
+ floatsisf_libfunc = init_one_libfunc ("__floatsisf");
+ floatdisf_libfunc = init_one_libfunc ("__floatdisf");
+ floattisf_libfunc = init_one_libfunc ("__floattisf");
+
+ floatsidf_libfunc = init_one_libfunc ("__floatsidf");
+ floatdidf_libfunc = init_one_libfunc ("__floatdidf");
+ floattidf_libfunc = init_one_libfunc ("__floattidf");
+
+ floatsixf_libfunc = init_one_libfunc ("__floatsixf");
+ floatdixf_libfunc = init_one_libfunc ("__floatdixf");
+ floattixf_libfunc = init_one_libfunc ("__floattixf");
+
+ floatsitf_libfunc = init_one_libfunc ("__floatsitf");
+ floatditf_libfunc = init_one_libfunc ("__floatditf");
+ floattitf_libfunc = init_one_libfunc ("__floattitf");
+
+ fixsfsi_libfunc = init_one_libfunc ("__fixsfsi");
+ fixsfdi_libfunc = init_one_libfunc ("__fixsfdi");
+ fixsfti_libfunc = init_one_libfunc ("__fixsfti");
+
+ fixdfsi_libfunc = init_one_libfunc ("__fixdfsi");
+ fixdfdi_libfunc = init_one_libfunc ("__fixdfdi");
+ fixdfti_libfunc = init_one_libfunc ("__fixdfti");
+
+ fixxfsi_libfunc = init_one_libfunc ("__fixxfsi");
+ fixxfdi_libfunc = init_one_libfunc ("__fixxfdi");
+ fixxfti_libfunc = init_one_libfunc ("__fixxfti");
+
+ fixtfsi_libfunc = init_one_libfunc ("__fixtfsi");
+ fixtfdi_libfunc = init_one_libfunc ("__fixtfdi");
+ fixtfti_libfunc = init_one_libfunc ("__fixtfti");
+
+ fixunssfsi_libfunc = init_one_libfunc ("__fixunssfsi");
+ fixunssfdi_libfunc = init_one_libfunc ("__fixunssfdi");
+ fixunssfti_libfunc = init_one_libfunc ("__fixunssfti");
+
+ fixunsdfsi_libfunc = init_one_libfunc ("__fixunsdfsi");
+ fixunsdfdi_libfunc = init_one_libfunc ("__fixunsdfdi");
+ fixunsdfti_libfunc = init_one_libfunc ("__fixunsdfti");
+
+ fixunsxfsi_libfunc = init_one_libfunc ("__fixunsxfsi");
+ fixunsxfdi_libfunc = init_one_libfunc ("__fixunsxfdi");
+ fixunsxfti_libfunc = init_one_libfunc ("__fixunsxfti");
+
+ fixunstfsi_libfunc = init_one_libfunc ("__fixunstfsi");
+ fixunstfdi_libfunc = init_one_libfunc ("__fixunstfdi");
+ fixunstfti_libfunc = init_one_libfunc ("__fixunstfti");
/* For check-memory-usage. */
- chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr");
- chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right");
- chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap");
- chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec");
- chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str");
+ chkr_check_addr_libfunc = init_one_libfunc ("chkr_check_addr");
+ chkr_set_right_libfunc = init_one_libfunc ("chkr_set_right");
+ chkr_copy_bitmap_libfunc = init_one_libfunc ("chkr_copy_bitmap");
+ chkr_check_exec_libfunc = init_one_libfunc ("chkr_check_exec");
+ chkr_check_str_libfunc = init_one_libfunc ("chkr_check_str");
/* For function entry/exit instrumentation. */
profile_function_entry_libfunc
- = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter");
+ = init_one_libfunc ("__cyg_profile_func_enter");
profile_function_exit_libfunc
- = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit");
+ = init_one_libfunc ("__cyg_profile_func_exit");
#ifdef HAVE_conditional_trap
init_traps ();
/* Allow the target to add more libcalls or rename some, etc. */
INIT_TARGET_OPTABS;
#endif
+
+ /* Add these GC roots. */
+ ggc_add_root (optab_table, OTI_MAX, sizeof(optab), mark_optab);
+ ggc_add_rtx_root (libfunc_table, LTI_MAX);
}
\f
#ifdef BROKEN_LDEXP
/* The insn generating function can not take an rtx_code argument.
TRAP_RTX is used as an rtx argument. Its code is replaced with
the code to be used in the trap insn and all other fields are
- ignored.
-
- ??? Will need to change to support garbage collection. */
+ ignored. */
static rtx trap_rtx;
static void
init_traps ()
{
if (HAVE_conditional_trap)
- trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
+ {
+ trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
+ ggc_add_rtx_root (&trap_rtx, 1);
+ }
}
#endif
&& cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
rtx insn;
+ start_sequence();
emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
PUT_CODE (trap_rtx, code);
insn = gen_conditional_trap (trap_rtx, tcode);
if (insn)
- return insn;
+ {
+ emit_insn (insn);
+ insn = gen_sequence ();
+ }
+ end_sequence();
+ return insn;
}
#endif