OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / expmed.c
index ec7d0e9..778e990 100644 (file)
@@ -1,6 +1,7 @@
 /* Medium-level subroutines: convert bit-field store and extract
    and shifts, multiplies and divides to rtl instructions.
-   Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -22,8 +23,10 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "toplev.h"
 #include "rtl.h"
 #include "tree.h"
+#include "tm_p.h"
 #include "flags.h"
 #include "insn-flags.h"
 #include "insn-codes.h"
@@ -32,19 +35,27 @@ Boston, MA 02111-1307, USA.  */
 #include "real.h"
 #include "recog.h"
 
-static void store_fixed_bit_field      PROTO((rtx, int, int, int, rtx, int));
-static void store_split_bit_field      PROTO((rtx, int, int, rtx, int));
-static rtx extract_fixed_bit_field     PROTO((enum machine_mode, rtx, int,
-                                              int, int, rtx, int, int));
-static rtx mask_rtx                    PROTO((enum machine_mode, int,
-                                              int, int));
-static rtx lshift_value                        PROTO((enum machine_mode, rtx,
-                                              int, int));
-static rtx extract_split_bit_field     PROTO((rtx, int, int, int, int));
-static void do_cmp_and_jump            PROTO((rtx, rtx, enum rtx_code,
-                                              enum machine_mode, rtx));
-
-#define CEIL(x,y) (((x) + (y) - 1) / (y))
+static void store_fixed_bit_field      PARAMS ((rtx, unsigned HOST_WIDE_INT,
+                                                unsigned HOST_WIDE_INT,
+                                                unsigned HOST_WIDE_INT, rtx,
+                                                unsigned int));
+static void store_split_bit_field      PARAMS ((rtx, unsigned HOST_WIDE_INT,
+                                                unsigned HOST_WIDE_INT, rtx,
+                                                unsigned 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));
+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));
+static void do_cmp_and_jump            PARAMS ((rtx, rtx, enum rtx_code,
+                                                enum machine_mode, rtx));
 
 /* Non-zero means divides or modulus operations are relatively cheap for
    powers of two, so don't use branches; emit the operation instead. 
@@ -54,7 +65,7 @@ static void do_cmp_and_jump           PROTO((rtx, rtx, enum rtx_code,
 static int sdiv_pow2_cheap, smod_pow2_cheap;
 
 #ifndef SLOW_UNALIGNED_ACCESS
-#define SLOW_UNALIGNED_ACCESS STRICT_ALIGNMENT
+#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
 #endif
 
 /* For compilers that support multiple targets with different word sizes,
@@ -65,8 +76,8 @@ static int sdiv_pow2_cheap, smod_pow2_cheap;
 #define MAX_BITS_PER_WORD BITS_PER_WORD
 #endif
 
-/* Cost of various pieces of RTL.  Note that some of these are indexed by shift count,
-   and some by mode.  */
+/* Cost of various pieces of RTL.  Note that some of these are indexed by
+   shift count and some by mode.  */
 static int add_cost, negate_cost, zero_cost;
 static int shift_cost[MAX_BITS_PER_WORD];
 static int shiftadd_cost[MAX_BITS_PER_WORD];
@@ -79,7 +90,6 @@ static int mul_highpart_cost[NUM_MACHINE_MODES];
 void
 init_expmed ()
 {
-  char *free_point;
   /* This is "some random pseudo register" for purposes of calling recog
      to see what insns exist.  */
   rtx reg = gen_rtx_REG (word_mode, 10000);
@@ -90,12 +100,7 @@ init_expmed ()
 
   start_sequence ();
 
-  /* Since we are on the permanent obstack, we must be sure we save this
-     spot AFTER we call start_sequence, since it will reuse the rtl it
-     makes.  */
-  free_point = (char *) oballoc (0);
-
-  reg = gen_rtx (REG, word_mode, 10000);
+  reg = gen_rtx_REG (word_mode, 10000);
 
   zero_cost = rtx_cost (const0_rtx, 0);
   add_cost = rtx_cost (gen_rtx_PLUS (word_mode, reg, reg), SET);
@@ -169,19 +174,18 @@ init_expmed ()
          mul_highpart_cost[(int) mode]
            = rtx_cost (gen_rtx_TRUNCATE
                        (mode,
-                        gen_rtx_LSHIFTRT
-                        (wider_mode,
-                         gen_rtx_MULT (wider_mode,
-                                       gen_rtx_ZERO_EXTEND (wider_mode, reg),
-                                       gen_rtx_ZERO_EXTEND (wider_mode, reg)),
-                         GEN_INT (GET_MODE_BITSIZE (mode)))),
+                        gen_rtx_LSHIFTRT (wider_mode,
+                                          gen_rtx_MULT (wider_mode,
+                                                        gen_rtx_ZERO_EXTEND
+                                                        (wider_mode, reg),
+                                                        gen_rtx_ZERO_EXTEND
+                                                        (wider_mode, reg)),
+                                          GEN_INT (GET_MODE_BITSIZE (mode)))),
                        SET);
        }
     }
 
-  /* Free the objects we just allocated.  */
   end_sequence ();
