OSDN Git Service

* doc/fragments.texi, doc/trouble.texi: Remove links to old
[pf3gnuchains/gcc-fork.git] / gcc / expmed.c
index 5a2e7f0..3879725 100644 (file)
@@ -3,22 +3,22 @@
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 
 #include "config.h"
@@ -28,32 +28,28 @@ Boston, MA 02111-1307, USA.  */
 #include "tree.h"
 #include "tm_p.h"
 #include "flags.h"
-#include "insn-flags.h"
-#include "insn-codes.h"
 #include "insn-config.h"
 #include "expr.h"
+#include "optabs.h"
 #include "real.h"
 #include "recog.h"
 
 static void store_fixed_bit_field      PARAMS ((rtx, unsigned HOST_WIDE_INT,
                                                 unsigned HOST_WIDE_INT,
-                                                unsigned HOST_WIDE_INT, rtx,
-                                                unsigned int));
+                                                unsigned HOST_WIDE_INT, rtx));
 static void store_split_bit_field      PARAMS ((rtx, unsigned HOST_WIDE_INT,
-                                                unsigned HOST_WIDE_INT, rtx,
-                                                unsigned int));
+                                                unsigned HOST_WIDE_INT, rtx));
 static rtx extract_fixed_bit_field     PARAMS ((enum machine_mode, rtx,
                                                 unsigned HOST_WIDE_INT,
                                                 unsigned HOST_WIDE_INT,
                                                 unsigned HOST_WIDE_INT,
-                                                rtx, int, unsigned int));
+                                                rtx, int));
 static rtx mask_rtx                    PARAMS ((enum machine_mode, int,
                                                 int, int));
 static rtx lshift_value                        PARAMS ((enum machine_mode, rtx,
                                                 int, int));
 static rtx extract_split_bit_field     PARAMS ((rtx, unsigned HOST_WIDE_INT,
-                                                unsigned HOST_WIDE_INT, int,
-                                                unsigned int));
+                                                unsigned HOST_WIDE_INT, int));
 static void do_cmp_and_jump            PARAMS ((rtx, rtx, enum rtx_code,
                                                 enum machine_mode, rtx));
 
@@ -76,6 +72,23 @@ static int sdiv_pow2_cheap, smod_pow2_cheap;
 #define MAX_BITS_PER_WORD BITS_PER_WORD
 #endif
 
+/* Reduce conditional compilation elsewhere.  */
+#ifndef HAVE_insv
+#define HAVE_insv      0
+#define CODE_FOR_insv  CODE_FOR_nothing
+#define gen_insv(a,b,c,d) NULL_RTX
+#endif
+#ifndef HAVE_extv
+#define HAVE_extv      0
+#define CODE_FOR_extv  CODE_FOR_nothing
+#define gen_extv(a,b,c,d) NULL_RTX
+#endif
+#ifndef HAVE_extzv
+#define HAVE_extzv     0
+#define CODE_FOR_extzv CODE_FOR_nothing
+#define gen_extzv(a,b,c,d) NULL_RTX
+#endif
+
 /* 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;
@@ -204,6 +217,58 @@ negate_rtx (mode, x)
 
   return result;
 }
+
+/* Report on the availability of insv/extv/extzv and the desired mode
+   of each of their operands.  Returns MAX_MACHINE_MODE if HAVE_foo
+   is false; else the mode of the specified operand.  If OPNO is -1,
+   all the caller cares about is whether the insn is available.  */
+enum machine_mode
+mode_for_extraction (pattern, opno)
+     enum extraction_pattern pattern;
+     int opno;
+{
+  const struct insn_data *data;
+
+  switch (pattern)
+    {
+    case EP_insv:
+      if (HAVE_insv)
+       {
+         data = &insn_data[CODE_FOR_insv];
+         break;
+       }
+      return MAX_MACHINE_MODE;
+
+    case EP_extv:
+      if (HAVE_extv)
+       {
+         data = &insn_data[CODE_FOR_extv];
+         break;
+       }
+      return MAX_MACHINE_MODE;
+
+    case EP_extzv:
+      if (HAVE_extzv)
+       {
+         data = &insn_data[CODE_FOR_extzv];
+         break;
+       }
+      return MAX_MACHINE_MODE;
+
+    default:
+      abort ();
+    }
+
+  if (opno == -1)
+    return VOIDmode;
+
+  /* Everyone who uses this function used to follow it with
+     if (result == VOIDmode) result = word_mode; */
+  if (data->operand[opno].mode == VOIDmode)
+    return word_mode;
+  return data->operand[opno].mode;
+}
+
 \f
 /* Generate code to store value from rtx VALUE
    into a bit-field within structure STR_RTX
@@ -221,34 +286,21 @@ negate_rtx (mode, x)
    else, we use the mode of operand 3.  */
 
 rtx
-store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
+store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, total_size)
      rtx str_rtx;
      unsigned HOST_WIDE_INT bitsize;
      unsigned HOST_WIDE_INT bitnum;
      enum machine_mode fieldmode;
      rtx value;
-     unsigned int align;
      HOST_WIDE_INT total_size;
 {
   unsigned int unit
     = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
   unsigned HOST_WIDE_INT offset = bitnum / unit;
   unsigned HOST_WIDE_INT bitpos = bitnum % unit;
-  register rtx op0 = str_rtx;
-#ifdef HAVE_insv
-  unsigned HOST_WIDE_INT insv_bitsize;
-  enum machine_mode op_mode;
-
-  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
+  rtx op0 = str_rtx;
 
-  /* It is wrong to have align==0, since every object is aligned at
-     least at a bit boundary.  This usually means a bug elsewhere.  */
-  if (align == 0)
-    abort ();
+  enum machine_mode op_mode = mode_for_extraction (EP_insv, 3);
 
   /* Discount the part of the structure before the desired byte.
      We need to know how many bytes are safe to reference after it.  */
@@ -263,20 +315,12 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
         meaningful at a much higher level; when structures are copied
         between memory and regs, the higher-numbered regs
         always get higher addresses.  */
-      offset += SUBREG_WORD (op0);
+      offset += (SUBREG_BYTE (op0) / UNITS_PER_WORD);
       /* We used to adjust BITPOS here, but now we do the whole adjustment
         right after the loop.  */
       op0 = SUBREG_REG (op0);
     }
 
