OSDN Git Service

Add -mabi=n32 support.
[pf3gnuchains/gcc-fork.git] / gcc / expmed.c
index dbd7eb2..be27f85 100644 (file)
@@ -185,21 +185,12 @@ negate_rtx (mode, x)
      enum machine_mode mode;
      rtx x;
 {
-  if (GET_CODE (x) == CONST_INT)
-    {
-      HOST_WIDE_INT val = - INTVAL (x);
-      if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
-       {
-         /* Sign extend the value from the bits that are significant.  */
-         if (val & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))
-           val |= (HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (mode);
-         else
-           val &= ((HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (mode)) - 1;
-       }
-      return GEN_INT (val);
-    }
-  else
-    return expand_unop (GET_MODE (x), neg_optab, x, NULL_RTX, 0);
+  rtx result = simplify_unary_operation (NEG, mode, x, mode);
+
+  if (result == 0)
+    result = expand_unop (mode, neg_optab, x, NULL_RTX, 0);
+
+  return result;
 }
 \f
 /* Generate code to store value from rtx VALUE
@@ -790,10 +781,19 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
          else
            /* The args are chosen so that the last part includes the
               lsb.  Give extract_bit_field the value it needs (with
-              endianness compensation) to fetch the piece we want.  */
-           part = extract_fixed_bit_field (word_mode, value, 0, thissize,
-                                           total_bits - bitsize + bitsdone,
-                                           NULL_RTX, 1, align);
+              endianness compensation) to fetch the piece we want.
+
+              ??? We have no idea what the alignment of VALUE is, so
+              we have to use a guess.  */
+           part
+             = extract_fixed_bit_field
+               (word_mode, value, 0, thissize,
+                total_bits - bitsize + bitsdone, NULL_RTX, 1,
+                GET_MODE (value) == VOIDmode
+                ? UNITS_PER_WORD
+                : (GET_MODE (value) == BLKmode
+                   ? 1
+                   : GET_MODE_ALIGNMENT (GET_MODE (value)) / BITS_PER_UNIT));
        }
       else
        {
@@ -803,8 +803,14 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
                             >> bitsdone)
                            & (((HOST_WIDE_INT) 1 << thissize) - 1));
          else