-  obfree (free_point);
 }
 
 /* Return an rtx representing minus the value of X.
@@ -205,7 +209,7 @@ negate_rtx (mode, x)
    into a bit-field within structure STR_RTX
    containing BITSIZE bits starting at bit BITNUM.
    FIELDMODE is the machine-mode of the FIELD_DECL node for this field.
-   ALIGN is the alignment that STR_RTX is known to have, measured in bytes.
+   ALIGN is the alignment that STR_RTX is known to have.
    TOTAL_SIZE is the size of the structure in bytes, or -1 if varying.  */
 
 /* ??? Note that there are two different ideas here for how
@@ -219,24 +223,26 @@ negate_rtx (mode, x)
 rtx
 store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
      rtx str_rtx;
-     register int bitsize;
-     int bitnum;
+     unsigned HOST_WIDE_INT bitsize;
+     unsigned HOST_WIDE_INT bitnum;
      enum machine_mode fieldmode;
      rtx value;
-     int align;
-     int total_size;
+     unsigned int align;
+     HOST_WIDE_INT total_size;
 {
-  int unit = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
-  register int offset = bitnum / unit;
-  register int bitpos = bitnum % unit;
+  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
-  int insv_bitsize;
+  unsigned HOST_WIDE_INT insv_bitsize;
+  enum machine_mode op_mode;
 
-  if (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode)
-    insv_bitsize = GET_MODE_BITSIZE (word_mode);
-  else
-    insv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]);
+  op_mode = insn_data[(int) CODE_FOR_insv].operand[3].mode;
+  if (op_mode == VOIDmode)
+    op_mode = word_mode;
+  insv_bitsize = GET_MODE_BITSIZE (op_mode);
 #endif
 
   if (GET_CODE (str_rtx) == MEM && ! MEM_IN_STRUCT_P (str_rtx))
@@ -289,16 +295,18 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
   if (flag_force_mem)
     value = force_not_mem (value);
 
-  /* Note that the adjustment of BITPOS above has no effect on whether
-     BITPOS is 0 in a REG bigger than a word.  */
-  if (GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
+  if ((GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
+       || (GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode)
+          && GET_MODE_SIZE (fieldmode) != 0))
       && (GET_CODE (op0) != MEM
-         || ! SLOW_UNALIGNED_ACCESS
+         || ! SLOW_UNALIGNED_ACCESS (fieldmode, align)
          || (offset * BITS_PER_UNIT % bitsize == 0
-             && align % GET_MODE_SIZE (fieldmode) == 0))
-      && bitpos == 0 && bitsize == GET_MODE_BITSIZE (fieldmode))
+             && align % GET_MODE_BITSIZE (fieldmode) == 0))
+      && (BYTES_BIG_ENDIAN ? bitpos + bitsize == unit : bitpos == 0)
+      && bitsize == GET_MODE_BITSIZE (fieldmode))
     {
       /* Storing in a full-word or multi-word field in a register
+        can be done with just SUBREG.  Also, storing in the entire object
         can be done with just SUBREG.  */
       if (GET_MODE (op0) != fieldmode)
        {
@@ -330,10 +338,11 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
   if (GET_CODE (op0) != MEM
       && (BYTES_BIG_ENDIAN ? bitpos + bitsize == unit : bitpos == 0)
       && bitsize == GET_MODE_BITSIZE (fieldmode)
-      && (GET_MODE (op0) == fieldmode
-         || (movstrict_optab->handlers[(int) fieldmode].insn_code
-             != CODE_FOR_nothing)))
+      && (movstrict_optab->handlers[(int) fieldmode].insn_code
+         != CODE_FOR_nothing))
     {
+      int icode = movstrict_optab->handlers[(int) fieldmode].insn_code;
+
       /* Get appropriate low part of the value being stored.  */
       if (GET_CODE (value) == CONST_INT || GET_CODE (value) == REG)
        value = gen_lowpart (fieldmode, value);
@@ -342,30 +351,25 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
                 || GET_CODE (value) == CONST))
        value = convert_to_mode (fieldmode, value, 0);
 
-      if (GET_MODE (op0) == fieldmode)
-       emit_move_insn (op0, value);
-      else
+      if (! (*insn_data[icode].operand[1].predicate) (value, fieldmode))
+       value = copy_to_mode_reg (fieldmode, value);
+
+      if (GET_CODE (op0) == SUBREG)
        {
-         int icode = movstrict_optab->handlers[(int) fieldmode].insn_code;
-         if (! (*insn_operand_predicate[icode][1]) (value, fieldmode))
-           value = copy_to_mode_reg (fieldmode, value);
+         if (GET_MODE (SUBREG_REG (op0)) == fieldmode
+             || GET_MODE_CLASS (fieldmode) == MODE_INT
+             || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT)
+           op0 = SUBREG_REG (op0);
+         else
+           /* Else we've got some float mode source being extracted into
+              a different float mode destination -- this combination of
+              subregs results in Severe Tire Damage.  */
+           abort ();
+       }
 
-         if (GET_CODE (op0) == SUBREG)
-           {
-             if (GET_MODE (SUBREG_REG (op0)) == fieldmode
-                 || GET_MODE_CLASS (fieldmode) == MODE_INT
-                 || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT)
-               op0 = SUBREG_REG (op0);
-             else
-               /* Else we've got some float mode source being extracted into
-                  a different float mode destination -- this combination of
-                  subregs results in Severe Tire Damage.  */
-               abort ();
-           }
+      emit_insn (GEN_FCN (icode)
+                (gen_rtx_SUBREG (fieldmode, op0, offset), value));
 
-         emit_insn (GEN_FCN (icode)
-                  (gen_rtx_SUBREG (fieldmode, op0, offset), value));
-       }
       return value;
     }
 
@@ -379,10 +383,9 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
         be less than full.
         However, only do that if the value is not BLKmode.  */
 
-      int backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
-
-      int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
-      int i;
+      unsigned int backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
+      unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
+      unsigned int i;
 
       /* This is the mode we must force value to, so that there will be enough
         subwords to extract.  Note that fieldmode will often (always?) be
@@ -395,10 +398,13 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
        {
          /* If I is 0, use the low-order word in both field and target;
             if I is 1, use the next to lowest word; and so on.  */