-  /* If OP0 is a register, BITPOS must count within a word.
-     But as we have it, it counts within whatever size OP0 now has.
-     On a bigendian machine, these are not the same, so convert.  */
-  if (BYTES_BIG_ENDIAN
-      && GET_CODE (op0) != MEM
-      && unit > GET_MODE_BITSIZE (GET_MODE (op0)))
-    bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
-
   value = protect_from_queue (value, 0);
 
   if (flag_force_mem)
@@ -289,14 +333,14 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
      done with a simple store.  For targets that support fast unaligned
      memory, any naturally sized, unit aligned field can be done directly.  */
      
-  if (bitsize == GET_MODE_BITSIZE (fieldmode)
+  if (bitpos == 0
+      && bitsize == GET_MODE_BITSIZE (fieldmode)
       && (GET_CODE (op0) != MEM
          ? (GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
             || GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode))
-         : (! SLOW_UNALIGNED_ACCESS (fieldmode, align)
+         : (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
             || (offset * BITS_PER_UNIT % bitsize == 0
-                && align % GET_MODE_BITSIZE (fieldmode) == 0)))
-      && (BYTES_BIG_ENDIAN ? bitpos + bitsize == unit : bitpos == 0))
+                && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0))))
     {
       if (GET_MODE (op0) != fieldmode)
        {
@@ -313,10 +357,11 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
                abort ();
            }
          if (GET_CODE (op0) == REG)
-           op0 = gen_rtx_SUBREG (fieldmode, op0, offset);
+           op0 = gen_rtx_SUBREG (fieldmode, op0,
+                                 (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+                                 + (offset * UNITS_PER_WORD));
          else
-           op0 = change_address (op0, fieldmode,
-                                 plus_constant (XEXP (op0, 0), offset));
+           op0 = adjust_address (op0, fieldmode, offset);
        }
       emit_move_insn (op0, value);
       return value;
@@ -331,7 +376,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
     if (imode != GET_MODE (op0))
       {
        if (GET_CODE (op0) == MEM)
-         op0 = change_address (op0, imode, NULL_RTX);
+         op0 = adjust_address (op0, imode, 0);
        else if (imode != BLKmode)
          op0 = gen_lowpart (imode, op0);
        else
@@ -339,6 +384,14 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
       }
   }
 
+  /* If OP0 is a register, BITPOS must count within a word.
+     But as we have it, it counts within whatever size OP0 now has.
+     On a bigendian machine, these are not the same, so convert.  */
+  if (BYTES_BIG_ENDIAN
+      && GET_CODE (op0) != MEM
+      && unit > GET_MODE_BITSIZE (GET_MODE (op0)))
+    bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
+
   /* Storing an lsb-aligned field in a register
      can be done with a movestrict instruction.  */
 
@@ -375,7 +428,10 @@ 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,
+                                 (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+                                 + (offset * UNITS_PER_WORD)),
+                                 value));
 
       return value;
     }
@@ -407,10 +463,10 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
             if I is 1, use the next to lowest word; and so on.  */
          unsigned int wordnum = (backwards ? nwords - i - 1 : i);
          unsigned int bit_offset = (backwards
-                           ? MAX ((int) bitsize - ((int) i + 1)
-                                  * BITS_PER_WORD,
-                                  0)
-                           : (int) i * BITS_PER_WORD);
+                                    ? MAX ((int) bitsize - ((int) i + 1)
+                                           * BITS_PER_WORD,
+                                           0)
+                                    : (int) i * BITS_PER_WORD);
 
          store_bit_field (op0, MIN (BITS_PER_WORD,
                                     bitsize - i * BITS_PER_WORD),
@@ -419,7 +475,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
                                                  (GET_MODE (value) == VOIDmode
                                                   ? fieldmode
                                                   : GET_MODE (value))),
-                          align, total_size);
+                          total_size);
        }
       return value;
     }
@@ -449,14 +505,12 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
                abort ();
            }
          op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
-                               op0, offset);
+                               op0, (offset * UNITS_PER_WORD));
        }
       offset = 0;
     }
   else
-    {
-      op0 = protect_from_queue (op0, 1);
-    }
+    op0 = protect_from_queue (op0, 1);
 
   /* If VALUE is a floating-point mode, access it as an integer of the
      corresponding size.  This can occur on a machine with 64 bit registers
@@ -472,27 +526,22 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
   /* Now OFFSET is nonzero only if OP0 is memory
      and is therefore always measured in bytes.  */
 
