OSDN Git Service

2001-07-30 H.J. Lu (hjl@gnu.org)
[pf3gnuchains/gcc-fork.git] / gcc / optabs.c
index 312dfce..84cf56d 100644 (file)
@@ -1,5 +1,6 @@
 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
-   Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -28,14 +29,15 @@ Boston, MA 02111-1307, USA.  */
 #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 "except.h"
 #include "expr.h"
 #include "recog.h"
 #include "reload.h"
 #include "ggc.h"
+#include "real.h"
 
 /* Each optab contains info on how this target machine
    can perform a particular operation
@@ -81,37 +83,32 @@ enum insn_code setcc_gen_code[NUM_RTX_CODE];
 enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
 #endif
 
-static int add_equal_note      PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
-static rtx widen_operand       PROTO((rtx, enum machine_mode,
+static int add_equal_note      PARAMS ((rtx, rtx, enum rtx_code, rtx, rtx));
+static rtx widen_operand       PARAMS ((rtx, enum machine_mode,
                                       enum machine_mode, int, int));
-static int expand_cmplxdiv_straight PROTO((rtx, rtx, rtx, rtx,
+static int expand_cmplxdiv_straight PARAMS ((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,
+static int expand_cmplxdiv_wide PARAMS ((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,
+static enum insn_code can_fix_p        PARAMS ((enum machine_mode, enum machine_mode,
                                       int, int *));
-static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode,
+static enum insn_code can_float_p PARAMS ((enum machine_mode, enum machine_mode,
                                         int));
-static rtx ftruncify   PROTO((rtx));
-static optab init_optab        PROTO((enum rtx_code));
-static void init_libfuncs PROTO((optab, int, int, const char *, int));
-static void init_integral_libfuncs PROTO((optab, const char *, int));
-static void init_floating_libfuncs PROTO((optab, const char *, int));
+static rtx ftruncify   PARAMS ((rtx));
+static optab init_optab        PARAMS ((enum rtx_code));
+static void init_libfuncs PARAMS ((optab, int, int, const char *, int));
+static void init_integral_libfuncs PARAMS ((optab, const char *, int));
+static void init_floating_libfuncs PARAMS ((optab, const char *, int));
 #ifdef HAVE_conditional_trap
-static void init_traps PROTO((void));
+static void init_traps PARAMS ((void));
 #endif
-static int cmp_available_p PROTO((enum machine_mode, int));
-static void emit_cmp_and_jump_insn_1 PROTO((rtx, rtx, enum machine_mode,
+static void emit_cmp_and_jump_insn_1 PARAMS ((rtx, rtx, enum machine_mode,
                                            enum rtx_code, int, rtx));
-static void prepare_cmp_insn PROTO((rtx *, rtx *, enum rtx_code *, rtx,
-                                   enum machine_mode *, int *, int));
-static rtx prepare_operand PROTO((int, rtx, int, enum machine_mode,
-                                 enum machine_mode, int));
-static void prepare_float_lib_cmp PROTO((rtx *, rtx *, enum rtx_code *,
+static void prepare_float_lib_cmp PARAMS ((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
@@ -219,7 +216,19 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
   rtx real_t, imag_t;
   rtx temp1, temp2;
   rtx res;
+  optab this_add_optab = add_optab;
+  optab this_sub_optab = sub_optab;
+  optab this_neg_optab = neg_optab;
+  optab this_mul_optab = smul_optab;
              
+  if (binoptab == sdivv_optab)
+    {
+      this_add_optab = addv_optab;
+      this_sub_optab = subv_optab;
+      this_neg_optab = negv_optab;
+      this_mul_optab = smulv_optab;
+    }
+
   /* Don't fetch these from memory more than once.  */
   real0 = force_reg (submode, real0);
   real1 = force_reg (submode, real1);
@@ -230,16 +239,16 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
   imag1 = force_reg (submode, imag1);
 
   /* Divisor: c*c + d*d.  */
