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.
 
    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
 
 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"
 
 
 #include "config.h"
@@ -28,32 +28,28 @@ Boston, MA 02111-1307, USA.  */
 #include "tree.h"
 #include "tm_p.h"
 #include "flags.h"
 #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 "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,
 #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,
 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,
 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,
 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));
 
 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
 
 #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;
 /* 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;
 }
 
   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
 \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
    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;
      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;
      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.  */
 
   /* 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.  */
         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);
     }
 
       /* 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)
   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.  */
      
      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))
       && (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
             || (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)
        {
     {
       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)
                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
          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;
        }
       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)
     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
        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.  */
 
   /* 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)
        }
 
       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;
     }
 
       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
             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),
 
          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))),
                                                  (GET_MODE (value) == VOIDmode
                                                   ? fieldmode
                                                   : GET_MODE (value))),
-                          align, total_size);
+                          total_size);
        }
       return value;
     }
        }
       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),
                abort ();
            }
          op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
-                               op0, offset);
+                               op0, (offset * UNITS_PER_WORD));
        }
       offset = 0;
     }
   else
        }
       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
 
   /* 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.  */
 
   /* 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.  */
   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)
       && ! ((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;
     {
       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;
 
       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
       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
          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
                               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;
 
            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);
          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;
          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,
 
          /* 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;
        }
          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)
 
       /* 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.  */
 
       /* 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);
 
       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))
                 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
                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
          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);
       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:
        }
     }
   else
     insv_loses:
-#endif
     /* Insv is not available; store using shifts and boolean ops.  */
     /* 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
   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.)
     (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
 
    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;
      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;
 
   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.
   /* 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)
        {
       /* 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;
        }
     }
          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
     {
       /* 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,
       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.  */
 
       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;
        }
 
          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));
         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);
     }
 
   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)
     {
 
   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;
 
       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.
    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
 
    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;
      rtx op0;
      unsigned HOST_WIDE_INT bitsize, bitpos;
      rtx value;
-     unsigned int align;
 {
   unsigned int unit;
   unsigned int bitsdone = 0;
 {
   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
   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
 
   /* 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
          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
        {
        }
       else
        {
@@ -895,13 +924,8 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
                             >> bitsdone)
                            & (((HOST_WIDE_INT) 1 << thissize) - 1));
          else
                             >> 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.
        }
 
       /* 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)
        {
         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;
        }
                                        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.  */
 
       /* 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;
     }
 }
       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.
 
    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.
 
    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,
 
 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;
      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;
      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;
   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.  */
 
   /* 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)));
 
       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);
 
 
       inner_size = MIN (inner_size, BITS_PER_WORD);
 
@@ -1027,6 +1029,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
       op0 = SUBREG_REG (op0);
     }
 
       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.  */
   {
   /* 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)
     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
        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
        && 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
               || (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
       && ((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)
                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
          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);
        }
       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,
            = 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 ();
 
          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++)
 
              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;
        }
            }
          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),
          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
        }
       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)
     {
 
   /* Now OFFSET is nonzero only for memory operands.  */
 
   if (unsignedp)
     {
-#ifdef HAVE_extzv
       if (HAVE_extzv
       if (HAVE_extzv
-         && (extzv_bitsize >= bitsize)
+         && (GET_MODE_BITSIZE (extzv_mode) >= bitsize)
          && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
          && ! ((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;
        {
          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;
          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)
            {
 
          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)))
                  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
                                              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,
                    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;
                  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);
 
                  /* 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.  */
                }
              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;
            }
 
              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,
            {
              delete_insns_since (last);
              target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
-                                               bitpos, target, 1, align);
+                                               bitpos, target, 1);
            }
        }
       else
            }
        }
       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
     {
     }
   else
     {
-#ifdef HAVE_extv
       if (HAVE_extv
       if (HAVE_extv
-         && (extv_bitsize >= bitsize)
+         && (GET_MODE_BITSIZE (extv_mode) >= bitsize)
          && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
          && ! ((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;
        {
          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;
          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)
            {
 
          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)))
                  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
                                              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,
                    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;
                  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);
 
                  /* 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.  */
                }
              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
            }
 
          /* 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,
            {
              delete_insns_since (last);
              target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
-                                               bitpos, target, 0, align);
+                                               bitpos, target, 0);
            }
        } 
       else
            }
        } 
       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;
     }
   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.
    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,
 
 static rtx
 extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
-                        target, unsignedp, align)
+                        target, unsignedp)
      enum machine_mode tmode;
      enum machine_mode tmode;
-     register rtx op0, target;
+     rtx op0, target;
      unsigned HOST_WIDE_INT offset, bitsize, bitpos;
      int unsignedp;
      unsigned HOST_WIDE_INT offset, bitsize, bitpos;
      int unsignedp;
-     unsigned int align;
 {
   unsigned int total_bits = BITS_PER_WORD;
   enum machine_mode mode;
 {
   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)
     {
       /* 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
     {
     }
   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.  */
 
         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,
 
       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);
 
 
       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));
         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)
     }
 
   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.  */
 
   /* 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))
     {
 
   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
       /* 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.
 
    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
 
 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;
      rtx op0;
      unsigned HOST_WIDE_INT bitsize, bitpos;
      int unsignedp;
-     unsigned int align;
 {
   unsigned int unit;
   unsigned int bitsdone = 0;
 {
   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
   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)
     {
 
   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)
        {
         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;
        }
                                        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,
         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.  */
       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;
 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;
      rtx shifted;
      tree amount;
-     register rtx target;
+     rtx target;
      int unsignedp;
 {
      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
   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
         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
        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
             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, 
            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;
 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;
      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;
 
       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.  */
       /* 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;
 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;
      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;
 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;
      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 ();
 
   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;
 
   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;
      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;
      int unsignedp;
 {
   enum machine_mode compute_mode;
-  register rtx tquotient;
+  rtx tquotient;
   rtx quotient = 0, remainder = 0;
   rtx last;
   int size;
   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;
                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)
                  }
 
                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);
                        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),
                        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,
                                               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);
 
                        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);
            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,
 
            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
 /* 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)
 
 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 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;
     {
       tem = op0;
       op0 = op1;
@@ -4335,7 +4329,7 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
       last = get_last_insn ();
 
       comparison
       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
       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 
 
       /* 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);
 
       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 ();
 
   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);
                           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_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);
 }
 }