-         int wordnum = (backwards ? nwords - i - 1 : i);
-         int bit_offset = (backwards
-                           ? MAX (bitsize - (i + 1) * BITS_PER_WORD, 0)
-                           : i * BITS_PER_WORD);
+         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);
+
          store_bit_field (op0, MIN (BITS_PER_WORD,
                                     bitsize - i * BITS_PER_WORD),
                           bitnum + bit_offset, word_mode,
@@ -476,7 +482,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
       enum machine_mode maxmode;
       int save_volatile_ok = volatile_ok;
 
-      maxmode = insn_operand_mode[(int) CODE_FOR_insv][3];
+      maxmode = insn_data[(int) CODE_FOR_insv].operand[3].mode;
       if (maxmode == VOIDmode)
        maxmode = word_mode;
 
@@ -487,7 +493,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
       /* This used to check flag_force_mem, but that was a serious
         de-optimization now that flag_force_mem is enabled by -O2.  */
       if (GET_CODE (op0) == MEM
-         && ! ((*insn_operand_predicate[(int) CODE_FOR_insv][0])
+         && ! ((*insn_data[(int) CODE_FOR_insv].operand[0].predicate)
                (op0, VOIDmode)))
        {
          rtx tempreg;
@@ -501,13 +507,14 @@ 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 * BITS_PER_UNIT, maxmode,
+             = get_best_mode (bitsize, bitnum, align, maxmode,
                               MEM_VOLATILE_P (op0));
          else
            bestmode = GET_MODE (op0);
 
          if (bestmode == VOIDmode
-             || (SLOW_UNALIGNED_ACCESS && GET_MODE_SIZE (bestmode) > align))
+             || (SLOW_UNALIGNED_ACCESS (bestmode, align)
+                 && GET_MODE_BITSIZE (bestmode) > align))
            goto insv_loses;
 
          /* Adjust address to point to the containing unit of that mode.  */
@@ -518,7 +525,8 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
          op0 = change_address (op0, bestmode, 
                                plus_constant (XEXP (op0, 0), offset));
 
-         /* Fetch that unit, store the bitfield in it, then store the unit.  */
+         /* 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);
@@ -584,7 +592,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
 
       /* If this machine's insv insists on a register,
         get VALUE1 into a register.  */
-      if (! ((*insn_operand_predicate[(int) CODE_FOR_insv][3])
+      if (! ((*insn_data[(int) CODE_FOR_insv].operand[3].predicate)
             (value1, maxmode)))
        value1 = force_reg (maxmode, value1);
 
@@ -613,25 +621,25 @@ 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 (in bytes).
+   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;
-     register int offset, bitsize, bitpos;
+     unsigned HOST_WIDE_INT offset, bitsize, bitpos;
      register rtx value;
-     int struct_align;
+     unsigned int struct_align;
 {
   register enum machine_mode mode;
-  int total_bits = BITS_PER_WORD;
+  unsigned int total_bits = BITS_PER_WORD;
   rtx subtarget, temp;
   int all_zero = 0;
   int all_one = 0;
 
-  if (! SLOW_UNALIGNED_ACCESS)
-    struct_align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+  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
@@ -659,7 +667,7 @@ store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align)
         a word, we won't be doing the extraction the normal way.  */
 
       mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
-                           struct_align * BITS_PER_UNIT, word_mode,
+                           struct_align, word_mode,
                            GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0));
 
       if (mode == VOIDmode)
@@ -783,7 +791,7 @@ 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, measured in bytes.
+   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.  */
@@ -791,19 +799,19 @@ store_fixed_bit_field (op0, offset, bitsize, bitpos, value, struct_align)
 static void
 store_split_bit_field (op0, bitsize, bitpos, value, align)
      rtx op0;
-     int bitsize, bitpos;
+     unsigned HOST_WIDE_INT bitsize, bitpos;
      rtx value;
-     int align;
+     unsigned int align;
 {
-  int unit;
-  int bitsdone = 0;
+  unsigned int unit;
+  unsigned int bitsdone = 0;
 
   /* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that
      much at a time.  */
   if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
     unit = BITS_PER_WORD;
   else
-    unit = MIN (align * BITS_PER_UNIT, BITS_PER_WORD);
+    unit = MIN (align, 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
@@ -825,10 +833,10 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
 
   while (bitsdone < bitsize)
     {
-      int thissize;
+      unsigned HOST_WIDE_INT thissize;
       rtx part, word;
-      int thispos;
-      int offset;
+      unsigned HOST_WIDE_INT thispos;
+      unsigned HOST_WIDE_INT offset;
 
       offset = (bitpos + bitsdone) / unit;
       thispos = (bitpos + bitsdone) % unit;
@@ -870,8 +878,7 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
                 GET_MODE (value) == VOIDmode
                 ? UNITS_PER_WORD
                 : (GET_MODE (value) == BLKmode
-                   ? 1
-                   : GET_MODE_ALIGNMENT (GET_MODE (value)) / BITS_PER_UNIT));
+                   ? 1 : GET_MODE_ALIGNMENT (GET_MODE (value))));
        }
       else
        {
@@ -887,8 +894,7 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
                 GET_MODE (value) == VOIDmode
                 ? UNITS_PER_WORD
                 : (GET_MODE (value) == BLKmode
-                   ? 1
-                   : GET_MODE_ALIGNMENT (GET_MODE (value)) / BITS_PER_UNIT));
+                   ? 1 : GET_MODE_ALIGNMENT (GET_MODE (value))));
        }
 
       /* If OP0 is a register, then handle OFFSET here.
@@ -932,7 +938,7 @@ 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, measured in bytes.
+   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.
 
@@ -945,40 +951,43 @@ rtx
 extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                   target, mode, tmode, align, total_size)
      rtx str_rtx;
-     register int bitsize;
-     int bitnum;
+     unsigned HOST_WIDE_INT bitsize;
+     unsigned HOST_WIDE_INT bitnum;
      int unsignedp;
      rtx target;
      enum machine_mode mode, tmode;
-     int align;
-     int total_size;
+     unsigned int align;
+     HOST_WIDE_INT total_size;
 {
-  int unit = (GET_CODE (str_rtx) == MEM) ? BITS_PER_UNIT : BITS_PER_WORD;
-  register int offset = bitnum / unit;
-  register int bitpos = bitnum % unit;
+  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 spec_target = target;
   rtx spec_target_subreg = 0;
+  enum machine_mode int_mode;
 #ifdef HAVE_extv
-  int extv_bitsize;
+  unsigned HOST_WIDE_INT extv_bitsize;
+  enum machine_mode extv_mode;
 #endif
 #ifdef HAVE_extzv
-  int extzv_bitsize;
+  unsigned HOST_WIDE_INT extzv_bitsize;
+  enum machine_mode extzv_mode;
 #endif
 
 #ifdef HAVE_extv
-  if (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode)
-    extv_bitsize = GET_MODE_BITSIZE (word_mode);
-  else
-    extv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]);
+  extv_mode = insn_data[(int) CODE_FOR_extv].operand[0].mode;
+  if (extv_mode == VOIDmode)
+    extv_mode = word_mode;
+  extv_bitsize = GET_MODE_BITSIZE (extv_mode);
 #endif
 
 #ifdef HAVE_extzv
-  if (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode)
-    extzv_bitsize = GET_MODE_BITSIZE (word_mode);
-  else
-    extzv_bitsize
-      = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]);
+  extzv_mode = insn_data[(int) CODE_FOR_extzv].operand[0].mode;
+  if (extzv_mode == VOIDmode)
+    extzv_mode = word_mode;
+  extzv_bitsize = GET_MODE_BITSIZE (extzv_mode);
 #endif
 
   /* Discount the part of the structure before the desired byte.
@@ -1048,9 +1057,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
+          && (! SLOW_UNALIGNED_ACCESS (mode, align)
               || (offset * BITS_PER_UNIT % bitsize == 0
-                  && align * BITS_PER_UNIT % bitsize == 0))))
+                  && align % 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
@@ -1063,7 +1072,8 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                  : bitpos == 0))))
     {
       enum machine_mode mode1
-       = mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0);
+       = (VECTOR_MODE_P (tmode) ? mode
+          : mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0));
 
       if (mode1 != GET_MODE (op0))
        {
@@ -1099,8 +1109,8 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
         This is because the most significant word is the one which may
         be less than full.  */
 