-  temp1 = expand_binop (submode, smul_optab, real1, real1,
+  temp1 = expand_binop (submode, this_mul_optab, real1, real1,
                        NULL_RTX, unsignedp, methods);
 
-  temp2 = expand_binop (submode, smul_optab, imag1, imag1,
+  temp2 = expand_binop (submode, this_mul_optab, imag1, imag1,
                        NULL_RTX, unsignedp, methods);
 
   if (temp1 == 0 || temp2 == 0)
     return 0;
 
-  divisor = expand_binop (submode, add_optab, temp1, temp2,
+  divisor = expand_binop (submode, this_add_optab, temp1, temp2,
                          NULL_RTX, unsignedp, methods);
   if (divisor == 0)
     return 0;
@@ -250,44 +259,44 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
       /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)).  */
 
       /* Calculate the dividend.  */
-      real_t = expand_binop (submode, smul_optab, real0, real1,
+      real_t = expand_binop (submode, this_mul_optab, real0, real1,
                             NULL_RTX, unsignedp, methods);
                  
-      imag_t = expand_binop (submode, smul_optab, real0, imag1,
+      imag_t = expand_binop (submode, this_mul_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,
+      imag_t = expand_unop (submode, this_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,
+      temp1 = expand_binop (submode, this_mul_optab, real0, real1,
                            NULL_RTX, unsignedp, methods);
 
-      temp2 = expand_binop (submode, smul_optab, imag0, imag1,
+      temp2 = expand_binop (submode, this_mul_optab, imag0, imag1,
                            NULL_RTX, unsignedp, methods);
 
       if (temp1 == 0 || temp2 == 0)
        return 0;
 
-      real_t = expand_binop (submode, add_optab, temp1, temp2,
+      real_t = expand_binop (submode, this_add_optab, temp1, temp2,
                             NULL_RTX, unsignedp, methods);
                  
-      temp1 = expand_binop (submode, smul_optab, imag0, real1,
+      temp1 = expand_binop (submode, this_mul_optab, imag0, real1,
                            NULL_RTX, unsignedp, methods);
 
-      temp2 = expand_binop (submode, smul_optab, real0, imag1,
+      temp2 = expand_binop (submode, this_mul_optab, real0, imag1,
                            NULL_RTX, unsignedp, methods);
 
       if (temp1 == 0 || temp2 == 0)
        return 0;
 
-      imag_t = expand_binop (submode, sub_optab, temp1, temp2,
+      imag_t = expand_binop (submode, this_sub_optab, temp1, temp2,
                             NULL_RTX, unsignedp, methods);
 
       if (real_t == 0 || imag_t == 0)
@@ -341,6 +350,18 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
   enum machine_mode mode;
   int align;
   rtx res;
+  optab this_add_optab = add_optab;
+  optab this_sub_optab = sub_optab;
+  optab this_neg_optab = neg_optab;
+  optab this_mul_optab = smul_optab;
+
+  if (binoptab == sdivv_optab)
+    {
+      this_add_optab = addv_optab;
+      this_sub_optab = subv_optab;
+      this_neg_optab = negv_optab;
+      this_mul_optab = smulv_optab;
+    }
              
   /* Don't fetch these from memory more than once.  */
   real0 = force_reg (submode, real0);
@@ -359,8 +380,8 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
     }
   else
     {
-      temp1 = expand_abs (submode, real1, NULL_RTX, 1);
-      temp2 = expand_abs (submode, imag1, NULL_RTX, 1);
+      temp1 = expand_abs (submode, real1, NULL_RTX, unsignedp, 1);
+      temp2 = expand_abs (submode, imag1, NULL_RTX, unsignedp, 1);
     }
 
   if (temp1 == 0 || temp2 == 0)
@@ -386,13 +407,13 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
 
   /* Calculate divisor.  */
 
-  temp1 = expand_binop (submode, smul_optab, imag1, ratio,
+  temp1 = expand_binop (submode, this_mul_optab, imag1, ratio,
                        NULL_RTX, unsignedp, methods);
 
   if (temp1 == 0)
     return 0;
 
-  divisor = expand_binop (submode, add_optab, temp1, real1,
+  divisor = expand_binop (submode, this_add_optab, temp1, real1,
                          NULL_RTX, unsignedp, methods);
 
   if (divisor == 0)
@@ -406,13 +427,13 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
 
       /* 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,
+      imag_t = expand_binop (submode, this_mul_optab, real0, ratio,
                             NULL_RTX, unsignedp, methods);
 
       if (imag_t == 0)
        return 0;
 
-      imag_t = expand_unop (submode, neg_optab, imag_t,
+      imag_t = expand_unop (submode, this_neg_optab, imag_t,
                            NULL_RTX, unsignedp);
 
       if (real_t == 0 || imag_t == 0)
@@ -423,22 +444,22 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
       /* 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,
+      temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
                            NULL_RTX, unsignedp, methods);
 
       if (temp1 == 0)
        return 0;
 
-      real_t = expand_binop (submode, add_optab, temp1, real0,
+      real_t = expand_binop (submode, this_add_optab, temp1, real0,
                             NULL_RTX, unsignedp, methods);
 
-      temp1 = expand_binop (submode, smul_optab, real0, ratio,
+      temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
                            NULL_RTX, unsignedp, methods);
 
       if (temp1 == 0)
        return 0;
 
-      imag_t = expand_binop (submode, sub_optab, imag0, temp1,
+      imag_t = expand_binop (submode, this_sub_optab, imag0, temp1,
                             NULL_RTX, unsignedp, methods);
 
       if (real_t == 0 || imag_t == 0)
@@ -491,13 +512,13 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
 
   /* Calculate divisor.  */
 
-  temp1 = expand_binop (submode, smul_optab, real1, ratio,
+  temp1 = expand_binop (submode, this_mul_optab, real1, ratio,
                        NULL_RTX, unsignedp, methods);
 
   if (temp1 == 0)
     return 0;
 
-  divisor = expand_binop (submode, add_optab, temp1, imag1,
+  divisor = expand_binop (submode, this_add_optab, temp1, imag1,
                          NULL_RTX, unsignedp, methods);
 
   if (divisor == 0)
@@ -509,10 +530,10 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
     {
       /* 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,
+      real_t = expand_binop (submode, this_mul_optab, real0, ratio,
                             NULL_RTX, unsignedp, methods);
 
-      imag_t = expand_unop (submode, neg_optab, real0,
+      imag_t = expand_unop (submode, this_neg_optab, real0,
                            NULL_RTX, unsignedp);
 
       if (real_t == 0 || imag_t == 0)
@@ -523,22 +544,22 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
       /* 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,
+      temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
                            NULL_RTX, unsignedp, methods);
 
       if (temp1 == 0)
        return 0;
 
-      real_t = expand_binop (submode, add_optab, temp1, imag0,
+      real_t = expand_binop (submode, this_add_optab, temp1, imag0,
                             NULL_RTX, unsignedp, methods);
 
-      temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+      temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
                            NULL_RTX, unsignedp, methods);
 
       if (temp1 == 0)
        return 0;
 
-      imag_t = expand_binop (submode, sub_optab, temp1, real0,
+      imag_t = expand_binop (submode, this_sub_optab, temp1, real0,
                             NULL_RTX, unsignedp, methods);
 
       if (real_t == 0 || imag_t == 0)
@@ -636,11 +657,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
   /* If we are inside an appropriately-short loop and one operand is an
      expensive constant, force it into a register.  */
   if (CONSTANT_P (op0) && preserve_subexpressions_p ()
-      && rtx_cost (op0, binoptab->code) > 2)
+      && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
     op0 = force_reg (mode, op0);
 
   if (CONSTANT_P (op1) && preserve_subexpressions_p ()
-      && ! shift_op && rtx_cost (op1, binoptab->code) > 2)
+      && ! shift_op && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
     op1 = force_reg (mode, op1);
 
   /* Record where to delete back to if we backtrack.  */
@@ -677,8 +698,8 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
       && 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;
 
@@ -702,30 +723,48 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
        }
 
       /* In case the insn wants input operands in modes different from
-        the result, convert the operands.  */
-
-      if (GET_MODE (op0) != VOIDmode
-         && GET_MODE (op0) != mode0
+        the result, convert the operands.  It would seem that we
+        don't need to convert CONST_INTs, but we do, so that they're
+        a properly sign-extended for their modes; we choose the
+        widest mode between mode and mode[01], so that, in a widening
+        operation, we call convert_modes with different FROM and TO
+        modes, which ensures the value is sign-extended.  Shift
+        operations are an exception, because the second operand needs
+        not be extended to the mode of the result.  */
+
+      if (GET_MODE (op0) != mode0
          && mode0 != VOIDmode)
-       xop0 = convert_to_mode (mode0, xop0, unsignedp);
-
-      if (GET_MODE (xop1) != VOIDmode
-         && GET_MODE (xop1) != mode1
+       xop0 = convert_modes (mode0,
+                             GET_MODE (op0) != VOIDmode
+                             ? GET_MODE (op0)
+                             : GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode0)
+                             ? mode
+                             : mode0,
+                             xop0, unsignedp);
+
+      if (GET_MODE (xop1) != mode1
          && mode1 != VOIDmode)
-       xop1 = convert_to_mode (mode1, xop1, unsignedp);
+       xop1 = convert_modes (mode1,
+                             GET_MODE (op1) != VOIDmode
+                             ? GET_MODE (op1)
+                             : (GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode1)
+                                && ! shift_op)
+                             ? mode
+                             : mode1,
+                             xop1, unsignedp);
 
       /* 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);
@@ -831,7 +870,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
       && GET_MODE_SIZE (mode) > UNITS_PER_WORD
       && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
     {
-      int i;
+      unsigned int i;
       rtx insns;
       rtx equiv_value;
 
@@ -1122,10 +1161,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
       && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
       && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
     {
-      int i;
+      unsigned int i;
       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;
+      unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
       rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
       rtx xop0, xop1;
 
@@ -1492,7 +1531,9 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
          else if (imag0)
            res = imag0;
          else if (binoptab->code == MINUS)
-           res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp);
+            res = expand_unop (submode,
+                                binoptab == subv_optab ? negv_optab : neg_optab,
+                                imag1, imagr, unsignedp);
          else
            res = imag1;
 
@@ -1526,8 +1567,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
              if (temp1 == 0 || temp2 == 0)
                break;
 
-             res = expand_binop (submode, sub_optab, temp1, temp2,
-                                 realr, unsignedp, methods);
+             res = (expand_binop
+                     (submode,
+                      binoptab == smulv_optab ? subv_optab : sub_optab,
+                      temp1, temp2, realr, unsignedp, methods));
 
              if (res == 0)
                break;
@@ -1543,8 +1586,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
              if (temp1 == 0 || temp2 == 0)
                  break;
 
-             res = expand_binop (submode, add_optab, temp1, temp2,
-                                 imagr, unsignedp, methods);
+             res = (expand_binop
+                     (submode,
+                      binoptab == smulv_optab ? addv_optab : add_optab,
+                      temp1, temp2, imagr, unsignedp, methods));
 
              if (res == 0)
                break;
@@ -1693,7 +1738,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
       /* Pass 1 for NO_QUEUE so we don't lose any increments
         if the libcall is cse'd or moved.  */
       value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
-                                      NULL_RTX, 1, mode, 2,
+                                      NULL_RTX, LCT_CONST, mode, 2,
                                       op0, mode, op1x, op1_mode);
 
       insns = get_insns ();
@@ -1877,11 +1922,11 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
   /* If we are inside an appropriately-short loop and one operand is an
      expensive constant, force it into a register.  */
   if (CONSTANT_P (op0) && preserve_subexpressions_p ()
-      && rtx_cost (op0, binoptab->code) > 2)
+      && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
     op0 = force_reg (mode, op0);
 
   if (CONSTANT_P (op1) && preserve_subexpressions_p ()
-      && rtx_cost (op1, binoptab->code) > 2)
+      && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
     op1 = force_reg (mode, op1);
 
   if (targ0)
@@ -1899,8 +1944,8 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
   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;
 
@@ -1913,16 +1958,16 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
        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);
@@ -1947,12 +1992,10 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
            {
              register rtx t0 = gen_reg_rtx (wider_mode);
              register rtx t1 = gen_reg_rtx (wider_mode);
+             rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
+             rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
 
-             if (expand_twoval_binop (binoptab,
-                                      convert_modes (wider_mode, mode, op0,
-                                                     unsignedp),
-                                      convert_modes (wider_mode, mode, op1,
-                                                     unsignedp),
+             if (expand_twoval_binop (binoptab, cop0, cop1,
                                       t0, t1, unsignedp))
                {
                  convert_move (targ0, t0, unsignedp);
@@ -2009,7 +2052,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
   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)
@@ -2023,10 +2066,10 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
 
       /* 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);
@@ -2092,7 +2135,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
       && GET_MODE_SIZE (mode) > UNITS_PER_WORD
       && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
     {
-      int i;
+      unsigned int i;
       rtx insns;
 
       if (target == 0 || target == op0)
@@ -2121,7 +2164,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
     }
 
   /* Open-code the complex negation operation.  */
-  else if (unoptab == neg_optab
+  else if (unoptab->code == NEG
           && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
     {
       rtx target_piece;
@@ -2176,7 +2219,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
       /* Pass 1 for NO_QUEUE so we don't lose any increments
         if the libcall is cse'd or moved.  */
       value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
-                                      NULL_RTX, 1, mode, 1, op0, mode);
+                                      NULL_RTX, LCT_CONST, mode, 1, op0, mode);
       insns = get_insns ();
       end_sequence ();
 
@@ -2232,11 +2275,13 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
 
   /* If there is no negate operation, try doing a subtract from zero.
      The US Software GOFAST library needs this.  */
-  if (unoptab == neg_optab)
+  if (unoptab->code == NEG)
     {    
       rtx temp;
-      temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
-                          target, unsignedp, OPTAB_LIB_WIDEN);
+      temp = expand_binop (mode,
+                           unoptab == negv_optab ? subv_optab : sub_optab,
+                           CONST0_RTX (mode), op0,
+                           target, unsignedp, OPTAB_LIB_WIDEN);
       if (temp)
        return temp;
     }
@@ -2254,19 +2299,40 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
  */
 
 rtx
-expand_abs (mode, op0, target, safe)
+expand_abs (mode, op0, target, result_unsignedp, safe)
      enum machine_mode mode;
      rtx op0;
      rtx target;
+     int result_unsignedp;
      int safe;
 {
   rtx temp, op1;
 
+  if (! flag_trapv)
+    result_unsignedp = 1;
+
   /* First try to do it with a special abs instruction.  */
-  temp = expand_unop (mode, abs_optab, op0, target, 0);
+  temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
+                      op0, target, 0);
   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.  */
@@ -2280,8 +2346,8 @@ expand_abs (mode, op0, target, safe)
       temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
                           OPTAB_LIB_WIDEN);
       if (temp != 0)
-       temp = expand_binop (mode, sub_optab, temp, extended, target, 0,
-                            OPTAB_LIB_WIDEN);
+       temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
+                             temp, extended, target, 0, OPTAB_LIB_WIDEN);
 
       if (temp != 0)
        return temp;
@@ -2308,14 +2374,16 @@ expand_abs (mode, op0, target, safe)
 
   /* 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 (GE, mode, ccp_jump))
     do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx, 
                                  NULL_RTX, op1);
   else
     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);
+  op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
+                     target, target, 0);
   if (op0 != target)
     emit_move_insn (target, op0);
   emit_label (op1);
@@ -2345,6 +2413,7 @@ expand_complex_abs (mode, op0, target, unsignedp)
   rtx entry_last = get_last_insn ();
   rtx last;
   rtx pat;
+  optab this_abs_optab;
 
   /* Find the correct mode for the real and imaginary parts.  */
   enum machine_mode submode
@@ -2367,10 +2436,14 @@ expand_complex_abs (mode, op0, target, unsignedp)
   if (target)
     target = protect_from_queue (target, 1);
 
-  if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+  this_abs_optab = ! unsignedp && flag_trapv
+                   && (GET_MODE_CLASS(mode) == MODE_INT)
+                   ? absv_optab : abs_optab;
+
+  if (this_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];
+      int icode = (int) this_abs_optab->handlers[(int) mode].insn_code;
+      enum machine_mode mode0 = insn_data[icode].operand[1].mode;
       rtx xop0 = op0;
 
       if (target)
@@ -2384,20 +2457,22 @@ expand_complex_abs (mode, op0, target, unsignedp)
 
       /* 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);
       if (pat)
        {
          if (GET_CODE (pat) == SEQUENCE
-             && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))
+             && ! add_equal_note (pat, temp, this_abs_optab->code, xop0, 
+                                  NULL_RTX))
            {
              delete_insns_since (last);
-             return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);
+             return expand_unop (mode, this_abs_optab, op0, NULL_RTX, 
+                                 unsignedp);
            }
 
          emit_insn (pat);
@@ -2413,7 +2488,8 @@ expand_complex_abs (mode, op0, target, unsignedp)
   for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
        wider_mode = GET_MODE_WIDER_MODE (wider_mode))
     {
-      if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
+      if (this_abs_optab->handlers[(int) wider_mode].insn_code 
+         != CODE_FOR_nothing)
        {
          rtx xop0 = op0;
 
@@ -2439,7 +2515,8 @@ expand_complex_abs (mode, op0, target, unsignedp)
 
   /* Open-code the complex absolute-value operation
      if we can open-code sqrt.  Otherwise it's not worth while.  */
-  if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)
+  if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing
+      && ! flag_trapv)
     {
       rtx real, imag, total;
 
@@ -2463,7 +2540,7 @@ expand_complex_abs (mode, op0, target, unsignedp)
     }
 
   /* Now try a library call in this mode.  */
-  if (abs_optab->handlers[(int) mode].libfunc)
+  if (this_abs_optab->handlers[(int) mode].libfunc)
     {
       rtx insns;
       rtx value;
@@ -2473,13 +2550,13 @@ expand_complex_abs (mode, op0, target, unsignedp)
       /* Pass 1 for NO_QUEUE so we don't lose any increments
         if the libcall is cse'd or moved.  */
       value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
-                                      NULL_RTX, 1, submode, 1, op0, mode);
+                                      NULL_RTX, LCT_CONST, submode, 1, op0, mode);
       insns = get_insns ();
       end_sequence ();
 
       target = gen_reg_rtx (submode);
       emit_libcall_block (insns, target, value,
-                         gen_rtx_fmt_e (abs_optab->code, mode, op0));
+                         gen_rtx_fmt_e (this_abs_optab->code, mode, op0));
 
       return target;
     }
@@ -2489,9 +2566,9 @@ expand_complex_abs (mode, op0, target, unsignedp)
   for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
        wider_mode = GET_MODE_WIDER_MODE (wider_mode))
     {
-      if ((abs_optab->handlers[(int) wider_mode].insn_code
+      if ((this_abs_optab->handlers[(int) wider_mode].insn_code
           != CODE_FOR_nothing)
-         || abs_optab->handlers[(int) wider_mode].libfunc)
+         || this_abs_optab->handlers[(int) wider_mode].libfunc)
        {
          rtx xop0 = op0;
 
@@ -2534,7 +2611,7 @@ emit_unop_insn (icode, target, op0, code)
      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);
@@ -2549,10 +2626,10 @@ emit_unop_insn (icode, target, op0, code)
 
   /* 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));
 
@@ -2680,7 +2757,16 @@ emit_no_conflict_block (insns, target, op0, op1, equiv)
        set_unique_reg_note (last, REG_EQUAL, equiv);
     }
   else
-    last = get_last_insn ();
+    {
+      last = get_last_insn ();
+
+      /* Remove any existing REG_EQUAL note from "last", or else it will
+        be mistaken for a note referring to the full contents of the
+        alleged libcall value when found together with the REG_RETVAL
+        note added below.  An existing note can come from an insn
+        expansion at "last".  */
+      remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
+    }
 
   if (prev == 0)
     first = get_insns ();
@@ -2727,22 +2813,43 @@ emit_libcall_block (insns, target, result, equiv)
      rtx result;
      rtx equiv;
 {
+  rtx final_dest = target;
   rtx prev, next, first, last, insn;
 
-  /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
-     reg note to indicate that this call cannot throw. (Unless there is
-     already a REG_EH_REGION note.) */
-
-  for (insn = insns; insn; insn = NEXT_INSN (insn))
+  /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
+     into a MEM later.  Protect the libcall block from this change.  */
+  if (! REG_P (target) || REG_USERVAR_P (target))
+    target = gen_reg_rtx (GET_MODE (target));
+  
+  /* If we're using non-call exceptions, a libcall corresponding to an
+     operation that may trap may also trap.  */
+  if (flag_non_call_exceptions && may_trap_p (equiv))
     {
-      if (GET_CODE (insn) == CALL_INSN)
-        {
-          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 (-1),
-                                                  REG_NOTES (insn));
-        }
+      for (insn = insns; insn; insn = NEXT_INSN (insn))
+       if (GET_CODE (insn) == CALL_INSN)
+         {
+           rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+           
+           if (note != 0 && INTVAL (XEXP (note, 0)) <= 0)
+             remove_note (insn, note);
+         }
     }
+  else
+  /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
+     reg note to indicate that this call cannot throw or execute a nonlocal
+     goto (unless there is already a REG_EH_REGION note, in which case
+     we update it).  */
+    for (insn = insns; insn; insn = NEXT_INSN (insn))
+      if (GET_CODE (insn) == CALL_INSN)
+       {
+         rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+       
+         if (note != 0)
+           XEXP (note, 0) = GEN_INT (-1);
+         else
+           REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
+                                                 REG_NOTES (insn));
+       }
 
   /* First emit all insns that set pseudos.  Remove them from the list as
      we go.  Avoid insns that set pseudos which were referenced in previous
@@ -2759,7 +2866,8 @@ emit_libcall_block (insns, target, result, equiv)
       if (set != 0 && GET_CODE (SET_DEST (set)) == REG
          && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
          && (insn == insns
-             || (! reg_mentioned_p (SET_DEST (set), PATTERN (insns))
+             || ((! INSN_P(insns)
+                  || ! reg_mentioned_p (SET_DEST (set), PATTERN (insns)))
                  && ! reg_used_between_p (SET_DEST (set), insns, insn)
                  && ! modified_in_p (SET_SRC (set), insns)
                  && ! modified_between_p (SET_SRC (set), insns, insn))))
@@ -2791,6 +2899,18 @@ emit_libcall_block (insns, target, result, equiv)
   if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
       != CODE_FOR_nothing)
     set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
+  else
+    {
+      /* Remove any existing REG_EQUAL note from "last", or else it will
+        be mistaken for a note referring to the full contents of the
+        libcall value when found together with the REG_RETVAL note added
+        below.  An existing note can come from an insn expansion at
+        "last".  */
+      remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
+    }
+
+  if (final_dest != target)
+    emit_move_insn (final_dest, target);
 
   if (prev == 0)
     first = get_insns ();
@@ -2822,22 +2942,45 @@ emit_0_to_1_insn (x)
   emit_move_insn (x, const1_rtx);
 }
 
-/* Nonzero if we can perform a comparison of mode MODE for a conditional jump
-   straightforwardly.  */
+/* Nonzero if we can perform a comparison of mode MODE straightforwardly.
+   PURPOSE describes how this comparison will be used.  CODE is the rtx
+   comparison code we will be using.
 
-static int
-cmp_available_p (mode, can_use_tst_p)
+   ??? Actually, CODE is slightly weaker than that.  A target is still
+   required to implement all of the normal bcc operations, but not 
+   required to implement all (or any) of the unordered bcc operations.  */
+  
+int
+can_compare_p (code, mode, purpose)
+     enum rtx_code code;
      enum machine_mode mode;
-     int can_use_tst_p;
+     enum can_compare_purpose purpose;
 {
   do
     {
-      if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing
-         || (can_use_tst_p
-             && tst_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing))
+      if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+       {
+         if (purpose == ccp_jump)
+           return bcc_gen_fctn[(int)code] != NULL;
+         else if (purpose == ccp_store_flag)
+           return setcc_gen_code[(int)code] != CODE_FOR_nothing;
+         else
+           /* There's only one cmov entry point, and it's allowed to fail.  */
+           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 = GET_MODE_WIDER_MODE (mode);
-    } while (mode != VOIDmode);
+    }
+  while (mode != VOIDmode);
 
   return 0;
 }
@@ -2859,19 +3002,22 @@ cmp_available_p (mode, can_use_tst_p)
    The values which are passed in through pointers can be modified; the caller
    should perform the comparison on the modified values.  */
 
-static void
-prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align)
+void
+prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align,
+                 purpose)
      rtx *px, *py;
      enum rtx_code *pcomparison;
      rtx size;
      enum machine_mode *pmode;
      int *punsignedp;
-     int align;
+     int align ATTRIBUTE_UNUSED;
+     enum can_compare_purpose purpose;
 {
   enum machine_mode mode = *pmode;
   rtx x = *px, y = *py;
   int unsignedp = *punsignedp;
   enum mode_class class;
+  rtx opalign ATTRIBUTE_UNUSED = GEN_INT (align / BITS_PER_UNIT);;
 
   class = GET_MODE_CLASS (mode);
 
@@ -2888,10 +3034,12 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align)
 
   /* If we are inside an appropriately-short loop and one operand is an
      expensive constant, force it into a register.  */
-  if (CONSTANT_P (x) && preserve_subexpressions_p () && rtx_cost (x, COMPARE) > 2)
+  if (CONSTANT_P (x) && preserve_subexpressions_p ()
+      && rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
     x = force_reg (mode, x);
 
-  if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
+  if (CONSTANT_P (y) && preserve_subexpressions_p ()
+      && rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
     y = force_reg (mode, y);
 
 #ifdef HAVE_cc0
@@ -2924,9 +3072,9 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align)
          && GET_CODE (size) == CONST_INT
          && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
        {
-         result_mode = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0];
+         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_insn (gen_cmpstrqi (result, x, y, size, opalign));
        }
       else
 #endif
@@ -2935,34 +3083,34 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align)
          && GET_CODE (size) == CONST_INT
          && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
        {
-         result_mode = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0];
+         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_insn (gen_cmpstrhi (result, x, y, size, opalign));
        }
       else
 #endif
 #ifdef HAVE_cmpstrsi
       if (HAVE_cmpstrsi)
        {
-         result_mode = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
+         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)));
+                                  opalign));
        }
       else
 #endif
        {
 #ifdef TARGET_MEM_FUNCTIONS
-         emit_library_call (memcmp_libfunc, 0,
+         emit_library_call (memcmp_libfunc, LCT_PURE_MAKE_BLOCK,
                             TYPE_MODE (integer_type_node), 3,
                             XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
                             convert_to_mode (TYPE_MODE (sizetype), size,
                                              TREE_UNSIGNED (sizetype)),
                             TYPE_MODE (sizetype));
 #else
-         emit_library_call (bcmp_libfunc, 0,
+         emit_library_call (bcmp_libfunc, LCT_PURE_MAKE_BLOCK,
                             TYPE_MODE (integer_type_node), 3,
                             XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
                             convert_to_mode (TYPE_MODE (integer_type_node),
@@ -2987,7 +3135,7 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align)
 
   *px = x;
   *py = y;
-  if (cmp_available_p (mode, y == CONST0_RTX (mode)))
+  if (can_compare_p (*pcomparison, mode, purpose))
     return;
 
   /* Handle a lib call just for the mode we are using.  */
@@ -3031,7 +3179,8 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align)
    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.  */
-static rtx
+
+rtx
 prepare_operand (icode, x, opnum, mode, wider_mode, unsignedp)
      int icode;
      rtx x;
@@ -3044,9 +3193,9 @@ prepare_operand (icode, x, opnum, mode, wider_mode, unsignedp)
   if (mode != wider_mode)
     x = convert_modes (wider_mode, mode, x, unsignedp);
 
-  if (! (*insn_operand_predicate[icode][opnum])
-      (x, insn_operand_mode[icode][opnum]))
-    x = copy_to_mode_reg (insn_operand_mode[icode][opnum], x);
+  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;
 }
 
@@ -3073,6 +3222,20 @@ emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label)
       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)
