OSDN Git Service

* config/i386/sol2.h (PREFERRED_DEBUGGING_TYPE): Use stabs.
[pf3gnuchains/gcc-fork.git] / gcc / expmed.c
index c0f0668..c0fa722 100644 (file)
@@ -22,8 +22,10 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "toplev.h"
 #include "rtl.h"
 #include "tree.h"
+#include "tm_p.h"
 #include "flags.h"
 #include "insn-flags.h"
 #include "insn-codes.h"
@@ -65,8 +67,8 @@ static int sdiv_pow2_cheap, smod_pow2_cheap;
 #define MAX_BITS_PER_WORD BITS_PER_WORD
 #endif
 
-/* Cost of various pieces of RTL.  Note that some of these are indexed by shift count,
-   and some by mode.  */
+/* Cost of various pieces of RTL.  Note that some of these are indexed by
+   shift count and some by mode.  */
 static int add_cost, negate_cost, zero_cost;
 static int shift_cost[MAX_BITS_PER_WORD];
 static int shiftadd_cost[MAX_BITS_PER_WORD];
@@ -95,7 +97,7 @@ init_expmed ()
      makes.  */
   free_point = (char *) oballoc (0);
 
-  reg = gen_rtx (REG, word_mode, 10000);
+  reg = gen_rtx_REG (word_mode, 10000);
 
   zero_cost = rtx_cost (const0_rtx, 0);
   add_cost = rtx_cost (gen_rtx_PLUS (word_mode, reg, reg), SET);
@@ -169,12 +171,13 @@ init_expmed ()
          mul_highpart_cost[(int) mode]
            = rtx_cost (gen_rtx_TRUNCATE
                        (mode,
-                        gen_rtx_LSHIFTRT
-                        (wider_mode,
-                         gen_rtx_MULT (wider_mode,
-                                       gen_rtx_ZERO_EXTEND (wider_mode, reg),
-                                       gen_rtx_ZERO_EXTEND (wider_mode, reg)),
-                         GEN_INT (GET_MODE_BITSIZE (mode)))),
+                        gen_rtx_LSHIFTRT (wider_mode,
+                                          gen_rtx_MULT (wider_mode,
+                                                        gen_rtx_ZERO_EXTEND
+                                                        (wider_mode, reg),
+                                                        gen_rtx_ZERO_EXTEND
+                                                        (wider_mode, reg)),
+                                          GEN_INT (GET_MODE_BITSIZE (mode)))),
                        SET);
        }
     }
@@ -232,11 +235,12 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
   register rtx op0 = str_rtx;
 #ifdef HAVE_insv
   int insv_bitsize;
+  enum machine_mode op_mode;
 
-  if (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode)
-    insv_bitsize = GET_MODE_BITSIZE (word_mode);
-  else
-    insv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]);
+  op_mode = insn_data[(int) CODE_FOR_insv].operand[3].mode;
+  if (op_mode == VOIDmode)
+    op_mode = word_mode;
+  insv_bitsize = GET_MODE_BITSIZE (op_mode);
 #endif
 
   if (GET_CODE (str_rtx) == MEM && ! MEM_IN_STRUCT_P (str_rtx))
@@ -347,7 +351,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
       else
        {
          int icode = movstrict_optab->handlers[(int) fieldmode].insn_code;
-         if (! (*insn_operand_predicate[icode][1]) (value, fieldmode))
+         if (! (*insn_data[icode].operand[1].predicate) (value, fieldmode))
            value = copy_to_mode_reg (fieldmode, value);
 
          if (GET_CODE (op0) == SUBREG)
@@ -364,7 +368,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
            }
 
          emit_insn (GEN_FCN (icode)
-                  (gen_rtx_SUBREG (fieldmode, op0, offset), value));
+                    (gen_rtx_SUBREG (fieldmode, op0, offset), value));
        }
       return value;
     }
@@ -476,7 +480,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
       enum machine_mode maxmode;
       int save_volatile_ok = volatile_ok;
 
-      maxmode = insn_operand_mode[(int) CODE_FOR_insv][3];
+      maxmode = insn_data[(int) CODE_FOR_insv].operand[3].mode;
       if (maxmode == VOIDmode)
        maxmode = word_mode;
 