-      int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
-      int i;
+      unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
+      unsigned int i;
 
       if (target == 0 || GET_CODE (target) != REG)
        target = gen_reg_rtx (mode);
@@ -1113,20 +1123,21 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          /* If I is 0, use the low-order word in both field and target;
             if I is 1, use the next to lowest word; and so on.  */
          /* Word number in TARGET to use.  */
-         int wordnum = (WORDS_BIG_ENDIAN
-                        ? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1
-                        : i);
+         unsigned int wordnum
+           = (WORDS_BIG_ENDIAN
+              ? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1
+              : i);
          /* Offset from start of field in OP0.  */
-         int bit_offset = (WORDS_BIG_ENDIAN
-                           ? MAX (0, bitsize - (i + 1) * BITS_PER_WORD)
-                           : i * BITS_PER_WORD);
+         unsigned int bit_offset = (WORDS_BIG_ENDIAN
+                                    ? MAX (0, ((int) bitsize - ((int) i + 1)
+                                               * (int) BITS_PER_WORD))
+                                    : (int) i * BITS_PER_WORD);
          rtx target_part = operand_subword (target, wordnum, 1, VOIDmode);
          rtx result_part
            = 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);
+                                bitnum + bit_offset, 1, target_part, mode,
+                                word_mode, align, total_size);
 
          if (target_part == 0)
            abort ();
@@ -1141,7 +1152,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
             need to be zero'd out.  */
          if (GET_MODE_SIZE (GET_MODE (target)) > nwords * UNITS_PER_WORD)
            {
-             int i,total_words;
+             unsigned int i, total_words;
 
              total_words = GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD;
              for (i = nwords; i < total_words; i++)
@@ -1163,10 +1174,19 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
                           NULL_RTX, 0);
     }
   
-  /* From here on we know the desired field is smaller than a word
-     so we can assume it is an integer.  So we can safely extract it as one
-     size of integer, if necessary, and then truncate or extend
-     to the size that is wanted.  */
+  /* From here on we know the desired field is smaller than a word.  */
+
+  /* Check if there is a correspondingly-sized integer field, so we can
+     safely extract it as one size of integer, if necessary; then
+     truncate or extend to the size that is wanted; then use SUBREGs or
+     convert_to_mode to get one of the modes we really wanted.  */
+  
+  int_mode = int_mode_for_mode (tmode);
+  if (int_mode == BLKmode)
+    int_mode = int_mode_for_mode (mode);
+  if (int_mode == BLKmode)
+    abort();    /* Should probably push op0 out to memory and then
+                  do a load.  */
 
   /* OFFSET is the number of words or bytes (UNIT says which)
      from STR_RTX to the first word or byte containing part of the field.  */