@@ -3132,25 +3295,22 @@ emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
      rtx size;
      enum machine_mode mode;
      int unsignedp;
-     int align;
+     unsigned int align;
      rtx label;
 {
-  rtx op0;
-  rtx op1;
-         
-  if ((CONSTANT_P (x) && ! CONSTANT_P (y))
-      || (GET_CODE (x) == CONST_INT && GET_CODE (y) != CONST_INT))
+  rtx op0 = x, op1 = y;
+
+  /* Swap operands and condition to ensure canonical RTL.  */
+  if (swap_commutative_operands_p (x, y))
     {
-      /* Swap operands and condition to ensure canonical RTL.  */
-      op0 = y;
-      op1 = x;
+      /* If we're not emitting a branch, this means some caller
+         is out of sync.  */
+      if (! label)
+       abort ();
+
+      op0 = y, op1 = x;
       comparison = swap_condition (comparison);
     }
-  else
-    {
-      op0 = x;
-      op1 = y;
-    }
 
 #ifdef HAVE_cc0
   /* If OP0 is still a constant, then both X and Y must be constants.  Force
@@ -3163,11 +3323,13 @@ emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
   emit_queue ();
   if (unsignedp)
     comparison = unsigned_condition (comparison);
-  prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, align);
+  prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, align,
+                   ccp_jump);
   emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
 }
 
 /* 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;
@@ -3175,28 +3337,10 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
      rtx size;
      enum machine_mode mode;
      int unsignedp;
-     int align;
+     unsigned int align;
 {
   emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, 0);
 }
-
-
-/* Nonzero if a compare of mode MODE can be done straightforwardly
-   (without splitting it into pieces).  */
-
-int
-can_compare_p (mode)
-     enum machine_mode mode;
-{
-  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;
-}
 \f
 /* Emit a library call comparison between floating point X and Y.
    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */
@@ -3209,7 +3353,8 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
      int *punsignedp;
 {
   enum rtx_code comparison = *pcomparison;
-  rtx x = *px, y = *py;
+  rtx x = *px = protect_from_queue (*px, 0);
+  rtx y = *py = protect_from_queue (*py, 0);
   enum machine_mode mode = GET_MODE (x);
   rtx libfunc = 0;
   rtx result;
@@ -3241,6 +3386,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = lehf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unordhf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3271,6 +3420,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = lesf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unordsf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3301,6 +3454,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = ledf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unorddf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3331,6 +3488,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = lexf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unordxf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3361,6 +3522,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
        libfunc = letf2_libfunc;
        break;
 
+      case UNORDERED:
+       libfunc = unordtf2_libfunc;
+       break;
+
       default:
        break;
       }
@@ -3389,8 +3554,8 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
   if (libfunc == 0)
     abort ();
 
-  emit_library_call (libfunc, 1,
-                    word_mode, 2, x, mode, y, mode);
+  emit_library_call (libfunc, LCT_CONST_MAKE_BLOCK, word_mode, 2, x, mode, y,
+                    mode);
 
   /* Immediately move the result of the libcall into a pseudo
      register so reload doesn't clobber the value if it needs
@@ -3400,8 +3565,10 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
   *px = result;
   *py = const0_rtx;
   *pmode = word_mode;
+  if (comparison == UNORDERED)
+    *pcomparison = NE;
 #ifdef FLOAT_LIB_COMPARE_RETURNS_BOOL
-  if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
+  else if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
     *pcomparison = NE;
 #endif
   *punsignedp = 0;
@@ -3413,7 +3580,7 @@ void
 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);
 
@@ -3450,12 +3617,12 @@ emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
 {
   rtx tem, subtarget, comparison, insn;
   enum insn_code icode;
+  enum rtx_code reversed;
 
   /* If one operand is constant, make it the second one.  Only do this
      if the other operand is not constant as well.  */
 
-  if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
-      || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
+  if (swap_commutative_operands_p (op0, op1))
     {
       tem = op0;
       op0 = op1;
@@ -3474,15 +3641,14 @@ emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
   if (cmode == VOIDmode)
     cmode = GET_MODE (op0);
 
-  if (((CONSTANT_P (op2) && ! CONSTANT_P (op3))
-       || (GET_CODE (op2) == CONST_INT && GET_CODE (op3) != CONST_INT))
-      && (GET_MODE_CLASS (GET_MODE (op1)) != MODE_FLOAT
-         || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT || flag_fast_math))
+  if (swap_commutative_operands_p (op2, op3)
+      && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
+          != UNKNOWN))
     {
       tem = op2;
       op2 = op3;
       op3 = tem;
-      code = reverse_condition (code);
+      code = reversed;
     }
 
   if (mode == VOIDmode)
@@ -3513,17 +3679,17 @@ emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
 
   /* 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.  */
@@ -3532,9 +3698,11 @@ emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
     = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX, 0);
 
   /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)?  */