-#ifdef HAVE_insv
   if (HAVE_insv
       && GET_MODE (value) != BLKmode
       && !(bitsize == 1 && GET_CODE (value) == CONST_INT)
       /* Ensure insv's size is wide enough for this field.  */
-      && (insv_bitsize >= bitsize)
+      && (GET_MODE_BITSIZE (op_mode) >= bitsize)
       && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
-           && (bitsize + bitpos > insv_bitsize)))
+           && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode))))
     {
       int xbitpos = bitpos;
       rtx value1;
       rtx xop0 = op0;
       rtx last = get_last_insn ();
       rtx pat;
-      enum machine_mode maxmode;
+      enum machine_mode maxmode = mode_for_extraction (EP_insv, 3);
       int save_volatile_ok = volatile_ok;
 
-      maxmode = insn_data[(int) CODE_FOR_insv].operand[3].mode;
-      if (maxmode == VOIDmode)
-       maxmode = word_mode;
-
       volatile_ok = 1;
 
       /* If this machine's insv can only insert into a register, copy OP0
@@ -514,29 +563,28 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
          if (GET_MODE (op0) == BLKmode
              || GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (maxmode))
            bestmode
-             = get_best_mode (bitsize, bitnum, align, maxmode,
+             = get_best_mode (bitsize, bitnum, MEM_ALIGN (op0), maxmode,
                               MEM_VOLATILE_P (op0));
          else
            bestmode = GET_MODE (op0);
 
          if (bestmode == VOIDmode
-             || (SLOW_UNALIGNED_ACCESS (bestmode, align)
-                 && GET_MODE_BITSIZE (bestmode) > align))
+             || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (op0))
+                 && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (op0)))
            goto insv_loses;
 
-         /* Adjust address to point to the containing unit of that mode.  */
+         /* Adjust address to point to the containing unit of that mode. 
+            Compute offset as multiple of this unit, counting in bytes.  */
          unit = GET_MODE_BITSIZE (bestmode);
-         /* Compute offset as multiple of this unit, counting in bytes.  */
          offset = (bitnum / unit) * GET_MODE_SIZE (bestmode);
          bitpos = bitnum % unit;
-         op0 = change_address (op0, bestmode, 
-                               plus_constant (XEXP (op0, 0), offset));
+         op0 = adjust_address (op0, bestmode,  offset);
 
          /* Fetch that unit, store the bitfield in it, then store
             the unit.  */
          tempreg = copy_to_reg (op0);
          store_bit_field (tempreg, bitsize, bitpos, fieldmode, value,
-                          align, total_size);
+                          total_size);
          emit_move_insn (op0, tempreg);
          return value;
        }
@@ -544,15 +592,14 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
 
       /* Add OFFSET into OP0's address.  */
       if (GET_CODE (xop0) == MEM)
-       xop0 = change_address (xop0, byte_mode,
-                              plus_constant (XEXP (xop0, 0), offset));
+       xop0 = adjust_address (xop0, byte_mode, offset);
 
       /* If xop0 is a register, we need it in MAXMODE
         to make it acceptable to the format of insv.  */
       if (GET_CODE (xop0) == SUBREG)
        /* We can't just change the mode, because this might clobber op0,
           and we will need the original value of op0 if insv fails.  */
-       xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_WORD (xop0));
+       xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_BYTE (xop0));
       if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)
        xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
 
@@ -580,15 +627,13 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
                 if we must narrow it, be sure we do it correctly.  */
 
              if (GET_MODE_SIZE (GET_MODE (value)) < GET_MODE_SIZE (maxmode))
-               {
-                 /* Avoid making subreg of a subreg, or of a mem.  */
-                 if (GET_CODE (value1) != REG)
-                   value1 = copy_to_reg (value1);
-                 value1 = gen_rtx_SUBREG (maxmode, value1, 0);
-               }
+               value1 = simplify_gen_subreg (maxmode, value1,
+                                             GET_MODE (value1), 0);
              else
                value1 = gen_lowpart (maxmode, value1);
            }
+         else if (GET_CODE (value) == CONST_INT)
+           value1 = GEN_INT (trunc_int_for_mode (INTVAL (value), maxmode));
          else if (!CONSTANT_P (value))
            /* Parse phase is supposed to make VALUE's data type
               match that of the component reference, which is a type
@@ -609,14 +654,13 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
       else
         {
          delete_insns_since (last);
-         store_fixed_bit_field (op0, offset, bitsize, bitpos, value, align);
+         store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
        }
     }
   else
     insv_loses:
-#endif
     /* Insv is not available; store using shifts and boolean ops.  */
-    store_fixed_bit_field (op0, offset, bitsize, bitpos, value, align);
+    store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
   return value;
 }
 \f
@@ -628,26 +672,21 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
     (If OP0 is a register, it may be a full word or a narrower mode,
      but BITPOS still counts within a full word,
      which is significant on bigendian machines.)
-   STRUCT_ALIGN is the alignment the structure is known to have.
 
    Note that protect_from_queue has already been done on OP0 and VALUE.  */
 
 static void
-store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align)
-     register rtx op0;
+store_fixed_bit_field (op0, offset, bitsize, bitpos, value)
+     rtx op0;
      unsigned HOST_WIDE_INT offset, bitsize, bitpos;
-     register rtx value;
-     unsigned int struct_align;
+     rtx value;
 {
-  register enum machine_mode mode;
+  enum machine_mode mode;
   unsigned int total_bits = BITS_PER_WORD;
   rtx subtarget, temp;
   int all_zero = 0;
   int all_one = 0;
 
-  if (! SLOW_UNALIGNED_ACCESS (word_mode, struct_align))
-    struct_align = BIGGEST_ALIGNMENT;
-    
   /* There is a case not handled here:
      a structure with a known alignment of just a halfword
      and a field split across two aligned halfwords within the structure.
@@ -662,8 +701,7 @@ store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align)
       /* Special treatment for a bit field split across two registers.  */
       if (bitsize + bitpos > BITS_PER_WORD)
        {
-         store_split_bit_field (op0, bitsize, bitpos,
-                                value, BITS_PER_WORD);
+         store_split_bit_field (op0, bitsize, bitpos, value);
          return;
        }
     }