-           part = extract_fixed_bit_field (word_mode, value, 0, thissize,
-                                           bitsdone, NULL_RTX, 1, align);
+           part
+             = extract_fixed_bit_field
+               (word_mode, value, 0, thissize, bitsdone, NULL_RTX, 1,
+                GET_MODE (value) == VOIDmode
+                ? UNITS_PER_WORD
+                : (GET_MODE (value) == BLKmode
+                   ? 1
+                   : GET_MODE_ALIGNMENT (GET_MODE (value)) / BITS_PER_UNIT));
        }
 
       /* If OP0 is a register, then handle OFFSET here.
@@ -2864,10 +2870,11 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                    pre_shift = floor_log2 (d);
                    if (rem_flag)
                      {
-                       remainder = expand_binop (compute_mode, and_optab, op0,
-                                                 GEN_INT (((HOST_WIDE_INT) 1 << pre_shift) - 1),
-                                                 remainder, 1,
-                                                 OPTAB_LIB_WIDEN);
+                       remainder =
+                         expand_binop (compute_mode, and_optab, op0,
+                                       GEN_INT (((HOST_WIDE_INT) 1 << pre_shift) - 1),
+                                       remainder, 1,
+                                       OPTAB_LIB_WIDEN);
                        if (remainder)
                          return gen_lowpart (mode, remainder);
                      }
@@ -2875,80 +2882,83 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                                             build_int_2 (pre_shift, 0),
                                             tquotient, 1);
                  }
-               else if (d >= ((unsigned HOST_WIDE_INT) 1 << (size - 1)))
-                 {
-                   /* Most significant bit of divisor is set, emit a scc insn.
-                      emit_store_flag needs to be passed a place for the
-                      result.  */
-                   quotient = emit_store_flag (tquotient, GEU, op0, op1,
-                                               compute_mode, 1, 1);
-                   if (quotient == 0)
-                     goto fail1;
-                 }
                else if (size <= HOST_BITS_PER_WIDE_INT)
                  {
-                   /* Find a suitable multiplier and right shift count instead
-                      of multiplying with D.  */
-
-                   mh = choose_multiplier (d, size, size,
-                                           &ml, &post_shift, &dummy);
-
-                   /* If the suggested multiplier is more than SIZE bits, we
-                      can do better for even divisors, using an initial right
-                      shift.  */
-                   if (mh != 0 && (d & 1) == 0)
+                   if (d >= ((unsigned HOST_WIDE_INT) 1 << (size - 1)))
                      {
-                       pre_shift = floor_log2 (d & -d);
-                       mh = choose_multiplier (d >> pre_shift, size,
-                                               size - pre_shift,
-                                               &ml, &post_shift, &dummy);
-                       if (mh)
-                         abort ();
-                     }
-                   else
-                     pre_shift = 0;
-
-                   if (mh != 0)
-                     {
-                       rtx t1, t2, t3, t4;
-
-                       extra_cost = (shift_cost[post_shift - 1]
-                                     + shift_cost[1] + 2 * add_cost);
-                       t1 = expand_mult_highpart (compute_mode, op0, ml,
-                                                  NULL_RTX, 1,
-                                                  max_cost - extra_cost);
-                       if (t1 == 0)
+                       /* Most significant bit of divisor is set; emit an scc
+                          insn.  */
+                       quotient = emit_store_flag (tquotient, GEU, op0, op1,
+                                                   compute_mode, 1, 1);
+                       if (quotient == 0)
                          goto fail1;
-                       t2 = force_operand (gen_rtx (MINUS, compute_mode,
-                                                    op0, t1),
-                                           NULL_RTX);
-                       t3 = expand_shift (RSHIFT_EXPR, compute_mode, t2,
-                                          build_int_2 (1, 0), NULL_RTX, 1);
-                       t4 = force_operand (gen_rtx (PLUS, compute_mode,
-                                                    t1, t3),
-                                           NULL_RTX);
-                       quotient = expand_shift (RSHIFT_EXPR, compute_mode, t4,
-                                                build_int_2 (post_shift - 1,
-                                                             0),
-                                                tquotient, 1);
                      }
                    else
                      {
-                       rtx t1, t2;
+                       /* Find a suitable multiplier and right shift count
+                          instead of multiplying with D.  */
 
-                       t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
-                                          build_int_2 (pre_shift, 0),
-                                          NULL_RTX, 1);
-                       extra_cost = (shift_cost[pre_shift]
-                                     + shift_cost[post_shift]);
-                       t2 = expand_mult_highpart (compute_mode, t1, ml,
-                                                  NULL_RTX, 1,
-                                                  max_cost - extra_cost);
-                       if (t2 == 0)
-                         goto fail1;
-                       quotient = expand_shift (RSHIFT_EXPR, compute_mode, t2,
-                                                build_int_2 (post_shift, 0),
-                                                tquotient, 1);
+                       mh = choose_multiplier (d, size, size,
+                                               &ml, &post_shift, &dummy);
+
+                       /* If the suggested multiplier is more than SIZE bits,
+                          we can do better for even divisors, using an
+                          initial right shift.  */
+                       if (mh != 0 && (d & 1) == 0)
+                         {
+                           pre_shift = floor_log2 (d & -d);
+                           mh = choose_multiplier (d >> pre_shift, size,
+                                                   size - pre_shift,
+                                                   &ml, &post_shift, &dummy);
+                           if (mh)
+                             abort ();
+                         }
+                       else
+                         pre_shift = 0;
+
+                       if (mh != 0)
+                         {
+                           rtx t1, t2, t3, t4;
+
+                           extra_cost = (shift_cost[post_shift - 1]
+                                         + shift_cost[1] + 2 * add_cost);
+                           t1 = expand_mult_highpart (compute_mode, op0, ml,
+                                                      NULL_RTX, 1,
+                                                      max_cost - extra_cost);
+                           if (t1 == 0)
+                             goto fail1;
+                           t2 = force_operand (gen_rtx (MINUS, compute_mode,
+                                                        op0, t1),
+                                               NULL_RTX);
+                           t3 = expand_shift (RSHIFT_EXPR, compute_mode, t2,
+                                              build_int_2 (1, 0), NULL_RTX,1);
+                           t4 = force_operand (gen_rtx (PLUS, compute_mode,
+                                                        t1, t3),
+                                               NULL_RTX);
+                           quotient =
+                             expand_shift (RSHIFT_EXPR, compute_mode, t4,
+                                           build_int_2 (post_shift - 1, 0),
+                                           tquotient, 1);
+                         }
+                       else
+                         {
+                           rtx t1, t2;
+
+                           t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
+                                              build_int_2 (pre_shift, 0),
+                                              NULL_RTX, 1);
+                           extra_cost = (shift_cost[pre_shift]
+                                         + shift_cost[post_shift]);
+                           t2 = expand_mult_highpart (compute_mode, t1, ml,
+                                                      NULL_RTX, 1,
+                                                      max_cost - extra_cost);
+                           if (t2 == 0)
+                             goto fail1;
+                           quotient =
+                             expand_shift (RSHIFT_EXPR, compute_mode, t2,
+                                           build_int_2 (post_shift, 0),
+                                           tquotient, 1);
+                         }
                      }
                  }
                else            /* Too wide mode to use tricky code */
@@ -3859,7 +3869,7 @@ expand_and (op0, op1, target)
    to perform the operation.  It says to use zero-extension.
 
    NORMALIZEP is 1 if we should convert the result to be either zero
-   or one one.  Normalize is -1 if we should convert the result to be
+   or one.  Normalize is -1 if we should convert the result to be
    either zero or -1.  If NORMALIZEP is zero, the result will be left
    "raw" out of the scc insn.  */
 
@@ -3955,9 +3965,11 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
        subtarget = 0;
 
       if (code == GE)
-       op0 = expand_unop (mode, one_cmpl_optab, op0, subtarget, 0);
+       op0 = expand_unop (mode, one_cmpl_optab, op0,
+                          ((STORE_FLAG_VALUE == 1 || normalizep)
+                           ? 0 : subtarget), 0);
 
-      if (normalizep || STORE_FLAG_VALUE == 1)
+      if (STORE_FLAG_VALUE == 1 || normalizep)
        /* If we are supposed to produce a 0/1 value, we want to do
           a logical shift from the sign bit to the low-order bit; for
           a -1/0 value, we do an arithmetic shift.  */