+  /* We can get const0_rtx or const_true_rtx in some circumstances.  Just
+     return NULL and let the caller figure out how best to deal with this
+     situation.  */
   if (GET_CODE (comparison) != code)
-    /* This shouldn't happen.  */
-    abort ();
+    return NULL_RTX;
   
   insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
 
@@ -3585,19 +3753,40 @@ gen_add2_insn (x, y)
 {
   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
-have_add2_insn (mode)
-     enum machine_mode mode;
+have_add2_insn (x, y)
+     rtx x, y;
 {
-  return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
+  int icode;
+
+  if (GET_MODE (x) == VOIDmode)
+    abort ();
+
+  icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 
+
+  if (icode == CODE_FOR_nothing)
+    return 0;
+
+  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)))
+    return 0;
+
+  return 1;
 }
 
 /* Generate and return an insn body to subtract Y from X.  */
@@ -3608,19 +3797,40 @@ gen_sub2_insn (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));
 }
 
 int
-have_sub2_insn (mode)
-     enum machine_mode mode;
+have_sub2_insn (x, y)
+     rtx x, y;
 {
-  return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
+  int icode;
+
+  if (GET_MODE (x) == VOIDmode)
+    abort ();
+
+  icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 
+
+  if (icode == CODE_FOR_nothing)
+    return 0;
+
+  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)))
+    return 0;
+
+  return 1;
 }
 
 /* Generate the body of an instruction to copy Y into X.
@@ -3672,18 +3882,14 @@ gen_move_insn (x, y)
          x = gen_lowpart_common (tmode, x1);
          if (x == 0 && GET_CODE (x1) == MEM)
            {
-             x = gen_rtx_MEM (tmode, XEXP (x1, 0));
-             RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
-             MEM_COPY_ATTRIBUTES (x, x1);
+             x = adjust_address_nv (x1, tmode, 0);
              copy_replacements (x1, x);
            }
 
          y = gen_lowpart_common (tmode, y1);
          if (y == 0 && GET_CODE (y1) == MEM)
            {
-             y = gen_rtx_MEM (tmode, XEXP (y1, 0));
-             RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
-             MEM_COPY_ATTRIBUTES (y, y1);
+             y = adjust_address_nv (y1, tmode, 0);
              copy_replacements (y1, y);
            }
        }
@@ -3713,7 +3919,12 @@ can_extend_p (to_mode, from_mode, unsignedp)
      enum machine_mode to_mode, from_mode;
      int unsignedp;
 {
-  return extendtab[(int) to_mode][(int) from_mode][unsignedp];
+#ifdef HAVE_ptr_extend
+  if (unsignedp < 0)
+    return CODE_FOR_ptr_extend;
+  else
+#endif
+    return extendtab[(int) to_mode][(int) from_mode][unsignedp != 0];
 }
 
 /* Generate the body of an insn to extend Y (with mode MFROM)
@@ -3725,7 +3936,7 @@ gen_extend_insn (x, y, mto, mfrom, unsignedp)
      enum machine_mode mto, mfrom;
      int unsignedp;
 {
-  return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp]) (x, y));
+  return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp != 0]) (x, y));
 }
 \f
 /* can_fix_p and can_float_p say whether the target machine
@@ -3744,13 +3955,14 @@ can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
      int *truncp_ptr;
 {
   *truncp_ptr = 0;
-  if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp] != CODE_FOR_nothing)
-    return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp];
+  if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0]
+      != CODE_FOR_nothing)
+    return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0];
 
   if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
     {
       *truncp_ptr = 1;
-      return fixtab[(int) fltmode][(int) fixmode][unsignedp];
+      return fixtab[(int) fltmode][(int) fixmode][unsignedp != 0];
     }
   return CODE_FOR_nothing;
 }
@@ -3760,7 +3972,7 @@ can_float_p (fltmode, fixmode, unsignedp)
      enum machine_mode fixmode, fltmode;
      int unsignedp;
 {
-  return floattab[(int) fltmode][(int) fixmode][unsignedp];
+  return floattab[(int) fltmode][(int) fixmode][unsignedp != 0];
 }
 \f
 /* Generate code to convert FROM to floating point
@@ -3794,6 +4006,10 @@ expand_float (to, from, unsignedp)
       {
        int doing_unsigned = unsignedp;
 
+       if (fmode != GET_MODE (to)
+           && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
+         continue;
+
        icode = can_float_p (fmode, imode, unsignedp);
        if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
          icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
@@ -3869,8 +4085,8 @@ expand_float (to, from, unsignedp)
              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);
@@ -4001,9 +4217,9 @@ expand_float (to, from, unsignedp)
 
       start_sequence ();
 
-      value = emit_library_call_value (libfcn, NULL_RTX, 1,
-                                      GET_MODE (to),
-                                      1, from, GET_MODE (from));
+      value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
+                                      GET_MODE (to), 1, from,
+                                      GET_MODE (from));
       insns = get_insns ();
       end_sequence ();
 
@@ -4141,7 +4357,9 @@ expand_fix (to, from, unsignedp)
                                 NULL_RTX, 0, OPTAB_LIB_WIDEN);
          expand_fix (to, target, 0);
          target = expand_binop (GET_MODE (to), xor_optab, to,
-                                GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
+                                GEN_INT (trunc_int_for_mode
+                                         ((HOST_WIDE_INT) 1 << (bitsize - 1),
+                                          GET_MODE (to))),
                                 to, 1, OPTAB_LIB_WIDEN);
 
          if (target != to)
@@ -4235,9 +4453,9 @@ expand_fix (to, from, unsignedp)
 
       start_sequence ();
 
-      value = emit_library_call_value (libfcn, NULL_RTX, 1, GET_MODE (to),
-
-                                      1, from, GET_MODE (from));
+      value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
+                                      GET_MODE (to), 1, from,
+                                      GET_MODE (from));
       insns = get_insns ();
       end_sequence ();
 
@@ -4307,8 +4525,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
     {
       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);
+      register char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
       register char *p;
       register const char *q;
 
@@ -4318,11 +4535,13 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
       for (q = opname; *q; )
        *p++ = *q++;
       for (q = mname; *q; q++)
-       *p++ = tolower ((unsigned char)*q);
+       *p++ = TOLOWER (*q);
       *p++ = suffix;
-      *p++ = '\0';
+      *p = '\0';
+
       optable->handlers[(int) mode].libfunc
-       = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
+       = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (libfunc_name,
+                                                      p - libfunc_name));
     }
 }
 
@@ -4354,6 +4573,15 @@ init_floating_libfuncs (optable, opname, suffix)
   init_libfuncs (optable, SFmode, TFmode, opname, suffix);
 }
 
+rtx
+init_one_libfunc (name)
+     register const char *name;
+{
+  name = ggc_strdup (name);
+
+  return gen_rtx_SYMBOL_REF (Pmode, name);
+}
+
 /* Mark ARG (which is really an OPTAB *) for GC.  */
 
 void