@@ -671,19 +709,22 @@ store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align)
     {
       /* Get the proper mode to use for this field.  We want a mode that
         includes the entire field.  If such a mode would be larger than
-        a word, we won't be doing the extraction the normal way.  */
+        a word, we won't be doing the extraction the normal way.  
+        We don't want a mode bigger than the destination.  */
 
+      mode = GET_MODE (op0);
+      if (GET_MODE_BITSIZE (mode) == 0
+          || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
+        mode = word_mode;
       mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
-                           struct_align, word_mode,
-                           GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0));
+                           MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
 
       if (mode == VOIDmode)
        {
          /* The only way this should occur is if the field spans word
             boundaries.  */
-         store_split_bit_field (op0,
-                                bitsize, bitpos + offset * BITS_PER_UNIT,
-                                value, struct_align);
+         store_split_bit_field (op0, bitsize, bitpos + offset * BITS_PER_UNIT,
+                                value);
          return;
        }
 
@@ -705,8 +746,7 @@ store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align)
         Then alter OP0 to refer to that word.  */
       bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT;
       offset -= (offset % (total_bits / BITS_PER_UNIT));
-      op0 = change_address (op0, mode,
-                           plus_constant (XEXP (op0, 0), offset));
+      op0 = adjust_address (op0, mode, offset);
     }
 
   mode = GET_MODE (op0);
@@ -731,7 +771,7 @@ store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align)
 
   if (GET_CODE (value) == CONST_INT)
     {
-      register HOST_WIDE_INT v = INTVAL (value);
+      HOST_WIDE_INT v = INTVAL (value);
 
       if (bitsize < HOST_BITS_PER_WIDE_INT)
        v &= ((HOST_WIDE_INT) 1 << bitsize) - 1;
@@ -798,17 +838,14 @@ store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align)
    BITSIZE is the field width; BITPOS the position of its first bit
    (within the word).
    VALUE is the value to store.
-   ALIGN is the known alignment of OP0.
-   This is also the size of the memory objects to be used.
 
    This does not yet handle fields wider than BITS_PER_WORD.  */
 
 static void
-store_split_bit_field (op0, bitsize, bitpos, value, align)
+store_split_bit_field (op0, bitsize, bitpos, value)
      rtx op0;
      unsigned HOST_WIDE_INT bitsize, bitpos;
      rtx value;
-     unsigned int align;
 {
   unsigned int unit;
   unsigned int bitsdone = 0;
@@ -818,7 +855,7 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
   if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
     unit = BITS_PER_WORD;
   else
-    unit = MIN (align, BITS_PER_WORD);
+    unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD);
 
   /* If VALUE is a constant other than a CONST_INT, get it into a register in
      WORD_MODE.  If we can do this using gen_lowpart_common, do so.  Note
@@ -874,18 +911,10 @@ 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.
-
-              ??? 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))));
+              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);
        }
       else
        {
@@ -895,13 +924,8 @@ 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,
-                GET_MODE (value) == VOIDmode
-                ? UNITS_PER_WORD
-                : (GET_MODE (value) == BLKmode
-                   ? 1 : GET_MODE_ALIGNMENT (GET_MODE (value))));
+           part = extract_fixed_bit_field (word_mode, value, 0, thissize,
+                                           bitsdone, NULL_RTX, 1);
        }
 
       /* If OP0 is a register, then handle OFFSET here.
@@ -912,8 +936,8 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
         the current word starting from the base register.  */
       if (GET_CODE (op0) == SUBREG)
        {
-         word = operand_subword_force (SUBREG_REG (op0),
-                                       SUBREG_WORD (op0) + offset,
+         int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
+         word = operand_subword_force (SUBREG_REG (op0), word_offset,
                                        GET_MODE (SUBREG_REG (op0)));
          offset = 0;
        }
@@ -927,8 +951,8 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
 
       /* OFFSET is in UNITs, and UNIT is in bits.
          store_fixed_bit_field wants offset in bytes.  */
-      store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT,
-                            thissize, thispos, part, align);
+      store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT, thissize,
+                            thispos, part);
       bitsdone += thissize;
     }
 }
@@ -945,7 +969,6 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
    TMODE is the mode the caller would like the value to have;
    but the value may be returned with type MODE instead.
 
-   ALIGN is the alignment that STR_RTX is known to have.
    TOTAL_SIZE is the size in bytes of the containing structure,
    or -1 if varying.
 
@@ -956,46 +979,25 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
 
 rtx
 extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
-                  target, mode, tmode, align, total_size)
+                  target, mode, tmode, total_size)
      rtx str_rtx;
      unsigned HOST_WIDE_INT bitsize;
      unsigned HOST_WIDE_INT bitnum;
      int unsignedp;
      rtx target;
      enum machine_mode mode, tmode;
-     unsigned int align;
      HOST_WIDE_INT total_size;
 {
   unsigned int unit
     = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
   unsigned HOST_WIDE_INT offset = bitnum / unit;
   unsigned HOST_WIDE_INT bitpos = bitnum % unit;
-  register rtx op0 = str_rtx;
+  rtx op0 = str_rtx;
   rtx spec_target = target;
   rtx spec_target_subreg = 0;
   enum machine_mode int_mode;
-#ifdef HAVE_extv
-  unsigned HOST_WIDE_INT extv_bitsize;
-  enum machine_mode extv_mode;
-#endif
-#ifdef HAVE_extzv
-  unsigned HOST_WIDE_INT extzv_bitsize;
-  enum machine_mode extzv_mode;
-#endif
-
-#ifdef HAVE_extv
-  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
-  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
+  enum machine_mode extv_mode = mode_for_extraction (EP_extv, 0);
+  enum machine_mode extzv_mode = mode_for_extraction (EP_extzv, 0);
 
   /* Discount the part of the structure before the desired byte.
      We need to know how many bytes are safe to reference after it.  */
@@ -1010,7 +1012,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
       int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));
       int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));
 
-      offset += SUBREG_WORD (op0);
+      offset += SUBREG_BYTE (op0) / UNITS_PER_WORD;
 
       inner_size = MIN (inner_size, BITS_PER_WORD);
 