@@ -1198,7 +1218,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
                && (bitsize + bitpos > extzv_bitsize)))
        {
-         int xbitpos = bitpos, xoffset = offset;
+         unsigned HOST_WIDE_INT xbitpos = bitpos, xoffset = offset;
          rtx bitsize_rtx, bitpos_rtx;
          rtx last = get_last_insn ();
          rtx xop0 = op0;
@@ -1208,7 +1228,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          rtx pat;
          enum machine_mode maxmode;
 
-         maxmode = insn_operand_mode[(int) CODE_FOR_extzv][0];
+         maxmode = insn_data[(int) CODE_FOR_extzv].operand[0].mode;
          if (maxmode == VOIDmode)
            maxmode = word_mode;
 
@@ -1218,7 +1238,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
              volatile_ok = 1;
 
              /* Is the memory operand acceptable?  */
-             if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][1])
+             if (! ((*insn_data[(int) CODE_FOR_extzv].operand[1].predicate)
                     (xop0, GET_MODE (xop0))))
                {
                  /* No, load into a reg and extract from there.  */
@@ -1233,14 +1253,14 @@ 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 * BITS_PER_UNIT, maxmode,
+                   bestmode = get_best_mode (bitsize, bitnum, align, maxmode,
                                              MEM_VOLATILE_P (xop0));
                  else
                    bestmode = GET_MODE (xop0);
 
                  if (bestmode == VOIDmode
-                     || (SLOW_UNALIGNED_ACCESS && GET_MODE_SIZE (bestmode) > align))
+                     || (SLOW_UNALIGNED_ACCESS (bestmode, align)
+                         && GET_MODE_BITSIZE (bestmode) > align))
                    goto extzv_loses;
 
                  /* Compute offset as multiple of this unit,
@@ -1302,7 +1322,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
 
          /* If this machine's extzv insists on a register target,
             make sure we have one.  */
-         if (! ((*insn_operand_predicate[(int) CODE_FOR_extzv][0])
+         if (! ((*insn_data[(int) CODE_FOR_extzv].operand[0].predicate)
                 (xtarget, maxmode)))
            xtarget = gen_reg_rtx (maxmode);
 
@@ -1321,15 +1341,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          else
            {
              delete_insns_since (last);
-             target = extract_fixed_bit_field (tmode, op0, offset, bitsize,
+             target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
                                                bitpos, target, 1, align);
            }
        }
       else
         extzv_loses:
 #endif
-       target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
-                                         target, 1, align);
+      target = extract_fixed_bit_field (int_mode, op0, offset, bitsize, 
+                                       bitpos, target, 1, align);
     }
   else
     {
@@ -1348,14 +1368,14 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          rtx pat;
          enum machine_mode maxmode;
 
-         maxmode = insn_operand_mode[(int) CODE_FOR_extv][0];
+         maxmode = insn_data[(int) CODE_FOR_extv].operand[0].mode;
          if (maxmode == VOIDmode)
            maxmode = word_mode;
 
          if (GET_CODE (xop0) == MEM)
            {
              /* Is the memory operand acceptable?  */
-             if (! ((*insn_operand_predicate[(int) CODE_FOR_extv][1])
+             if (! ((*insn_data[(int) CODE_FOR_extv].operand[1].predicate)
                     (xop0, GET_MODE (xop0))))
                {
                  /* No, load into a reg and extract from there.  */
@@ -1370,14 +1390,14 @@ 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 * BITS_PER_UNIT, maxmode,
+                   bestmode = get_best_mode (bitsize, bitnum, align, maxmode,
                                              MEM_VOLATILE_P (xop0));
                  else
                    bestmode = GET_MODE (xop0);
 
                  if (bestmode == VOIDmode
-                     || (SLOW_UNALIGNED_ACCESS && GET_MODE_SIZE (bestmode) > align))
+                     || (SLOW_UNALIGNED_ACCESS (bestmode, align)
+                         && GET_MODE_BITSIZE (bestmode) > align))
                    goto extv_loses;
 
                  /* Compute offset as multiple of this unit,
@@ -1438,7 +1458,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
 
          /* If this machine's extv insists on a register target,
             make sure we have one.  */
-         if (! ((*insn_operand_predicate[(int) CODE_FOR_extv][0])
+         if (! ((*insn_data[(int) CODE_FOR_extv].operand[0].predicate)
                 (xtarget, maxmode)))
            xtarget = gen_reg_rtx (maxmode);
 
@@ -1457,15 +1477,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
          else
            {
              delete_insns_since (last);
-             target = extract_fixed_bit_field (tmode, op0, offset, bitsize,
+             target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
                                                bitpos, target, 0, align);
            }
        } 
       else
        extv_loses:
 #endif
-       target = extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
-                                         target, 0, align);
+      target = extract_fixed_bit_field (int_mode, op0, offset, bitsize, 
+                                       bitpos, target, 0, align);
     }
   if (target == spec_target)
     return target;
@@ -1507,18 +1527,18 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
    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, measured in bytes.  */
+   ALIGN is the alignment that STR_RTX is known to have.  */
 
 static rtx
 extract_fixed_bit_field (tmode, op0, offset, bitsize, bitpos,
                         target, unsignedp, align)
      enum machine_mode tmode;
      register rtx op0, target;
-     register int offset, bitsize, bitpos;
+     unsigned HOST_WIDE_INT offset, bitsize, bitpos;
      int unsignedp;
-     int align;
+     unsigned int align;
 {
-  int total_bits = BITS_PER_WORD;
+  unsigned int total_bits = BITS_PER_WORD;
   enum machine_mode mode;
 
   if (GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
@@ -1534,8 +1554,8 @@ 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 * BITS_PER_UNIT, word_mode,
+      mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT, align,
+                           word_mode,
                            GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0));
 
       if (mode == VOIDmode)
@@ -1728,16 +1748,18 @@ lshift_value (mode, value, bitpos, bitsize)
    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, measured in bytes.
-   This is also the size of the memory objects to be used.  */
+   ALIGN is the known alignment of OP0.  This is also the size of the
+   memory objects to be used.  */
 
 static rtx
 extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align)
      rtx op0;
-     int bitsize, bitpos, unsignedp, align;
+     unsigned HOST_WIDE_INT bitsize, bitpos;
+     int unsignedp;
+     unsigned int align;
 {
-  int unit;
-  int bitsdone = 0;
+  unsigned int unit;
+  unsigned int bitsdone = 0;
   rtx result = NULL_RTX;
   int first = 1;
 
@@ -1746,14 +1768,14 @@ 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_UNIT, BITS_PER_WORD);
+    unit = MIN (align, BITS_PER_WORD);
 
   while (bitsdone < bitsize)
     {
-      int thissize;
+      unsigned HOST_WIDE_INT thissize;
       rtx part, word;
-      int thispos;
-      int offset;
+      unsigned HOST_WIDE_INT thispos;
+      unsigned HOST_WIDE_INT offset;
 
       offset = (bitpos + bitsdone) / unit;
       thispos = (bitpos + bitsdone) % unit;
@@ -2041,15 +2063,15 @@ struct algorithm
   char log[MAX_BITS_PER_WORD];
 };
 
-static void synth_mult                 PROTO((struct algorithm *,
-                                              unsigned HOST_WIDE_INT,
-                                              int));
-static unsigned HOST_WIDE_INT choose_multiplier PROTO((unsigned HOST_WIDE_INT,
-                                                      int, int,
-                                                      unsigned HOST_WIDE_INT *,
-                                                      int *, int *));
-static unsigned HOST_WIDE_INT invert_mod2n     PROTO((unsigned HOST_WIDE_INT,
-                                                      int));
+static void synth_mult                 PARAMS ((struct algorithm *,
+                                                unsigned HOST_WIDE_INT,
+                                                int));
+static unsigned HOST_WIDE_INT choose_multiplier PARAMS ((unsigned HOST_WIDE_INT,
+                                                        int, int,
+                                                        unsigned HOST_WIDE_INT *,
+                                                        int *, int *));
+static unsigned HOST_WIDE_INT invert_mod2n     PARAMS ((unsigned HOST_WIDE_INT,
+                                                        int));
 /* Compute and return the best algorithm for multiplying by T.
    The algorithm must cost less than cost_limit
    If retval.cost >= COST_LIMIT, no algorithm was found and all
@@ -2418,7 +2440,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                  tem = expand_shift (LSHIFT_EXPR, mode, op0,
                                      build_int_2 (log, 0), NULL_RTX, 0);
                  accum = force_operand (gen_rtx_PLUS (mode, accum, tem),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far += (HOST_WIDE_INT) 1 << log;
                  break;
 
@@ -2426,7 +2449,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                  tem = expand_shift (LSHIFT_EXPR, mode, op0,
                                      build_int_2 (log, 0), NULL_RTX, 0);
                  accum = force_operand (gen_rtx_MINUS (mode, accum, tem),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far -= (HOST_WIDE_INT) 1 << log;
                  break;
 
@@ -2435,7 +2459,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                                        build_int_2 (log, 0), shift_subtarget,
                                        0);
                  accum = force_operand (gen_rtx_PLUS (mode, accum, op0),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far = (val_so_far << log) + 1;
                  break;
 
@@ -2444,7 +2469,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                                        build_int_2 (log, 0), shift_subtarget,
                                        0);
                  accum = force_operand (gen_rtx_MINUS (mode, accum, op0),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far = (val_so_far << log) - 1;
                  break;
 
@@ -2452,7 +2478,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
                  tem = expand_shift (LSHIFT_EXPR, mode, accum,
                                      build_int_2 (log, 0), NULL_RTX, 0);
                  accum = force_operand (gen_rtx_PLUS (mode, accum, tem),
-                                        add_target ? add_target : accum_target);
+                                        add_target
+                                        ? add_target : accum_target);
                  val_so_far += val_so_far << log;
                  break;
 
@@ -2466,17 +2493,17 @@ expand_mult (mode, op0, op1, target, unsignedp)
                  break;
 
                default:
-                 abort ();;
+                 abort ();
                }
 
              /* Write a REG_EQUAL note on the last insn so that we can cse
                 multiplication sequences.  */
 
              insn = get_last_insn ();
-             REG_NOTES (insn)
-               = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                    gen_rtx_MULT (mode, op0, GEN_INT (val_so_far)),
-                                    REG_NOTES (insn));
+             set_unique_reg_note (insn, 
+                                  REG_EQUAL,
+                                  gen_rtx_MULT (mode, op0, 
+                                                GEN_INT (val_so_far)));
            }
 
          if (variant == negate_variant)