@@ -4373,34 +4601,29 @@ mark_optab (arg)
 void
 init_optabs ()
 {
-  int i;
-#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
-  int j;
-#endif
-
-  enum insn_code *p;
+  unsigned int i, j, k;
 
   /* Start by initializing all tables to contain CODE_FOR_nothing.  */
 
-  for (p = fixtab[0][0];
-       p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]); 
-       p++)
-    *p = CODE_FOR_nothing;
+  for (i = 0; i < ARRAY_SIZE (fixtab); i++)
+    for (j = 0; j < ARRAY_SIZE (fixtab[0]); j++)
+      for (k = 0; k < ARRAY_SIZE (fixtab[0][0]); k++)
+       fixtab[i][j][k] = CODE_FOR_nothing;
 
-  for (p = fixtrunctab[0][0];
-       p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]); 
-       p++)
-    *p = CODE_FOR_nothing;
+  for (i = 0; i < ARRAY_SIZE (fixtrunctab); i++)
+    for (j = 0; j < ARRAY_SIZE (fixtrunctab[0]); j++)
+      for (k = 0; k < ARRAY_SIZE (fixtrunctab[0][0]); k++)
+       fixtrunctab[i][j][k] = CODE_FOR_nothing;
 
-  for (p = floattab[0][0];
-       p < floattab[0][0] + sizeof floattab / sizeof (floattab[0][0][0]); 
-       p++)
-    *p = CODE_FOR_nothing;
+  for (i = 0; i < ARRAY_SIZE (floattab); i++)
+    for (j = 0; j < ARRAY_SIZE (floattab[0]); j++)
+      for (k = 0; k < ARRAY_SIZE (floattab[0][0]); k++)
+       floattab[i][j][k] = CODE_FOR_nothing;
 