@@ -1027,6 +1029,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
       op0 = SUBREG_REG (op0);
     }
 
+  if (GET_CODE (op0) == REG
+      && mode == GET_MODE (op0)
+      && bitnum == 0
+      && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
+    {
+      /* We're trying to extract a full register from itself.  */
+      return op0;
+    }
+
   /* Make sure we are playing with integral modes.  Pun with subregs
      if we aren't.  */
   {
@@ -1034,7 +1045,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
     if (imode != GET_MODE (op0))
       {
        if (GET_CODE (op0) == MEM)
-         op0 = change_address (op0, imode, NULL_RTX);
+         op0 = adjust_address (op0, imode, 0);
        else if (imode != BLKmode)
          op0 = gen_lowpart (imode, op0);
        else
@@ -1064,9 +1075,9 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
        && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
                                  GET_MODE_BITSIZE (GET_MODE (op0))))
        || (GET_CODE (op0) == MEM
-          && (! SLOW_UNALIGNED_ACCESS (mode, align)
+          && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (op0))
               || (offset * BITS_PER_UNIT % bitsize == 0
-                  && align % bitsize == 0))))
+                  && MEM_ALIGN (op0) % bitsize == 0))))
       && ((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode)
           && bitpos % BITS_PER_WORD == 0)
          || (mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0) != BLKmode
@@ -1097,10 +1108,11 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                abort ();
            }
          if (GET_CODE (op0) == REG)
-           op0 = gen_rtx_SUBREG (mode1, op0, offset);
+           op0 = gen_rtx_SUBREG (mode1, op0,
+                                 (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+                                 + (offset * UNITS_PER_WORD));
          else
-           op0 = change_address (op0, mode1,
-                                 plus_constant (XEXP (op0, 0), offset));
+           op0 = adjust_address (op0, mode1, offset);
        }
       if (mode1 != mode)
        return convert_to_mode (tmode, op0, unsignedp);
@@ -1144,7 +1156,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
            = extract_bit_field (op0, MIN (BITS_PER_WORD,
                                           bitsize - i * BITS_PER_WORD),
                                 bitnum + bit_offset, 1, target_part, mode,
-                                word_mode, align, total_size);
+                                word_mode, total_size);
 
          if (target_part == 0)
            abort ();
@@ -1163,11 +1175,11 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
 
              total_words = GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD;
              for (i = nwords; i < total_words; i++)
-               {
-                 int wordnum = WORDS_BIG_ENDIAN ? total_words - i - 1 : i;
-                 rtx target_part = operand_subword (target, wordnum, 1, VOIDmode);
-                 emit_move_insn (target_part, const0_rtx);
-               }
+               emit_move_insn
+                 (operand_subword (target,
+                                   WORDS_BIG_ENDIAN ? total_words - i - 1 : i,
+                                   1, VOIDmode),
+                  const0_rtx);
            }
          return target;
        }
@@ -1206,24 +1218,21 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          if (GET_CODE (op0) != REG)
            op0 = copy_to_reg (op0);
          op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
-                               op0, offset);
+                               op0, (offset * UNITS_PER_WORD));
        }
       offset = 0;
     }
   else
-    {
-      op0 = protect_from_queue (str_rtx, 1);
-    }
+    op0 = protect_from_queue (str_rtx, 1);
 
   /* Now OFFSET is nonzero only for memory operands.  */
 
   if (unsignedp)
     {
-#ifdef HAVE_extzv
       if (HAVE_extzv
-         && (extzv_bitsize >= bitsize)
+         && (GET_MODE_BITSIZE (extzv_mode) >= bitsize)
          && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
-               && (bitsize + bitpos > extzv_bitsize)))
+               && (bitsize + bitpos > GET_MODE_BITSIZE (extzv_mode))))
        {
          unsigned HOST_WIDE_INT xbitpos = bitpos, xoffset = offset;
          rtx bitsize_rtx, bitpos_rtx;
@@ -1233,11 +1242,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          rtx xspec_target = spec_target;
          rtx xspec_target_subreg = spec_target_subreg;
          rtx pat;
-         enum machine_mode maxmode;
-
-         maxmode = insn_data[(int) CODE_FOR_extzv].operand[0].mode;
-         if (maxmode == VOIDmode)
-           maxmode = word_mode;
+         enum machine_mode maxmode = mode_for_extraction (EP_extzv, 0);
 
          if (GET_CODE (xop0) == MEM)
            {
@@ -1260,14 +1265,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                  if (GET_MODE (xop0) == BLKmode
                      || (GET_MODE_SIZE (GET_MODE (op0))
                          > GET_MODE_SIZE (maxmode)))
-                   bestmode = get_best_mode (bitsize, bitnum, align, maxmode,
+                   bestmode = get_best_mode (bitsize, bitnum,
+                                             MEM_ALIGN (xop0), maxmode,
                                              MEM_VOLATILE_P (xop0));
                  else
                    bestmode = GET_MODE (xop0);
 
                  if (bestmode == VOIDmode
-                     || (SLOW_UNALIGNED_ACCESS (bestmode, align)
-                         && GET_MODE_BITSIZE (bestmode) > align))
+                     || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (xop0))
+                         && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (xop0)))
                    goto extzv_loses;
 
                  /* Compute offset as multiple of this unit,
@@ -1275,9 +1281,8 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                  unit = GET_MODE_BITSIZE (bestmode);
                  xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode);
                  xbitpos = bitnum % unit;
-                 xop0 = change_address (xop0, bestmode,
-                                        plus_constant (XEXP (xop0, 0),
-                                                       xoffset));
+                 xop0 = adjust_address (xop0, bestmode, xoffset);
+
                  /* Fetch it to a register in that size.  */
                  xop0 = force_reg (bestmode, xop0);
 