@@ -2541,11 +2568,12 @@ choose_multiplier (d, n, precision, multiplier_ptr, post_shift_ptr, lgup_ptr)
      int *post_shift_ptr;
      int *lgup_ptr;
 {
-  unsigned HOST_WIDE_INT mhigh_hi, mhigh_lo;
-  unsigned HOST_WIDE_INT mlow_hi, mlow_lo;
+  HOST_WIDE_INT mhigh_hi, mlow_hi;
+  unsigned HOST_WIDE_INT mhigh_lo, mlow_lo;
   int lgup, post_shift;
   int pow, pow2;
-  unsigned HOST_WIDE_INT nh, nl, dummy1, dummy2;
+  unsigned HOST_WIDE_INT nl, dummy1;
+  HOST_WIDE_INT nh, dummy2;
 
   /* lgup = ceil(log2(divisor)); */
   lgup = ceil_log2 (d);
@@ -2566,7 +2594,7 @@ choose_multiplier (d, n, precision, multiplier_ptr, post_shift_ptr, lgup_ptr)
   /* mlow = 2^(N + lgup)/d */
  if (pow >= HOST_BITS_PER_WIDE_INT)
     {
-      nh = (unsigned HOST_WIDE_INT) 1 << (pow - HOST_BITS_PER_WIDE_INT);
+      nh = (HOST_WIDE_INT) 1 << (pow - HOST_BITS_PER_WIDE_INT);
       nl = 0;
     }
   else
@@ -2579,7 +2607,7 @@ choose_multiplier (d, n, precision, multiplier_ptr, post_shift_ptr, lgup_ptr)
 
   /* mhigh = (2^(N + lgup) + 2^N + lgup - precision)/d */
   if (pow2 >= HOST_BITS_PER_WIDE_INT)
-    nh |= (unsigned HOST_WIDE_INT) 1 << (pow2 - HOST_BITS_PER_WIDE_INT);
+    nh |= (HOST_WIDE_INT) 1 << (pow2 - HOST_BITS_PER_WIDE_INT);
   else
     nl |= (unsigned HOST_WIDE_INT) 1 << pow2;
   div_and_round_double (TRUNC_DIV_EXPR, 1, nl, nh, d, (HOST_WIDE_INT) 0,
@@ -2757,7 +2785,7 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
     {
       mul_highpart_optab = unsignedp ? umul_highpart_optab : smul_highpart_optab;
       target = expand_binop (mode, mul_highpart_optab,
-                            op0, wide_op1, target, unsignedp, OPTAB_DIRECT);
+                            op0, op1, target, unsignedp, OPTAB_DIRECT);
       if (target)
        return target;
     }
@@ -2768,7 +2796,7 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
     {
       mul_highpart_optab = unsignedp ? smul_highpart_optab : umul_highpart_optab;
       target = expand_binop (mode, mul_highpart_optab,
-                            op0, wide_op1, target, unsignedp, OPTAB_DIRECT);
+                            op0, op1, target, unsignedp, OPTAB_DIRECT);
       if (target)
        /* We used the wrong signedness.  Adjust the result.  */
        return expand_mult_highpart_adjust (mode, target, op0,
@@ -3170,10 +3198,9 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                if (insn != last
                    && (set = single_set (insn)) != 0
                    && SET_DEST (set) == quotient)
-                 REG_NOTES (insn)
-                   = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                        gen_rtx_UDIV (compute_mode, op0, op1),
-                                        REG_NOTES (insn));
+                 set_unique_reg_note (insn, 
+                                      REG_EQUAL,
+                                      gen_rtx_UDIV (compute_mode, op0, op1));
              }
            else                /* TRUNC_DIV, signed */
              {
@@ -3246,13 +3273,14 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                        insn = get_last_insn ();
                        if (insn != last
                            && (set = single_set (insn)) != 0
-                           && SET_DEST (set) == quotient)
-                         REG_NOTES (insn)
-                           = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                                gen_rtx_DIV (compute_mode,
-                                                             op0,
-                                                             GEN_INT (abs_d)),
-                                      REG_NOTES (insn));
+                           && SET_DEST (set) == quotient
+                           && abs_d < ((unsigned HOST_WIDE_INT) 1
+                                       << (HOST_BITS_PER_WIDE_INT - 1)))
+                         set_unique_reg_note (insn, 
+                                              REG_EQUAL,
+                                              gen_rtx_DIV (compute_mode,
+                                                           op0,
+                                                           GEN_INT (abs_d)));
 
                        quotient = expand_unop (compute_mode, neg_optab,
                                                quotient, quotient, 0);