-  for (p = extendtab[0][0];
-       p < extendtab[0][0] + sizeof extendtab / sizeof extendtab[0][0][0];
-       p++)
-    *p = CODE_FOR_nothing;
+  for (i = 0; i < ARRAY_SIZE (extendtab); i++)
+    for (j = 0; j < ARRAY_SIZE (extendtab[0]); j++)
+      for (k = 0; k < ARRAY_SIZE (extendtab[0][0]); k++)
+       extendtab[i][j][k] = CODE_FOR_nothing;
 
   for (i = 0; i < NUM_RTX_CODE; i++)
     setcc_gen_code[i] = CODE_FOR_nothing;
@@ -4411,13 +4634,17 @@ init_optabs ()
 #endif
 
   add_optab = init_optab (PLUS);
+  addv_optab = init_optab (PLUS);
   sub_optab = init_optab (MINUS);
+  subv_optab = init_optab (MINUS);
   smul_optab = init_optab (MULT);
+  smulv_optab = init_optab (MULT);
   smul_highpart_optab = init_optab (UNKNOWN);
   umul_highpart_optab = init_optab (UNKNOWN);
   smul_widen_optab = init_optab (UNKNOWN);
   umul_widen_optab = init_optab (UNKNOWN);
   sdiv_optab = init_optab (DIV);