@@ -1285,8 +1290,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                }
              else
                /* Get ref to first byte containing part of the field.  */
-               xop0 = change_address (xop0, byte_mode,
-                                      plus_constant (XEXP (xop0, 0), xoffset));
+               xop0 = adjust_address (xop0, byte_mode, xoffset);
 
              volatile_ok = save_volatile_ok;
            }
@@ -1349,22 +1353,20 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
            {
              delete_insns_since (last);
              target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
-                                               bitpos, target, 1, align);
+                                               bitpos, target, 1);
            }
        }
       else
-        extzv_loses:
-#endif
-      target = extract_fixed_bit_field (int_mode, op0, offset, bitsize, 
-                                       bitpos, target, 1, align);
+      extzv_loses:
+       target = extract_fixed_bit_field (int_mode, op0, offset, bitsize, 
+                                         bitpos, target, 1);
     }
   else
     {
-#ifdef HAVE_extv
       if (HAVE_extv
-         && (extv_bitsize >= bitsize)
+         && (GET_MODE_BITSIZE (extv_mode) >= bitsize)
          && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
-               && (bitsize + bitpos > extv_bitsize)))
+               && (bitsize + bitpos > GET_MODE_BITSIZE (extv_mode))))
        {
          int xbitpos = bitpos, xoffset = offset;
          rtx bitsize_rtx, bitpos_rtx;
@@ -1373,11 +1375,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          rtx xspec_target = spec_target;
          rtx xspec_target_subreg = spec_target_subreg;
          rtx pat;
-         enum machine_mode maxmode;
-
-         maxmode = insn_data[(int) CODE_FOR_extv].operand[0].mode;
-         if (maxmode == VOIDmode)
-           maxmode = word_mode;
+         enum machine_mode maxmode = mode_for_extraction (EP_extv, 0);
 
          if (GET_CODE (xop0) == MEM)
            {
@@ -1397,14 +1395,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                  if (GET_MODE (xop0) == BLKmode
                      || (GET_MODE_SIZE (GET_MODE (op0))
                          > GET_MODE_SIZE (maxmode)))
-                   bestmode = get_best_mode (bitsize, bitnum, align, maxmode,
+                   bestmode = get_best_mode (bitsize, bitnum,
+                                             MEM_ALIGN (xop0), maxmode,
                                              MEM_VOLATILE_P (xop0));
                  else
                    bestmode = GET_MODE (xop0);
 
                  if (bestmode == VOIDmode
-                     || (SLOW_UNALIGNED_ACCESS (bestmode, align)
-                         && GET_MODE_BITSIZE (bestmode) > align))
+                     || (SLOW_UNALIGNED_ACCESS (bestmode, MEM_ALIGN (xop0))
+                         && GET_MODE_BITSIZE (bestmode) > MEM_ALIGN (xop0)))
                    goto extv_loses;
 
                  /* Compute offset as multiple of this unit,
@@ -1412,9 +1411,8 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                  unit = GET_MODE_BITSIZE (bestmode);
                  xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode);
                  xbitpos = bitnum % unit;
-                 xop0 = change_address (xop0, bestmode,
-                                        plus_constant (XEXP (xop0, 0),
-                                                       xoffset));
+                 xop0 = adjust_address (xop0, bestmode, xoffset);
+
                  /* Fetch it to a register in that size.  */
                  xop0 = force_reg (bestmode, xop0);
 
@@ -1422,8 +1420,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                }
              else
                /* Get ref to first byte containing part of the field.  */
-               xop0 = change_address (xop0, byte_mode,
-                                      plus_constant (XEXP (xop0, 0), xoffset));
+               xop0 = adjust_address (xop0, byte_mode, xoffset);
            }
 
          /* If op0 is a register, we need it in MAXMODE (which is usually
@@ -1485,14 +1482,13 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
            {
              delete_insns_since (last);
              target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
-                                               bitpos, target, 0, align);
+                                               bitpos, target, 0);
            }
        } 
       else
-       extv_loses:
-#endif
-      target = extract_fixed_bit_field (int_mode, op0, offset, bitsize, 
-                                       bitpos, target, 0, align);
+      extv_loses:
+       target = extract_fixed_bit_field (int_mode, op0, offset, bitsize, 
+                                         bitpos, target, 0);
     }
   if (target == spec_target)
     return target;
@@ -1532,18 +1528,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
    UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value).
    If TARGET is nonzero, attempts to store the value there
    and return TARGET, but this is not guaranteed.
-   If TARGET is not used, create a pseudo-reg of mode TMODE for the value.
-
-   ALIGN is the alignment that STR_RTX is known to have.  */
+   If TARGET is not used, create a pseudo-reg of mode TMODE for the value.  */
 
 static rtx
 extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
-                        target, unsignedp, align)
+                        target, unsignedp)
      enum machine_mode tmode;
-     register rtx op0, target;
+     rtx op0, target;
      unsigned HOST_WIDE_INT offset, bitsize, bitpos;
      int unsignedp;
-     unsigned int align;
 {
   unsigned int total_bits = BITS_PER_WORD;
   enum machine_mode mode;
@@ -1552,8 +1545,7 @@ extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
     {
       /* Special treatment for a bit field split across two registers.  */
       if (bitsize + bitpos > BITS_PER_WORD)
-       return extract_split_bit_field (op0, bitsize, bitpos,
-                                       unsignedp, align);
+       return extract_split_bit_field (op0, bitsize, bitpos, unsignedp);
     }
   else
     {
@@ -1561,16 +1553,15 @@ extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
         includes the entire field.  If such a mode would be larger than
         a word, we won't be doing the extraction the normal way.  */
 
-      mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT, align,
-                           word_mode,
-                           GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0));
+      mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
+                           MEM_ALIGN (op0), word_mode, MEM_VOLATILE_P (op0));
 
       if (mode == VOIDmode)
        /* The only way this should occur is if the field spans word
           boundaries.  */
        return extract_split_bit_field (op0, bitsize,
                                        bitpos + offset * BITS_PER_UNIT,
-                                       unsignedp, align);
+                                       unsignedp);
 
       total_bits = GET_MODE_BITSIZE (mode);
 