@@ -487,7 +491,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
       /* This used to check flag_force_mem, but that was a serious
         de-optimization now that flag_force_mem is enabled by -O2.  */
       if (GET_CODE (op0) == MEM
-         && ! ((*insn_operand_predicate[(int) CODE_FOR_insv][0])
+         && ! ((*insn_data[(int) CODE_FOR_insv].operand[0].predicate)
                (op0, VOIDmode)))
        {
          rtx tempreg;
@@ -584,7 +588,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
 
       /* If this machine's insv insists on a register,
         get VALUE1 into a register.  */
-      if (! ((*insn_operand_predicate[(int) CODE_FOR_insv][3])
+      if (! ((*insn_data[(int) CODE_FOR_insv].operand[3].predicate)
             (value1, maxmode)))
        value1 = force_reg (maxmode, value1);
 
@@ -961,24 +965,25 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
   rtx spec_target_subreg = 0;
 #ifdef HAVE_extv
   int extv_bitsize;
+  enum machine_mode extv_mode;
 #endif
 #ifdef HAVE_extzv
   int extzv_bitsize;
+  enum machine_mode extzv_mode;
 #endif
 
 #ifdef HAVE_extv
-  if (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode)
-    extv_bitsize = GET_MODE_BITSIZE (word_mode);
-  else
-    extv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]);
+  extv_mode = insn_data[(int) CODE_FOR_extv].operand[0].mode;
+  if (extv_mode == VOIDmode)
+    extv_mode = word_mode;
+  extv_bitsize = GET_MODE_BITSIZE (extv_mode);
 #endif
 
 #ifdef HAVE_extzv
-  if (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode)
-    extzv_bitsize = GET_MODE_BITSIZE (word_mode);
-  else
-    extzv_bitsize
-      = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]);
+  extzv_mode = insn_data[(int) CODE_FOR_extzv].operand[0].mode;
+  if (extzv_mode == VOIDmode)
+    extzv_mode = word_mode;
+  extzv_bitsize = GET_MODE_BITSIZE (extzv_mode);
 #endif
 
   /* Discount the part of the structure before the desired byte.
@@ -1208,7 +1213,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          rtx pat;
          enum machine_mode maxmode;
 
-         maxmode = insn_operand_mode[(int) CODE_FOR_extzv][0];
+         maxmode = insn_data[(int) CODE_FOR_extzv].operand[0].mode;
          if (maxmode == VOIDmode)
            maxmode = word_mode;
 
@@ -1218,7 +1223,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
              volatile_ok = 1;
 
              /* Is the memory operand acceptable?  */
-             if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][1])
+             if (! ((*insn_data[(int) CODE_FOR_extzv].operand[1].predicate)
                     (xop0, GET_MODE (xop0))))
                {
                  /* No, load into a reg and extract from there.  */
@@ -1302,7 +1307,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
 
          /* If this machine's extzv insists on a register target,
             make sure we have one.  */
-         if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][0])
+         if (! ((*insn_data[(int) CODE_FOR_extzv].operand[0].predicate)
                 (xtarget, maxmode)))
            xtarget = gen_reg_rtx (maxmode);
 
@@ -1348,14 +1353,14 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          rtx pat;
          enum machine_mode maxmode;
 