+  sdivv_optab = init_optab (DIV);
   sdivmod_optab = init_optab (UNKNOWN);
   udiv_optab = init_optab (UDIV);
   udivmod_optab = init_optab (UNKNOWN);
@@ -4443,13 +4670,19 @@ init_optabs ()
   ucmp_optab = init_optab (UNKNOWN);
   tst_optab = init_optab (UNKNOWN);
   neg_optab = init_optab (NEG);
+  negv_optab = init_optab (NEG);
   abs_optab = init_optab (ABS);
+  absv_optab = init_optab (ABS);
   one_cmpl_optab = init_optab (NOT);
   ffs_optab = init_optab (FFS);
   sqrt_optab = init_optab (SQRT);
   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);
+  push_optab = init_optab (UNKNOWN);
 
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
@@ -4475,11 +4708,18 @@ init_optabs ()
   /* Initialize the optabs with the names of the library functions.  */
   init_integral_libfuncs (add_optab, "add", '3');
   init_floating_libfuncs (add_optab, "add", '3');
+  init_integral_libfuncs (addv_optab, "addv", '3');
+  init_floating_libfuncs (addv_optab, "add", '3');
   init_integral_libfuncs (sub_optab, "sub", '3');
   init_floating_libfuncs (sub_optab, "sub", '3');