@@ -3278,11 +3306,15 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                        t3 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
                                           build_int_2 (size - 1, 0), NULL_RTX, 0);
                        if (d < 0)
-                         quotient = force_operand (gen_rtx_MINUS (compute_mode, t3, t2),
-                                                   tquotient);
+                         quotient
+                           = force_operand (gen_rtx_MINUS (compute_mode,
+                                                           t3, t2),
+                                            tquotient);
                        else
-                         quotient = force_operand (gen_rtx_MINUS (compute_mode, t2, t3),
-                                                   tquotient);
+                         quotient
+                           = force_operand (gen_rtx_MINUS (compute_mode,
+                                                           t2, t3),
+                                            tquotient);
                      }
                    else
                      {
@@ -3296,18 +3328,25 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                                                   max_cost - extra_cost);
                        if (t1 == 0)
                          goto fail1;
-                       t2 = force_operand (gen_rtx_PLUS (compute_mode, t1, op0),
+                       t2 = force_operand (gen_rtx_PLUS (compute_mode,
+                                                         t1, op0),
                                            NULL_RTX);
                        t3 = expand_shift (RSHIFT_EXPR, compute_mode, t2,
-                                          build_int_2 (post_shift, 0), NULL_RTX, 0);
+                                          build_int_2 (post_shift, 0),
+                                          NULL_RTX, 0);
                        t4 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
-                                          build_int_2 (size - 1, 0), NULL_RTX, 0);
+                                          build_int_2 (size - 1, 0),
+                                          NULL_RTX, 0);
                        if (d < 0)
-                         quotient = force_operand (gen_rtx_MINUS (compute_mode, t4, t3),
-                                                   tquotient);
+                         quotient
+                           = force_operand (gen_rtx_MINUS (compute_mode,
+                                                           t4, t3),
+                                            tquotient);
                        else
-                         quotient = force_operand (gen_rtx_MINUS (compute_mode, t3, t4),
-                                                   tquotient);
+                         quotient
+                           = force_operand (gen_rtx_MINUS (compute_mode,
+                                                           t3, t4),
+                                            tquotient);
                      }
                  }
                else            /* Too wide mode to use tricky code */
@@ -3317,10 +3356,9 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                if (insn != last
                    && (set = single_set (insn)) != 0
                    && SET_DEST (set) == quotient)
-                 REG_NOTES (insn)
-                   = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                        gen_rtx_DIV (compute_mode, op0, op1),
-                                        REG_NOTES (insn));
+                 set_unique_reg_note (insn, 
+                                      REG_EQUAL,
+                                      gen_rtx_DIV (compute_mode, op0, op1));
              }
            break;
          }
@@ -3733,12 +3771,11 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                                     NULL_RTX, unsignedp);
 
            insn = get_last_insn ();
-           REG_NOTES (insn)
-             = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                  gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
-                                                  compute_mode,
-                                                  op0, op1),
-                                  REG_NOTES (insn));
+           set_unique_reg_note (insn,
+                                REG_EQUAL,
+                                gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
+                                                compute_mode,
+                                                op0, op1));
          }
        break;
 