-         maxmode = insn_operand_mode[(int) CODE_FOR_extv][0];
+         maxmode = insn_data[(int) CODE_FOR_extv].operand[0].mode;
          if (maxmode == VOIDmode)
            maxmode = word_mode;
 
          if (GET_CODE (xop0) == MEM)
            {
              /* Is the memory operand acceptable?  */
-             if (! ((*insn_operand_predicate[(int) CODE_FOR_extv][1])
+             if (! ((*insn_data[(int) CODE_FOR_extv].operand[1].predicate)
                     (xop0, GET_MODE (xop0))))
                {
                  /* No, load into a reg and extract from there.  */
@@ -1438,7 +1443,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
 
          /* If this machine's extv insists on a register target,
             make sure we have one.  */
-         if (! ((*insn_operand_predicate[(int) CODE_FOR_extv][0])
+         if (! ((*insn_data[(int) CODE_FOR_extv].operand[0].predicate)
                 (xtarget, maxmode)))
            xtarget = gen_reg_rtx (maxmode);
 
@@ -2418,7 +2423,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                  tem = expand_shift (LSHIFT_EXPR, mode, op0,
                                      build_int_2 (log, 0), NULL_RTX, 0);
                  accum = force_operand (gen_rtx_PLUS (mode, accum, tem),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far += (HOST_WIDE_INT) 1 << log;
                  break;
 
@@ -2426,7 +2432,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                  tem = expand_shift (LSHIFT_EXPR, mode, op0,
                                      build_int_2 (log, 0), NULL_RTX, 0);
                  accum = force_operand (gen_rtx_MINUS (mode, accum, tem),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far -= (HOST_WIDE_INT) 1 << log;
                  break;
 
@@ -2435,7 +2442,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                                        build_int_2 (log, 0), shift_subtarget,
                                        0);
                  accum = force_operand (gen_rtx_PLUS (mode, accum, op0),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far = (val_so_far << log) + 1;
                  break;
 
@@ -2444,7 +2452,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                                        build_int_2 (log, 0), shift_subtarget,
                                        0);
                  accum = force_operand (gen_rtx_MINUS (mode, accum, op0),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far = (val_so_far << log) - 1;
                  break;
 
@@ -2452,7 +2461,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                  tem = expand_shift (LSHIFT_EXPR, mode, accum,
                                      build_int_2 (log, 0), NULL_RTX, 0);
                  accum = force_operand (gen_rtx_PLUS (mode, accum, tem),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far += val_so_far << log;
                  break;
 
@@ -2466,17 +2476,17 @@ expand_mult (mode, op0, op1, target, unsignedp)
                  break;
 
                default:
-                 abort ();;
+                 abort ();
                }
 
              /* Write a REG_EQUAL note on the last insn so that we can cse
                 multiplication sequences.  */
 
              insn = get_last_insn ();
-             REG_NOTES (insn)
-               = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                    gen_rtx_MULT (mode, op0, GEN_INT (val_so_far)),
-                                    REG_NOTES (insn));
+             set_unique_reg_note (insn, 
+                                  REG_EQUAL,
+                                  gen_rtx_MULT (mode, op0, 
+                                                GEN_INT (val_so_far)));
            }
 
          if (variant == negate_variant)
@@ -3170,10 +3180,9 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                if (insn != last
                    && (set = single_set (insn)) != 0
                    && SET_DEST (set) == quotient)
-                 REG_NOTES (insn)
-                   = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                        gen_rtx_UDIV (compute_mode, op0, op1),
-                                        REG_NOTES (insn));
+                 set_unique_reg_note (insn, 
+                                      REG_EQUAL,
+                                      gen_rtx_UDIV (compute_mode, op0, op1));
              }
            else                /* TRUNC_DIV, signed */
              {
@@ -3246,13 +3255,14 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                        insn = get_last_insn ();
                        if (insn != last
                            && (set = single_set (insn)) != 0
-                           && SET_DEST (set) == quotient)
-                         REG_NOTES (insn)
-                           = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                                gen_rtx_DIV (compute_mode,
-                                                             op0,
-                                                             GEN_INT (abs_d)),
-                                      REG_NOTES (insn));
+                           && SET_DEST (set) == quotient
+                           && abs_d < ((unsigned HOST_WIDE_INT) 1
+                                       << (HOST_BITS_PER_WIDE_INT - 1)))
+                         set_unique_reg_note (insn, 
+                                              REG_EQUAL,
+                                              gen_rtx_DIV (compute_mode,
+                                                           op0,
+                                                           GEN_INT (abs_d)));
 
                        quotient = expand_unop (compute_mode, neg_optab,
                                                quotient, quotient, 0);
@@ -3278,11 +3288,15 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                        t3 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
                                           build_int_2 (size - 1, 0), NULL_RTX, 0);
                        if (d < 0)
-                         quotient = force_operand (gen_rtx_MINUS (compute_mode, t3, t2),
-                                                   tquotient);
+                         quotient
+                           = force_operand (gen_rtx_MINUS (compute_mode,
+                                                           t3, t2),
+                                            tquotient);
                        else
-                         quotient = force_operand (gen_rtx_MINUS (compute_mode, t2, t3),
-                                                   tquotient);
+                         quotient
+                           = force_operand (gen_rtx_MINUS (compute_mode,
+                                                           t2, t3),
+                                            tquotient);
                      }
                    else
                      {
@@ -3296,18 +3310,25 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                                                   max_cost - extra_cost);
                        if (t1 == 0)
                          goto fail1;
-                       t2 = force_operand (gen_rtx_PLUS (compute_mode, t1, op0),
+                       t2 = force_operand (gen_rtx_PLUS (compute_mode,
+                                                         t1, op0),
                                            NULL_RTX);
                        t3 = expand_shift (RSHIFT_EXPR, compute_mode, t2,
-                                          build_int_2 (post_shift, 0), NULL_RTX, 0);
+                                          build_int_2 (post_shift, 0),
+                                          NULL_RTX, 0);
                        t4 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
-                                          build_int_2 (size - 1, 0), NULL_RTX, 0);
+                                          build_int_2 (size - 1, 0),
+                                          NULL_RTX, 0);
                        if (d < 0)