+  init_integral_libfuncs (subv_optab, "subv", '3');
+  init_floating_libfuncs (subv_optab, "sub", '3');
   init_integral_libfuncs (smul_optab, "mul", '3');
   init_floating_libfuncs (smul_optab, "mul", '3');
+  init_integral_libfuncs (smulv_optab, "mulv", '3');
+  init_floating_libfuncs (smulv_optab, "mul", '3');
   init_integral_libfuncs (sdiv_optab, "div", '3');
+  init_integral_libfuncs (sdivv_optab, "divv", '3');
   init_integral_libfuncs (udiv_optab, "udiv", '3');
   init_integral_libfuncs (sdivmod_optab, "divmod", '4');
   init_integral_libfuncs (udivmod_optab, "udivmod", '4');
@@ -4501,6 +4741,8 @@ init_optabs ()
   init_integral_libfuncs (umax_optab, "umax", '3');
   init_integral_libfuncs (neg_optab, "neg", '2');
   init_floating_libfuncs (neg_optab, "neg", '2');
+  init_integral_libfuncs (negv_optab, "negv", '2');
+  init_floating_libfuncs (negv_optab, "neg", '2');
   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
   init_integral_libfuncs (ffs_optab, "ffs", '2');
 
@@ -4511,189 +4753,192 @@ init_optabs ()
 
 #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");
+    = 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");
+  memmove_libfunc = init_one_libfunc ("memmove");
+  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");
+
+  unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+                                           ? "_Unwind_SjLj_Resume"
+                                           : "_Unwind_Resume");
 #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");
+  unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
+  unwind_sjlj_unregister_libfunc
+    = init_one_libfunc ("_Unwind_SjLj_Unregister");
+
+  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");
+  unordhf2_libfunc = init_one_libfunc ("__unordhf2");
+
+  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");
+  unordsf2_libfunc = init_one_libfunc ("__unordsf2");
+
+  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");
+  unorddf2_libfunc = init_one_libfunc ("__unorddf2");
+
+  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");
+  unordxf2_libfunc = init_one_libfunc ("__unordxf2");
+
+  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");
+  unordtf2_libfunc = init_one_libfunc ("__unordtf2");
+
+  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 ();
@@ -4709,37 +4954,21 @@ init_optabs ()
   ggc_add_rtx_root (libfunc_table, LTI_MAX);
 }
 \f
-#ifdef BROKEN_LDEXP
-
-/* SCO 3.2 apparently has a broken ldexp.  */
-
-double
-ldexp(x,n)
-     double x;
-     int n;
-{
-  if (n > 0)
-    while (n--)
-      x *= 2;
-
-  return x;
-}
-#endif /* BROKEN_LDEXP */
-\f
 #ifdef HAVE_conditional_trap
 /* 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
 
@@ -4761,11 +4990,17 @@ gen_cond_trap (code, op1, op2, tcode)
       && 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