@@ -3784,8 +3821,8 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
                remainder = expand_binop (compute_mode, sub_optab, op0, tem,
                                          remainder, 0, OPTAB_LIB_WIDEN);
              }
-           abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 0, 0);
-           abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 0, 0);
+           abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 0);
+           abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 0);
            tem = expand_shift (LSHIFT_EXPR, compute_mode, abs_rem,
                                build_int_2 (1, 0), NULL_RTX, 1);
            do_cmp_and_jump (tem, abs_op1, LTU, compute_mode, label);
@@ -4094,6 +4131,9 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
   rtx last = get_last_insn ();
   rtx pattern, comparison;
 
+  if (unsignedp)
+    code = unsigned_condition (code);
+
   /* If one operand is constant, make it the second one.  Only do this
      if the other operand is not constant as well.  */
 
@@ -4143,6 +4183,29 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
       break;
     }
 
+  /* If we are comparing a double-word integer with zero, we can convert
+     the comparison into one involving a single word.  */
+  if (GET_MODE_BITSIZE (mode) == BITS_PER_WORD * 2
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && op1 == const0_rtx)
+    {
+      if (code == EQ || code == NE)
+       {
+         /* Do a logical OR of the two words and compare the result.  */
+         rtx op0h = gen_highpart (word_mode, op0);
+         rtx op0l = gen_lowpart (word_mode, op0);
+         rtx op0both = expand_binop (word_mode, ior_optab, op0h, op0l,
+                                     NULL_RTX, unsignedp, OPTAB_DIRECT);
+         if (op0both != 0)
+           return emit_store_flag (target, code, op0both, op1, word_mode,
+                                   unsignedp, normalizep);
+       }
+      else if (code == LT || code == GE)
+       /* If testing the sign bit, can just test on high word.  */
+       return emit_store_flag (target, code, gen_highpart (word_mode, op0),
+                               op1, word_mode, unsignedp, normalizep);
+    }
+
   /* From now on, we won't change CODE, so set ICODE now.  */
   icode = setcc_gen_code[(int) code];
 
@@ -4191,13 +4254,17 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
 
   if (icode != CODE_FOR_nothing)
     {
+      insn_operand_predicate_fn pred;
+
       /* We think we may be able to do this with a scc insn.  Emit the
         comparison and then the scc insn.
 
         compare_from_rtx may call emit_queue, which would be deleted below
-        if the scc insn fails.  So call it ourselves before setting LAST.  */
+        if the scc insn fails.  So call it ourselves before setting LAST.
+        Likewise for do_pending_stack_adjust.  */
 
       emit_queue ();
+      do_pending_stack_adjust ();
       last = get_last_insn ();
 
       comparison
@@ -4216,10 +4283,11 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
        abort ();
 
       /* Get a reference to the target in the proper mode for this insn.  */
-      compare_mode = insn_operand_mode[(int) icode][0];
+      compare_mode = insn_data[(int) icode].operand[0].mode;
       subtarget = target;
+      pred = insn_data[(int) icode].operand[0].predicate;
       if (preserve_subexpressions_p ()
-         || ! (*insn_operand_predicate[(int) icode][0]) (subtarget, compare_mode))
+         || ! (*pred) (subtarget, compare_mode))
        subtarget = gen_reg_rtx (compare_mode);
 
       pattern = GEN_FCN (icode) (subtarget);
@@ -4259,7 +4327,9 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
             we don't have to do anything.  */
          if (normalizep == 0 || normalizep == STORE_FLAG_VALUE)
            ;
-         else if (normalizep == - STORE_FLAG_VALUE)
+         /* STORE_FLAG_VALUE might be the most negative number, so write
+            the comparison this way to avoid a compiler-time warning.  */
+         else if (- normalizep == STORE_FLAG_VALUE)
            op0 = expand_unop (compare_mode, neg_optab, op0, subtarget, 0);
 
          /* We don't want to use STORE_FLAG_VALUE < 0 below since this
@@ -4493,15 +4563,10 @@ emit_store_flag_force (target, code, op0, op1, mode, unsignedp, normalizep)
     target = gen_reg_rtx (GET_MODE (target));
 
   emit_move_insn (target, const1_rtx);
-  tem = compare_from_rtx (op0, op1, code, unsignedp, mode, NULL_RTX, 0);
-  if (GET_CODE (tem) == CONST_INT)
-    return tem;
-
   label = gen_label_rtx ();
-  if (bcc_gen_fctn[(int) code] == 0)
-    abort ();
+  do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX, 0,
+                          NULL_RTX, label);
 
-  emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label));
   emit_move_insn (target, const0_rtx);
   emit_label (label);
 
@@ -4520,13 +4585,14 @@ emit_store_flag_force (target, code, op0, op1, mode, unsignedp, normalizep)
 static void
 do_cmp_and_jump (arg1, arg2, op, mode, label)
      rtx arg1, arg2, label;
-    enum rtx_code op;
-    enum machine_mode mode;
+     enum rtx_code op;
+     enum machine_mode mode;
 {
   /* If this mode is an integer too wide to compare properly,
      compare word by word.  Rely on cse to optimize constant cases.  */
 
-  if (GET_MODE_CLASS (mode) == MODE_INT && !can_compare_p (mode))
+  if (GET_MODE_CLASS (mode) == MODE_INT
+      && ! can_compare_p (op, mode, ccp_jump))
     {
       rtx label2 = gen_label_rtx ();
 
@@ -4574,9 +4640,6 @@ do_cmp_and_jump (arg1, arg2, op, mode, label)
     }
   else
     {
-      emit_cmp_insn(arg1, arg2, op, NULL_RTX, mode, 0, 0);
-      if (bcc_gen_fctn[(int) op] == 0)
-       abort ();
-      emit_jump_insn ((*bcc_gen_fctn[(int) op]) (label));
+      emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, 0, label);
     }
 }