@@ -1590,19 +1581,15 @@ extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
         Then alter OP0 to refer to that word.  */
       bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT;
       offset -= (offset % (total_bits / BITS_PER_UNIT));
-      op0 = change_address (op0, mode,
-                           plus_constant (XEXP (op0, 0), offset));
+      op0 = adjust_address (op0, mode, offset);
     }
 
   mode = GET_MODE (op0);
 
   if (BYTES_BIG_ENDIAN)
-    {
-      /* BITPOS is the distance between our msb and that of OP0.
-        Convert it to the distance from the lsb.  */
-
-      bitpos = total_bits - bitsize - bitpos;
-    }
+    /* BITPOS is the distance between our msb and that of OP0.
+       Convert it to the distance from the lsb.  */
+    bitpos = total_bits - bitsize - bitpos;
 
   /* Now BITPOS is always the distance between the field's lsb and that of OP0.
      We have reduced the big-endian case to the little-endian case.  */
@@ -1663,7 +1650,8 @@ extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
 
   if (GET_MODE_BITSIZE (mode) != (bitsize + bitpos))
     {
-      tree amount = build_int_2 (GET_MODE_BITSIZE (mode) - (bitsize + bitpos), 0);
+      tree amount
+       = build_int_2 (GET_MODE_BITSIZE (mode) - (bitsize + bitpos), 0);
       /* Maybe propagate the target for the shift.  */
       /* But not if we will return the result--could confuse integrate.c.  */
       rtx subtarget = (target != 0 && GET_CODE (target) == REG
@@ -1753,17 +1741,13 @@ lshift_value (mode, value, bitpos, bitsize)
 
    OP0 is the REG, SUBREG or MEM rtx for the first of the two words.
    BITSIZE is the field width; BITPOS, position of its first bit, in the word.
-   UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend.
-
-   ALIGN is the known alignment of OP0.  This is also the size of the
-   memory objects to be used.  */
+   UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend.  */
 
 static rtx
-extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align)
+extract_split_bit_field (op0, bitsize, bitpos, unsignedp)
      rtx op0;
      unsigned HOST_WIDE_INT bitsize, bitpos;
      int unsignedp;
-     unsigned int align;
 {
   unsigned int unit;
   unsigned int bitsdone = 0;
@@ -1775,7 +1759,7 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align)
   if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
     unit = BITS_PER_WORD;
   else
-    unit = MIN (align, BITS_PER_WORD);
+    unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD);
 
   while (bitsdone < bitsize)
     {
@@ -1801,8 +1785,8 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align)
         the current word starting from the base register.  */
       if (GET_CODE (op0) == SUBREG)
        {
-         word = operand_subword_force (SUBREG_REG (op0),
-                                       SUBREG_WORD (op0) + offset,
+         int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
+         word = operand_subword_force (SUBREG_REG (op0), word_offset,
                                        GET_MODE (SUBREG_REG (op0)));
          offset = 0;
        }
@@ -1820,7 +1804,7 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align)
         extract_fixed_bit_field wants offset in bytes.  */
       part = extract_fixed_bit_field (word_mode, word,
                                      offset * unit / BITS_PER_UNIT,
-                                     thissize, thispos, 0, 1, align);
+                                     thissize, thispos, 0, 1);
       bitsdone += thissize;
 
       /* Shift this part into place for the result.  */
@@ -1895,15 +1879,15 @@ expand_dec (target, dec)
 rtx
 expand_shift (code, mode, shifted, amount, target, unsignedp)
      enum tree_code code;
-     register enum machine_mode mode;
+     enum machine_mode mode;
      rtx shifted;
      tree amount;