-                         quotient = force_operand (gen_rtx_MINUS (compute_mode, t4, t3),
-                                                   tquotient);
+                         quotient
+                           = force_operand (gen_rtx_MINUS (compute_mode,
+                                                           t4, t3),
+                                            tquotient);
                        else
-                         quotient = force_operand (gen_rtx_MINUS (compute_mode, t3, t4),
-                                                   tquotient);
+                         quotient
+                           = force_operand (gen_rtx_MINUS (compute_mode,
+                                                           t3, t4),
+                                            tquotient);
                      }
                  }
                else            /* Too wide mode to use tricky code */
@@ -3317,10 +3338,9 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                if (insn != last
                    && (set = single_set (insn)) != 0
                    && SET_DEST (set) == quotient)
-                 REG_NOTES (insn)
-                   = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                        gen_rtx_DIV (compute_mode, op0, op1),
-                                        REG_NOTES (insn));
+                 set_unique_reg_note (insn, 
+                                      REG_EQUAL,
+                                      gen_rtx_DIV (compute_mode, op0, op1));
              }
            break;
          }
@@ -3733,12 +3753,11 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                                     NULL_RTX, unsignedp);
 
            insn = get_last_insn ();
-           REG_NOTES (insn)
-             = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                  gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
-                                                  compute_mode,
-                                                  op0, op1),
-                                  REG_NOTES (insn));
+           set_unique_reg_note (insn,
+                                REG_EQUAL,
+                                gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
+                                                compute_mode,
+                                                op0, op1));
          }
        break;
 
@@ -4094,6 +4113,9 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
   rtx last = get_last_insn ();
   rtx pattern, comparison;
 
+  if (unsignedp)
+    code = unsigned_condition (code);
+
   /* If one operand is constant, make it the second one.  Only do this
      if the other operand is not constant as well.  */
 
@@ -4191,6 +4213,8 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
 
   if (icode != CODE_FOR_nothing)
     {
+      insn_operand_predicate_fn pred;
+
       /* We think we may be able to do this with a scc insn.  Emit the
         comparison and then the scc insn.
 
@@ -4216,10 +4240,11 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
        abort ();
 
       /* Get a reference to the target in the proper mode for this insn.  */
-      compare_mode = insn_operand_mode[(int) icode][0];
+      compare_mode = insn_data[(int) icode].operand[0].mode;
       subtarget = target;
+      pred = insn_data[(int) icode].operand[0].predicate;
       if (preserve_subexpressions_p ()
-         || ! (*insn_operand_predicate[(int) icode][0]) (subtarget, compare_mode))
+         || ! (*pred) (subtarget, compare_mode))
        subtarget = gen_reg_rtx (compare_mode);
 
       pattern = GEN_FCN (icode) (subtarget);
@@ -4259,7 +4284,9 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
             we don't have to do anything.  */
          if (normalizep == 0 || normalizep == STORE_FLAG_VALUE)
            ;
-         else if (normalizep == - STORE_FLAG_VALUE)
+         /* STORE_FLAG_VALUE might be the most negative number, so write
+            the comparison this way to avoid a compiler-time warning.  */
+         else if (- normalizep == STORE_FLAG_VALUE)
            op0 = expand_unop (compare_mode, neg_optab, op0, subtarget, 0);
 
          /* We don't want to use STORE_FLAG_VALUE < 0 below since this
@@ -4493,15 +4520,10 @@ emit_store_flag_force (target, code, op0, op1, mode, unsignedp, normalizep)
     target = gen_reg_rtx (GET_MODE (target));
 
   emit_move_insn (target, const1_rtx);
-  tem = compare_from_rtx (op0, op1, code, unsignedp, mode, NULL_RTX, 0);
-  if (GET_CODE (tem) == CONST_INT)
-    return tem;
-
   label = gen_label_rtx ();
-  if (bcc_gen_fctn[(int) code] == 0)
-    abort ();
+  do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX, 0,
+                          NULL_RTX, label);
 
-  emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label));
   emit_move_insn (target, const0_rtx);
   emit_label (label);
 
@@ -4520,13 +4542,13 @@ emit_store_flag_force (target, code, op0, op1, mode, unsignedp, normalizep)
 static void
 do_cmp_and_jump (arg1, arg2, op, mode, label)
      rtx arg1, arg2, label;
-    enum rtx_code op;
-    enum machine_mode mode;
+     enum rtx_code op;
+     enum machine_mode mode;
 {
   /* 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))
     {
       rtx label2 = gen_label_rtx ();