-     register rtx target;
+     rtx target;
      int unsignedp;
 {
-  register rtx op1, temp = 0;
-  register int left = (code == LSHIFT_EXPR || code == LROTATE_EXPR);
-  register int rotate = (code == LROTATE_EXPR || code == RROTATE_EXPR);
+  rtx op1, temp = 0;
+  int left = (code == LSHIFT_EXPR || code == LROTATE_EXPR);
+  int rotate = (code == LROTATE_EXPR || code == RROTATE_EXPR);
   int try;
 
   /* Previously detected shift-counts computed by NEGATE_EXPR
@@ -1921,7 +1905,7 @@ expand_shift (code, mode, shifted, amount, target, unsignedp)
         op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
                       % GET_MODE_BITSIZE (mode));
       else if (GET_CODE (op1) == SUBREG
-              && SUBREG_WORD (op1) == 0)
+              && SUBREG_BYTE (op1) == 0)
        op1 = SUBREG_REG (op1);
     }
 #endif
@@ -1988,7 +1972,8 @@ expand_shift (code, mode, shifted, amount, target, unsignedp)
             that is in range, try a rotate in the opposite direction.  */
 
          if (temp == 0 && GET_CODE (op1) == CONST_INT
-             && INTVAL (op1) > 0 && INTVAL (op1) < GET_MODE_BITSIZE (mode))
+             && INTVAL (op1) > 0
+             && (unsigned int) INTVAL (op1) < GET_MODE_BITSIZE (mode))
            temp = expand_binop (mode,
                                 left ? rotr_optab : rotl_optab,
                                 shifted, 
@@ -2334,7 +2319,7 @@ synth_mult (alg_out, t, cost_limit)
 rtx
 expand_mult (mode, op0, op1, target, unsignedp)
      enum machine_mode mode;
-     register rtx op0, op1, target;
+     rtx op0, op1, target;
      int unsignedp;
 {
   rtx const_op1 = op1;
@@ -2374,6 +2359,10 @@ expand_mult (mode, op0, op1, target, unsignedp)
       int mult_cost;
       enum {basic_variant, negate_variant, add_variant} variant = basic_variant;
 
+      /* op0 must be register to make mult_cost match the precomputed
+         shiftadd_cost array.  */
+      op0 = force_reg (mode, op0);
+
       /* Try to do the computation three ways: multiply by the negative of OP1
         and then negate, do the multiplication directly, or do multiplication
         by OP1 - 1.  */
@@ -2720,7 +2709,7 @@ invert_mod2n (x, n)
 rtx
 expand_mult_highpart_adjust (mode, adj_operand, op0, op1, target, unsignedp)
      enum machine_mode mode;
-     register rtx adj_operand, op0, op1, target;
+     rtx adj_operand, op0, op1, target;
      int unsignedp;
 {
   rtx tem;
@@ -2757,7 +2746,7 @@ expand_mult_highpart_adjust (mode, adj_operand, op0, op1, target, unsignedp)
 rtx
 expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
      enum machine_mode mode;
-     register rtx op0, target;
+     rtx op0, target;
      unsigned HOST_WIDE_INT cnst1;
      int unsignedp;
      int max_cost;
@@ -2773,7 +2762,7 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
   if (size > HOST_BITS_PER_WIDE_INT)
     abort ();
 
-  op1 = GEN_INT (cnst1);
+  op1 = GEN_INT (trunc_int_for_mode (cnst1, mode));
 
   if (GET_MODE_BITSIZE (wider_mode) <= HOST_BITS_PER_INT)
     wide_op1 = op1;
@@ -2939,11 +2928,11 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
      int rem_flag;
      enum tree_code code;
      enum machine_mode mode;
-     register rtx op0, op1, target;
+     rtx op0, op1, target;
      int unsignedp;
 {
   enum machine_mode compute_mode;
-  register rtx tquotient;
+  rtx tquotient;
   rtx quotient = 0, remainder = 0;
   rtx last;
   int size;
@@ -3260,7 +3249,7 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                if (rem_flag && d < 0)
                  {
                    d = abs_d;
-                   op1 = GEN_INT (abs_d);
+                   op1 = GEN_INT (trunc_int_for_mode (abs_d, compute_mode));
                  }
 
                if (d == 1)
@@ -3290,7 +3279,8 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                        t1 = copy_to_mode_reg (compute_mode, op0);
                        do_cmp_and_jump (t1, const0_rtx, GE,
                                         compute_mode, label);
-                       expand_inc (t1, GEN_INT (abs_d - 1));
+                       expand_inc (t1, GEN_INT (trunc_int_for_mode
+                                                (abs_d - 1, compute_mode)));
                        emit_label (label);
                        quotient = expand_shift (RSHIFT_EXPR, compute_mode, t1,
                                                 build_int_2 (lgup, 0),
@@ -3327,7 +3317,10 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                                               REG_EQUAL,
                                               gen_rtx_DIV (compute_mode,
                                                            op0,
-                                                           GEN_INT (abs_d)));
+                                                           GEN_INT
+                                                           (trunc_int_for_mode
+                                                            (abs_d,
+                                                             compute_mode))));
 
                        quotient = expand_unop (compute_mode, neg_optab,
                                                quotient, quotient, 0);
@@ -3826,8 +3819,10 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
            ml = invert_mod2n (d >> pre_shift, size);
            t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
                               build_int_2 (pre_shift, 0), NULL_RTX, unsignedp);
-           quotient = expand_mult (compute_mode, t1, GEN_INT (ml), NULL_RTX,
-                                   0);
+           quotient = expand_mult (compute_mode, t1,
+                                   GEN_INT (trunc_int_for_mode
+                                            (ml, compute_mode)),
+                                   NULL_RTX, 0);
 
            insn = get_last_insn ();
            set_unique_reg_note (insn,
@@ -4007,7 +4002,7 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
 /* Return a tree node with data type TYPE, describing the value of X.
    Usually this is an RTL_EXPR, if there is no obvious better choice.
    X may be an expression, however we only support those expressions
-   generated by loop.c.   */
+   generated by loop.c.  */
 
 tree
 make_tree (type, x)
@@ -4204,8 +4199,7 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
   /* 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;
@@ -4335,7 +4329,7 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
       last = get_last_insn ();
 
       comparison
-       = compare_from_rtx (op0, op1, code, unsignedp, mode, NULL_RTX, 0);
+       = compare_from_rtx (op0, op1, code, unsignedp, mode, NULL_RTX);
       if (GET_CODE (comparison) == CONST_INT)
        return (comparison == const0_rtx ? const0_rtx
                : normalizep == 1 ? const1_rtx
@@ -4541,7 +4535,7 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
 
       /* Note that ABS doesn't yield a positive number for INT_MIN, but 
         that is compensated by the subsequent overflow when subtracting 
-        one / negating. */
+        one / negating.  */
 
       if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
        tem = expand_unop (mode, abs_optab, op0, subtarget, 1);
@@ -4635,7 +4629,7 @@ emit_store_flag_force (target, code, op0, op1, mode, unsignedp, normalizep)
 
   emit_move_insn (target, const1_rtx);
   label = gen_label_rtx ();
-  do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX, 0,
+  do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX,
                           NULL_RTX, label);
 
   emit_move_insn (target, const0_rtx);
@@ -4710,7 +4704,5 @@ do_cmp_and_jump (arg1, arg2, op, mode, label)
       emit_label (label2);
     }
   else
-    {
-      emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, 0, label);
-    }
+    emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, label);
 }