OSDN Git Service

2010-02-20 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / genmodes.c
index 6d32d70..2aa559f 100644 (file)
@@ -1,12 +1,12 @@
 /* Generate the machine mode enumeration and associated tables.
 /* Generate the machine mode enumeration and associated tables.
-   Copyright (C) 2003
+   Copyright (C) 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 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
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 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
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +15,8 @@ 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
 for more details.
 
 You should have received a copy of the GNU General Public License
-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.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "bconfig.h"
 #include "system.h"
 
 #include "bconfig.h"
 #include "system.h"
@@ -55,18 +54,26 @@ struct mode_data
   struct mode_data *next;      /* next this class - arbitrary order */
 
   const char *name;            /* printable mode name -- SI, not SImode */
   struct mode_data *next;      /* next this class - arbitrary order */
 
   const char *name;            /* printable mode name -- SI, not SImode */
-  enum mode_class class;       /* this mode class */
-  unsigned int bitsize;                /* size in bits, equiv to TYPE_PRECISION */
+  enum mode_class cl;          /* this mode class */
+  unsigned int precision;      /* size in bits, equiv to TYPE_PRECISION */
   unsigned int bytesize;       /* storage size in addressable units */
   unsigned int ncomponents;    /* number of subunits */
   unsigned int alignment;      /* mode alignment */
   unsigned int bytesize;       /* storage size in addressable units */
   unsigned int ncomponents;    /* number of subunits */
   unsigned int alignment;      /* mode alignment */
-  const char *format;          /* floating point format - MODE_FLOAT only */
+  const char *format;          /* floating point format - float modes only */
 
   struct mode_data *component; /* mode of components */
   struct mode_data *wider;     /* next wider mode */
 
   struct mode_data *component; /* mode of components */
   struct mode_data *wider;     /* next wider mode */
+  struct mode_data *wider_2x;  /* 2x wider mode */
+
+  struct mode_data *contained;  /* Pointer to list of modes that have
+                                  this mode as a component.  */
+  struct mode_data *next_cont;  /* Next mode in that list.  */
 
   const char *file;            /* file and line of definition, */
   unsigned int line;           /* for error reporting */
 
   const char *file;            /* file and line of definition, */
   unsigned int line;           /* for error reporting */
+  unsigned int counter;                /* Rank ordering of modes */
+  unsigned int ibit;           /* the number of integral bits */
+  unsigned int fbit;           /* the number of fractional bits */
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
@@ -75,9 +82,9 @@ static struct mode_data *void_mode;
 
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
 
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
-  -1, -1, -1, -1,
-  0, 0, 0,
-  "<unknown>", 0
+  -1U, -1U, -1U, -1U,
+  0, 0, 0, 0, 0, 0,
+  "<unknown>", 0, 0, 0, 0
 };
 
 static htab_t modes_by_name;
 };
 
 static htab_t modes_by_name;
@@ -98,30 +105,36 @@ struct mode_adjust
 static struct mode_adjust *adj_bytesize;
 static struct mode_adjust *adj_alignment;
 static struct mode_adjust *adj_format;
 static struct mode_adjust *adj_bytesize;
 static struct mode_adjust *adj_alignment;
 static struct mode_adjust *adj_format;
+static struct mode_adjust *adj_ibit;
+static struct mode_adjust *adj_fbit;
 
 /* Mode class operations.  */
 static enum mode_class
 
 /* Mode class operations.  */
 static enum mode_class
-complex_class (enum mode_class class)
+complex_class (enum mode_class c)
 {
 {
-  switch (class)
+  switch (c)
     {
     case MODE_INT: return MODE_COMPLEX_INT;
     case MODE_FLOAT: return MODE_COMPLEX_FLOAT;
     default:
     {
     case MODE_INT: return MODE_COMPLEX_INT;
     case MODE_FLOAT: return MODE_COMPLEX_FLOAT;
     default:
-      error ("no complex class for class %s", mode_class_names[class]);
+      error ("no complex class for class %s", mode_class_names[c]);
       return MODE_RANDOM;
     }
 }
 
 static enum mode_class
       return MODE_RANDOM;
     }
 }
 
 static enum mode_class
-vector_class (enum mode_class class)
+vector_class (enum mode_class cl)
 {
 {
-  switch (class)
+  switch (cl)
     {
     case MODE_INT: return MODE_VECTOR_INT;
     case MODE_FLOAT: return MODE_VECTOR_FLOAT;
     {
     case MODE_INT: return MODE_VECTOR_INT;
     case MODE_FLOAT: return MODE_VECTOR_FLOAT;
+    case MODE_FRACT: return MODE_VECTOR_FRACT;
+    case MODE_UFRACT: return MODE_VECTOR_UFRACT;
+    case MODE_ACCUM: return MODE_VECTOR_ACCUM;
+    case MODE_UACCUM: return MODE_VECTOR_UACCUM;
     default:
     default:
-      error ("no vector class for class %s", mode_class_names[class]);
+      error ("no vector class for class %s", mode_class_names[cl]);
       return MODE_RANDOM;
     }
 }
       return MODE_RANDOM;
     }
 }
@@ -133,14 +146,15 @@ find_mode (const char *name)
   struct mode_data key;
 
   key.name = name;
   struct mode_data key;
 
   key.name = name;
-  return htab_find (modes_by_name, &key);
+  return (struct mode_data *) htab_find (modes_by_name, &key);
 }
 
 static struct mode_data *
 }
 
 static struct mode_data *
-new_mode (enum mode_class class, const char *name,
+new_mode (enum mode_class cl, const char *name,
          const char *file, unsigned int line)
 {
   struct mode_data *m;
          const char *file, unsigned int line)
 {
   struct mode_data *m;
+  static unsigned int count = 0;
 
   m = find_mode (name);
   if (m)
 
   m = find_mode (name);
   if (m)
@@ -151,20 +165,21 @@ new_mode (enum mode_class class, const char *name,
       return m;
     }
 
       return m;
     }
 
-  m = xmalloc (sizeof (struct mode_data));
+  m = XNEW (struct mode_data);
   memcpy (m, &blank_mode, sizeof (struct mode_data));
   memcpy (m, &blank_mode, sizeof (struct mode_data));
-  m->class = class;
+  m->cl = cl;
   m->name = name;
   if (file)
     m->file = trim_filename (file);
   m->line = line;
   m->name = name;
   if (file)
     m->file = trim_filename (file);
   m->line = line;
+  m->counter = count++;
 
 
-  m->next = modes[class];
-  modes[class] = m;
-  n_modes[class]++;
+  m->next = modes[cl];
+  modes[cl] = m;
+  n_modes[cl]++;
 
   *htab_find_slot (modes_by_name, m, INSERT) = m;
 
   *htab_find_slot (modes_by_name, m, INSERT) = m;
-  
+
   return m;
 }
 
   return m;
 }
 
@@ -192,7 +207,8 @@ static void ATTRIBUTE_UNUSED
 new_adjust (const char *name,
            struct mode_adjust **category, const char *catname,
            const char *adjustment,
 new_adjust (const char *name,
            struct mode_adjust **category, const char *catname,
            const char *adjustment,
-           enum mode_class required_class,
+           enum mode_class required_class_from,
+           enum mode_class required_class_to,
            const char *file, unsigned int line)
 {
   struct mode_data *mode = find_mode (name);
            const char *file, unsigned int line)
 {
   struct mode_data *mode = find_mode (name);
@@ -206,13 +222,14 @@ new_adjust (const char *name,
       return;
     }
 
       return;
     }
 
-  if (required_class != MODE_RANDOM && mode->class != required_class)
+  if (required_class_from != MODE_RANDOM
+      && (mode->cl < required_class_from || mode->cl > required_class_to))
     {
     {
-      error ("%s:%d: mode \"%s\" is not class %s",
-            file, line, name, mode_class_names[required_class] + 5);
+      error ("%s:%d: mode \"%s\" is not among class {%s, %s}",
+            file, line, name, mode_class_names[required_class_from] + 5,
+            mode_class_names[required_class_to] + 5);
       return;
     }
       return;
     }
-  
 
   for (a = *category; a; a = a->next)
     if (a->mode == mode)
 
   for (a = *category; a; a = a->next)
     if (a->mode == mode)
@@ -223,7 +240,7 @@ new_adjust (const char *name,
        return;
       }
 
        return;
       }
 
-  a = xmalloc (sizeof (struct mode_adjust));
+  a = XNEW (struct mode_adjust);
   a->mode = mode;
   a->adjustment = adjustment;
   a->file = file;
   a->mode = mode;
   a->adjustment = adjustment;
   a->file = file;
@@ -259,13 +276,13 @@ enum requirement { SET, UNSET, OPTIONAL };
 
 static void
 validate_mode (struct mode_data *m,
 
 static void
 validate_mode (struct mode_data *m,
-              enum requirement r_bitsize,
+              enum requirement r_precision,
               enum requirement r_bytesize,
               enum requirement r_component,
               enum requirement r_ncomponents,
               enum requirement r_format)
 {
               enum requirement r_bytesize,
               enum requirement r_component,
               enum requirement r_ncomponents,
               enum requirement r_format)
 {
-  validate_field (m, bitsize);
+  validate_field (m, precision);
   validate_field (m, bytesize);
   validate_field (m, component);
   validate_field (m, ncomponents);
   validate_field (m, bytesize);
   validate_field (m, component);
   validate_field (m, ncomponents);
@@ -286,13 +303,13 @@ complete_mode (struct mode_data *m)
       error ("%s:%d: mode with no name", m->file, m->line);
       return;
     }
       error ("%s:%d: mode with no name", m->file, m->line);
       return;
     }
-  if (m->class == MAX_MODE_CLASS)
+  if (m->cl == MAX_MODE_CLASS)
     {
       error ("%s:%d: %smode has no mode class", m->file, m->line, m->name);
       return;
     }
 
     {
       error ("%s:%d: %smode has no mode class", m->file, m->line, m->name);
       return;
     }
 
-  switch (m->class)
+  switch (m->cl)
     {
     case MODE_RANDOM:
       /* Nothing more need be said.  */
     {
     case MODE_RANDOM:
       /* Nothing more need be said.  */
@@ -301,7 +318,7 @@ complete_mode (struct mode_data *m)
 
       validate_mode (m, UNSET, UNSET, UNSET, UNSET, UNSET);
 
 
       validate_mode (m, UNSET, UNSET, UNSET, UNSET, UNSET);
 
-      m->bitsize = 0;
+      m->precision = 0;
       m->bytesize = 0;
       m->ncomponents = 0;
       m->component = 0;
       m->bytesize = 0;
       m->ncomponents = 0;
       m->component = 0;
@@ -313,19 +330,25 @@ complete_mode (struct mode_data *m)
       validate_mode (m, UNSET, UNSET, UNSET, UNSET, UNSET);
 
       m->bytesize = 4;
       validate_mode (m, UNSET, UNSET, UNSET, UNSET, UNSET);
 
       m->bytesize = 4;
-      m->ncomponents = 0;
+      m->ncomponents = 1;
       m->component = 0;
       break;
 
     case MODE_INT:
     case MODE_FLOAT:
       m->component = 0;
       break;
 
     case MODE_INT:
     case MODE_FLOAT:
+    case MODE_DECIMAL_FLOAT:
+    case MODE_FRACT:
+    case MODE_UFRACT:
+    case MODE_ACCUM:
+    case MODE_UACCUM:
       /* A scalar mode must have a byte size, may have a bit size,
         and must not have components.   A float mode must have a
          format.  */
       validate_mode (m, OPTIONAL, SET, UNSET, UNSET,
       /* A scalar mode must have a byte size, may have a bit size,
         and must not have components.   A float mode must have a
          format.  */
       validate_mode (m, OPTIONAL, SET, UNSET, UNSET,
-                    m->class == MODE_FLOAT ? SET : UNSET);
+                    (m->cl == MODE_FLOAT || m->cl == MODE_DECIMAL_FLOAT)
+                    ? SET : UNSET);
 
 
-      m->ncomponents = 0;
+      m->ncomponents = 1;
       m->component = 0;
       break;
 
       m->component = 0;
       break;
 
@@ -337,7 +360,7 @@ complete_mode (struct mode_data *m)
 
       m->bytesize = m->component->bytesize;
 
 
       m->bytesize = m->component->bytesize;
 
-      m->ncomponents = 0;
+      m->ncomponents = 1;
       m->component = 0;  /* ??? preserve this */
       break;
 
       m->component = 0;  /* ??? preserve this */
       break;
 
@@ -346,63 +369,75 @@ complete_mode (struct mode_data *m)
       /* Complex modes should have a component indicated, but no more.  */
       validate_mode (m, UNSET, UNSET, SET, UNSET, UNSET);
       m->ncomponents = 2;
       /* Complex modes should have a component indicated, but no more.  */
       validate_mode (m, UNSET, UNSET, SET, UNSET, UNSET);
       m->ncomponents = 2;
-      if (m->component->bitsize != (unsigned int)-1)
-       m->bitsize = 2 * m->component->bitsize;
+      if (m->component->precision != (unsigned int)-1)
+       m->precision = 2 * m->component->precision;
       m->bytesize = 2 * m->component->bytesize;
       break;
 
     case MODE_VECTOR_INT:
     case MODE_VECTOR_FLOAT:
       m->bytesize = 2 * m->component->bytesize;
       break;
 
     case MODE_VECTOR_INT:
     case MODE_VECTOR_FLOAT:
+    case MODE_VECTOR_FRACT:
+    case MODE_VECTOR_UFRACT:
+    case MODE_VECTOR_ACCUM:
+    case MODE_VECTOR_UACCUM:
       /* Vector modes should have a component and a number of components.  */
       validate_mode (m, UNSET, UNSET, SET, SET, UNSET);
       /* Vector modes should have a component and a number of components.  */
       validate_mode (m, UNSET, UNSET, SET, SET, UNSET);
-      if (m->component->bitsize != (unsigned int)-1)
-       m->bitsize = m->ncomponents * m->component->bitsize;
+      if (m->component->precision != (unsigned int)-1)
+       m->precision = m->ncomponents * m->component->precision;
       m->bytesize = m->ncomponents * m->component->bytesize;
       break;
 
     default:
       m->bytesize = m->ncomponents * m->component->bytesize;
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* If not already specified, the mode alignment defaults to the largest
      power of two that divides the size of the object.  Complex types are
      not more aligned than their contents.  */
     }
 
   /* If not already specified, the mode alignment defaults to the largest
      power of two that divides the size of the object.  Complex types are
      not more aligned than their contents.  */
-  if (m->class == MODE_COMPLEX_INT || m->class == MODE_COMPLEX_FLOAT)
+  if (m->cl == MODE_COMPLEX_INT || m->cl == MODE_COMPLEX_FLOAT)
     alignment = m->component->bytesize;
   else
     alignment = m->bytesize;
 
   m->alignment = alignment & (~alignment + 1);
     alignment = m->component->bytesize;
   else
     alignment = m->bytesize;
 
   m->alignment = alignment & (~alignment + 1);
+
+  /* If this mode has components, make the component mode point back
+     to this mode, for the sake of adjustments.  */
+  if (m->component)
+    {
+      m->next_cont = m->component->contained;
+      m->component->contained = m;
+    }
 }
 
 static void
 complete_all_modes (void)
 {
   struct mode_data *m;
 }
 
 static void
 complete_all_modes (void)
 {
   struct mode_data *m;
-  enum mode_class c;
-  
-  for_all_modes (c, m)
+  int cl;
+
+  for_all_modes (cl, m)
     complete_mode (m);
 }
 
 /* For each mode in class CLASS, construct a corresponding complex mode.  */
 #define COMPLEX_MODES(C) make_complex_modes(MODE_##C, __FILE__, __LINE__)
 static void
     complete_mode (m);
 }
 
 /* For each mode in class CLASS, construct a corresponding complex mode.  */
 #define COMPLEX_MODES(C) make_complex_modes(MODE_##C, __FILE__, __LINE__)
 static void
-make_complex_modes (enum mode_class class,
+make_complex_modes (enum mode_class cl,
                    const char *file, unsigned int line)
 {
   struct mode_data *m;
   struct mode_data *c;
   char buf[8];
                    const char *file, unsigned int line)
 {
   struct mode_data *m;
   struct mode_data *c;
   char buf[8];
-  enum mode_class cclass = complex_class (class);
+  enum mode_class cclass = complex_class (cl);
 
   if (cclass == MODE_RANDOM)
     return;
 
   if (cclass == MODE_RANDOM)
     return;
-    
-  for (m = modes[class]; m; m = m->next)
+
+  for (m = modes[cl]; m; m = m->next)
     {
       /* Skip BImode.  FIXME: BImode probably shouldn't be MODE_INT.  */
     {
       /* Skip BImode.  FIXME: BImode probably shouldn't be MODE_INT.  */
-      if (m->bitsize == 1)
+      if (m->precision == 1)
        continue;
 
       if (strlen (m->name) >= sizeof buf)
        continue;
 
       if (strlen (m->name) >= sizeof buf)
@@ -415,19 +450,24 @@ make_complex_modes (enum mode_class class,
       /* Float complex modes are named SCmode, etc.
         Int complex modes are named CSImode, etc.
          This inconsistency should be eliminated.  */
       /* Float complex modes are named SCmode, etc.
         Int complex modes are named CSImode, etc.
          This inconsistency should be eliminated.  */
-      if (class == MODE_FLOAT)
+      if (cl == MODE_FLOAT)
        {
        {
-         char *p;
+         char *p, *q = 0;
          strncpy (buf, m->name, sizeof buf);
          p = strchr (buf, 'F');
          if (p == 0)
          strncpy (buf, m->name, sizeof buf);
          p = strchr (buf, 'F');
          if (p == 0)
+           q = strchr (buf, 'D');
+         if (p == 0 && q == 0)
            {
            {
-             error ("%s:%d: float mode \"%s\" has no 'F'",
+             error ("%s:%d: float mode \"%s\" has no 'F' or 'D'",
                     m->file, m->line, m->name);
              continue;
            }
 
                     m->file, m->line, m->name);
              continue;
            }
 
-         *p = 'C';
+         if (p != 0)
+           *p = 'C';
+         else
+           snprintf (buf, sizeof buf, "C%s", m->name);
        }
       else
        snprintf (buf, sizeof buf, "C%s", m->name);
        }
       else
        snprintf (buf, sizeof buf, "C%s", m->name);
@@ -437,23 +477,23 @@ make_complex_modes (enum mode_class class,
     }
 }
 
     }
 }
 
-/* For all modes in class CLASS, construct vector modes of width
+/* For all modes in class CL, construct vector modes of width
    WIDTH, having as many components as necessary.  */
 #define VECTOR_MODES(C, W) make_vector_modes(MODE_##C, W, __FILE__, __LINE__)
    WIDTH, having as many components as necessary.  */
 #define VECTOR_MODES(C, W) make_vector_modes(MODE_##C, W, __FILE__, __LINE__)
-static void
-make_vector_modes (enum mode_class class, unsigned int width,
+static void ATTRIBUTE_UNUSED
+make_vector_modes (enum mode_class cl, unsigned int width,
                   const char *file, unsigned int line)
 {
   struct mode_data *m;
   struct mode_data *v;
   char buf[8];
   unsigned int ncomponents;
                   const char *file, unsigned int line)
 {
   struct mode_data *m;
   struct mode_data *v;
   char buf[8];
   unsigned int ncomponents;
-  enum mode_class vclass = vector_class (class);
+  enum mode_class vclass = vector_class (cl);
 
   if (vclass == MODE_RANDOM)
     return;
 
 
   if (vclass == MODE_RANDOM)
     return;
 
-  for (m = modes[class]; m; m = m->next)
+  for (m = modes[cl]; m; m = m->next)
     {
       /* Do not construct vector modes with only one element, or
         vector modes where the element size doesn't divide the full
     {
       /* Do not construct vector modes with only one element, or
         vector modes where the element size doesn't divide the full
@@ -466,9 +506,9 @@ make_vector_modes (enum mode_class class, unsigned int width,
 
       /* Skip QFmode and BImode.  FIXME: this special case should
         not be necessary.  */
 
       /* Skip QFmode and BImode.  FIXME: this special case should
         not be necessary.  */
-      if (class == MODE_FLOAT && m->bytesize == 1)
+      if (cl == MODE_FLOAT && m->bytesize == 1)
        continue;
        continue;
-      if (class == MODE_INT && m->bitsize == 1)
+      if (cl == MODE_INT && m->precision == 1)
        continue;
 
       if ((size_t)snprintf (buf, sizeof buf, "V%u%s", ncomponents, m->name)
        continue;
 
       if ((size_t)snprintf (buf, sizeof buf, "V%u%s", ncomponents, m->name)
@@ -492,39 +532,85 @@ make_vector_modes (enum mode_class class, unsigned int width,
 #define CC_MODE(N) _SPECIAL_MODE (CC, N)
 
 static void
 #define CC_MODE(N) _SPECIAL_MODE (CC, N)
 
 static void
-make_special_mode (enum mode_class class, const char *name,
+make_special_mode (enum mode_class cl, const char *name,
                   const char *file, unsigned int line)
 {
                   const char *file, unsigned int line)
 {
-  new_mode (class, name, file, line);
+  new_mode (cl, name, file, line);
 }
 
 }
 
-#define INT_MODE(N, Y) FRACTIONAL_INT_MODE (N, -1, Y)
+#define INT_MODE(N, Y) FRACTIONAL_INT_MODE (N, -1U, Y)
 #define FRACTIONAL_INT_MODE(N, B, Y) \
   make_int_mode (#N, B, Y, __FILE__, __LINE__)
 
 static void
 make_int_mode (const char *name,
 #define FRACTIONAL_INT_MODE(N, B, Y) \
   make_int_mode (#N, B, Y, __FILE__, __LINE__)
 
 static void
 make_int_mode (const char *name,
-              unsigned int bitsize, unsigned int bytesize,
+              unsigned int precision, unsigned int bytesize,
               const char *file, unsigned int line)
 {
   struct mode_data *m = new_mode (MODE_INT, name, file, line);
   m->bytesize = bytesize;
               const char *file, unsigned int line)
 {
   struct mode_data *m = new_mode (MODE_INT, name, file, line);
   m->bytesize = bytesize;
-  m->bitsize = bitsize;
+  m->precision = precision;
 }
 
 }
 
-#define FLOAT_MODE(N, Y, F)             FRACTIONAL_FLOAT_MODE (N, -1, Y, F)
+#define FRACT_MODE(N, Y, F) \
+       make_fixed_point_mode (MODE_FRACT, #N, Y, 0, F, __FILE__, __LINE__)
+
+#define UFRACT_MODE(N, Y, F) \
+       make_fixed_point_mode (MODE_UFRACT, #N, Y, 0, F, __FILE__, __LINE__)
+
+#define ACCUM_MODE(N, Y, I, F) \
+       make_fixed_point_mode (MODE_ACCUM, #N, Y, I, F, __FILE__, __LINE__)
+
+#define UACCUM_MODE(N, Y, I, F) \
+       make_fixed_point_mode (MODE_UACCUM, #N, Y, I, F, __FILE__, __LINE__)
+
+/* Create a fixed-point mode by setting CL, NAME, BYTESIZE, IBIT, FBIT,
+   FILE, and LINE.  */
+
+static void
+make_fixed_point_mode (enum mode_class cl,
+                      const char *name,
+                      unsigned int bytesize,
+                      unsigned int ibit,
+                      unsigned int fbit,
+                      const char *file, unsigned int line)
+{
+  struct mode_data *m = new_mode (cl, name, file, line);
+  m->bytesize = bytesize;
+  m->ibit = ibit;
+  m->fbit = fbit;
+}
+
+#define FLOAT_MODE(N, Y, F)             FRACTIONAL_FLOAT_MODE (N, -1U, Y, F)
 #define FRACTIONAL_FLOAT_MODE(N, B, Y, F) \
   make_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
 
 static void
 make_float_mode (const char *name,
 #define FRACTIONAL_FLOAT_MODE(N, B, Y, F) \
   make_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
 
 static void
 make_float_mode (const char *name,
-                unsigned int bitsize, unsigned int bytesize,
+                unsigned int precision, unsigned int bytesize,
                 const char *format,
                 const char *file, unsigned int line)
 {
   struct mode_data *m = new_mode (MODE_FLOAT, name, file, line);
   m->bytesize = bytesize;
                 const char *format,
                 const char *file, unsigned int line)
 {
   struct mode_data *m = new_mode (MODE_FLOAT, name, file, line);
   m->bytesize = bytesize;
-  m->bitsize = bitsize;
+  m->precision = precision;
+  m->format = format;
+}
+
+#define DECIMAL_FLOAT_MODE(N, Y, F)    \
+       FRACTIONAL_DECIMAL_FLOAT_MODE (N, -1U, Y, F)
+#define FRACTIONAL_DECIMAL_FLOAT_MODE(N, B, Y, F)      \
+  make_decimal_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
+
+static void
+make_decimal_float_mode (const char *name,
+                        unsigned int precision, unsigned int bytesize,
+                        const char *format,
+                        const char *file, unsigned int line)
+{
+  struct mode_data *m = new_mode (MODE_DECIMAL_FLOAT, name, file, line);
+  m->bytesize = bytesize;
+  m->precision = precision;
   m->format = format;
 }
 
   m->format = format;
 }
 
@@ -540,9 +626,9 @@ reset_float_format (const char *name, const char *format,
       error ("%s:%d: no mode \"%s\"", file, line, name);
       return;
     }
       error ("%s:%d: no mode \"%s\"", file, line, name);
       return;
     }
-  if (m->class != MODE_FLOAT)
+  if (m->cl != MODE_FLOAT && m->cl != MODE_DECIMAL_FLOAT)
     {
     {
-      error ("%s:%d: mode \"%s\" is not class FLOAT", file, line, name);
+      error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
       return;
     }
   m->format = format;
       return;
     }
   m->format = format;
@@ -551,10 +637,10 @@ reset_float_format (const char *name, const char *format,
 /* Partial integer modes are specified by relation to a full integer mode.
    For now, we do not attempt to narrow down their bit sizes.  */
 #define PARTIAL_INT_MODE(M) \
 /* Partial integer modes are specified by relation to a full integer mode.
    For now, we do not attempt to narrow down their bit sizes.  */
 #define PARTIAL_INT_MODE(M) \
-  make_partial_integer_mode (#M, "P" #M, -1, __FILE__, __LINE__)
+  make_partial_integer_mode (#M, "P" #M, -1U, __FILE__, __LINE__)
 static void ATTRIBUTE_UNUSED
 make_partial_integer_mode (const char *base, const char *name,
 static void ATTRIBUTE_UNUSED
 make_partial_integer_mode (const char *base, const char *name,
-                          unsigned int bitsize,
+                          unsigned int precision,
                           const char *file, unsigned int line)
 {
   struct mode_data *m;
                           const char *file, unsigned int line)
 {
   struct mode_data *m;
@@ -564,14 +650,14 @@ make_partial_integer_mode (const char *base, const char *name,
       error ("%s:%d: no mode \"%s\"", file, line, name);
       return;
     }
       error ("%s:%d: no mode \"%s\"", file, line, name);
       return;
     }
-  if (component->class != MODE_INT)
+  if (component->cl != MODE_INT)
     {
       error ("%s:%d: mode \"%s\" is not class INT", file, line, name);
       return;
     }
     {
       error ("%s:%d: mode \"%s\" is not class INT", file, line, name);
       return;
     }
-  
+
   m = new_mode (MODE_PARTIAL_INT, name, file, line);
   m = new_mode (MODE_PARTIAL_INT, name, file, line);
-  m->bitsize = bitsize;
+  m->precision = precision;
   m->component = component;
 }
 
   m->component = component;
 }
 
@@ -597,7 +683,9 @@ make_vector_mode (enum mode_class bclass,
       error ("%s:%d: no mode \"%s\"", file, line, base);
       return;
     }
       error ("%s:%d: no mode \"%s\"", file, line, base);
       return;
     }
-  if (component->class != bclass)
+  if (component->cl != bclass
+      && (component->cl != MODE_PARTIAL_INT
+         || bclass != MODE_INT))
     {
       error ("%s:%d: mode \"%s\" is not class %s",
             file, line, base, mode_class_names[bclass] + 5);
     {
       error ("%s:%d: mode \"%s\" is not class %s",
             file, line, base, mode_class_names[bclass] + 5);
@@ -608,7 +696,7 @@ make_vector_mode (enum mode_class bclass,
                        ncomponents, base) >= sizeof namebuf)
     {
       error ("%s:%d: mode name \"%s\" is too long",
                        ncomponents, base) >= sizeof namebuf)
     {
       error ("%s:%d: mode name \"%s\" is too long",
-            base, file, line);
+            file, line, base);
       return;
     }
 
       return;
     }
 
@@ -618,12 +706,14 @@ make_vector_mode (enum mode_class bclass,
 }
 
 /* Adjustability.  */
 }
 
 /* Adjustability.  */
-#define _ADD_ADJUST(A, M, X, C) \
-  new_adjust (#M, &adj_##A, #A, #X, MODE_##C, __FILE__, __LINE__)
+#define _ADD_ADJUST(A, M, X, C1, C2) \
+  new_adjust (#M, &adj_##A, #A, #X, MODE_##C1, MODE_##C2, __FILE__, __LINE__)
 
 
-#define ADJUST_BYTESIZE(M, X)  _ADD_ADJUST(bytesize, M, X, RANDOM)
-#define ADJUST_ALIGNMENT(M, X) _ADD_ADJUST(alignment, M, X, RANDOM)
-#define ADJUST_FLOAT_FORMAT(M, X)    _ADD_ADJUST(format, M, X, FLOAT)
+#define ADJUST_BYTESIZE(M, X)  _ADD_ADJUST(bytesize, M, X, RANDOM, RANDOM)
+#define ADJUST_ALIGNMENT(M, X) _ADD_ADJUST(alignment, M, X, RANDOM, RANDOM)
+#define ADJUST_FLOAT_FORMAT(M, X)    _ADD_ADJUST(format, M, X, FLOAT, FLOAT)
+#define ADJUST_IBIT(M, X)  _ADD_ADJUST(ibit, M, X, ACCUM, UACCUM)
+#define ADJUST_FBIT(M, X)  _ADD_ADJUST(fbit, M, X, FRACT, UACCUM)
 
 static void
 create_modes (void)
 
 static void
 create_modes (void)
@@ -634,54 +724,62 @@ create_modes (void)
 /* Processing.  */
 
 /* Sort a list of modes into the order needed for the WIDER field:
 /* Processing.  */
 
 /* Sort a list of modes into the order needed for the WIDER field:
-   major sort by bitsize, minor sort by component bitsize.
+   major sort by precision, minor sort by component precision.
 
    For instance:
      QI < HI < SI < DI < TI
      V4QI < V2HI < V8QI < V4HI < V2SI.
 
 
    For instance:
      QI < HI < SI < DI < TI
      V4QI < V2HI < V8QI < V4HI < V2SI.
 
-   If the bitsize is not set, sort by the bytesize.  A mode with
-   bitsize set gets sorted before a mode without bitsize set, if
+   If the precision is not set, sort by the bytesize.  A mode with
+   precision set gets sorted before a mode without precision set, if
    they have the same bytesize; this is the right thing because
    they have the same bytesize; this is the right thing because
-   the bitsize must always be smaller than the bytesize * BITS_PER_UNIT.
+   the precision must always be smaller than the bytesize * BITS_PER_UNIT.
    We don't have to do anything special to get this done -- an unset
    We don't have to do anything special to get this done -- an unset
-   bitsize shows up as (unsigned int)-1, i.e. UINT_MAX.  */
+   precision shows up as (unsigned int)-1, i.e. UINT_MAX.  */
 static int
 cmp_modes (const void *a, const void *b)
 {
 static int
 cmp_modes (const void *a, const void *b)
 {
-  struct mode_data *m = *(struct mode_data **)a;
-  struct mode_data *n = *(struct mode_data **)b;
+  const struct mode_data *const m = *(const struct mode_data *const*)a;
+  const struct mode_data *const n = *(const struct mode_data *const*)b;
 
   if (m->bytesize > n->bytesize)
     return 1;
   else if (m->bytesize < n->bytesize)
     return -1;
 
 
   if (m->bytesize > n->bytesize)
     return 1;
   else if (m->bytesize < n->bytesize)
     return -1;
 
-  if (m->bitsize > n->bitsize)
+  if (m->precision > n->precision)
     return 1;
     return 1;
-  else if (m->bitsize < n->bitsize)
+  else if (m->precision < n->precision)
     return -1;
 
   if (!m->component && !n->component)
     return -1;
 
   if (!m->component && !n->component)
-    return 0;
+    {
+      if (m->counter < n->counter)
+       return -1;
+      else
+       return 1;
+    }
 
   if (m->component->bytesize > n->component->bytesize)
     return 1;
   else if (m->component->bytesize < n->component->bytesize)
     return -1;
 
 
   if (m->component->bytesize > n->component->bytesize)
     return 1;
   else if (m->component->bytesize < n->component->bytesize)
     return -1;
 
-  if (m->component->bitsize > n->component->bitsize)
+  if (m->component->precision > n->component->precision)
     return 1;
     return 1;
-  else if (m->component->bitsize < n->component->bitsize)
+  else if (m->component->precision < n->component->precision)
     return -1;
 
     return -1;
 
-  return 0;
+  if (m->counter < n->counter)
+    return -1;
+  else
+    return 1;
 }
 
 static void
 calc_wider_mode (void)
 {
 }
 
 static void
 calc_wider_mode (void)
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
   struct mode_data **sortbuf;
   unsigned int max_n_modes = 0;
   struct mode_data *m;
   struct mode_data **sortbuf;
   unsigned int max_n_modes = 0;
@@ -692,7 +790,7 @@ calc_wider_mode (void)
 
   /* Allocate max_n_modes + 1 entries to leave room for the extra null
      pointer assigned after the qsort call below.  */
 
   /* Allocate max_n_modes + 1 entries to leave room for the extra null
      pointer assigned after the qsort call below.  */
-  sortbuf = alloca ((max_n_modes + 1) * sizeof (struct mode_data *));
+  sortbuf = (struct mode_data **) alloca ((max_n_modes + 1) * sizeof (struct mode_data *));
 
   for (c = 0; c < MAX_MODE_CLASS; c++)
     {
 
   for (c = 0; c < MAX_MODE_CLASS; c++)
     {
@@ -706,6 +804,7 @@ calc_wider_mode (void)
          for (prev = 0, m = modes[c]; m; m = next)
            {
              m->wider = void_mode;
          for (prev = 0, m = modes[c]; m; m = next)
            {
              m->wider = void_mode;
+             m->wider_2x = void_mode;
 
              /* this is nreverse */
              next = m->next;
 
              /* this is nreverse */
              next = m->next;
@@ -737,8 +836,7 @@ calc_wider_mode (void)
 /* Output routines.  */
 
 #define tagged_printf(FMT, ARG, TAG) do {              \
 /* Output routines.  */
 
 #define tagged_printf(FMT, ARG, TAG) do {              \
-  int count_;                                          \
-  printf ("  " FMT ",%n", ARG, &count_);               \
+  int count_ = printf ("  " FMT ",", ARG);             \
   printf ("%*s/* %s */\n", 27 - count_, "", TAG);      \
 } while (0)
 
   printf ("%*s/* %s */\n", 27 - count_, "", TAG);      \
 } while (0)
 
@@ -754,7 +852,7 @@ calc_wider_mode (void)
 static void
 emit_insn_modes_h (void)
 {
 static void
 emit_insn_modes_h (void)
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m, *first, *last;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
   struct mode_data *m, *first, *last;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
@@ -772,8 +870,7 @@ enum machine_mode\n{");
   for (c = 0; c < MAX_MODE_CLASS; c++)
     for (m = modes[c]; m; m = m->next)
       {
   for (c = 0; c < MAX_MODE_CLASS; c++)
     for (m = modes[c]; m; m = m->next)
       {
-       int count_;
-       printf ("  %smode,%n", m->name, &count_);
+       int count_ = printf ("  %smode,", m->name);
        printf ("%*s/* %s:%d */\n", 27 - count_, "",
                 trim_filename (m->file), m->line);
       }
        printf ("%*s/* %s:%d */\n", 27 - count_, "",
                 trim_filename (m->file), m->line);
       }
@@ -791,7 +888,7 @@ enum machine_mode\n{");
         end will try to use it for bitfields in structures and the
         like, which we do not want.  Only the target md file should
         generate BImode widgets.  */
         end will try to use it for bitfields in structures and the
         like, which we do not want.  Only the target md file should
         generate BImode widgets.  */
-      if (first && first->bitsize == 1)
+      if (first && first->precision == 1)
        first = first->next;
 
       if (first && last)
        first = first->next;
 
       if (first && last)
@@ -814,6 +911,8 @@ enum machine_mode\n{");
 #if 0 /* disabled for backward compatibility, temporary */
   printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
 #endif
 #if 0 /* disabled for backward compatibility, temporary */
   printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
 #endif
+  printf ("#define CONST_MODE_IBIT%s\n", adj_ibit ? "" : " const");
+  printf ("#define CONST_MODE_FBIT%s\n", adj_fbit ? "" : " const");
   puts ("\
 \n\
 #endif /* insn-modes.h */");
   puts ("\
 \n\
 #endif /* insn-modes.h */");
@@ -855,7 +954,7 @@ emit_min_insn_modes_c_header (void)
 static void
 emit_mode_name (void)
 {
 static void
 emit_mode_name (void)
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
 
   print_decl ("char *const", "mode_name", "NUM_MACHINE_MODES");
   struct mode_data *m;
 
   print_decl ("char *const", "mode_name", "NUM_MACHINE_MODES");
@@ -869,28 +968,28 @@ emit_mode_name (void)
 static void
 emit_mode_class (void)
 {
 static void
 emit_mode_class (void)
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
 
   print_decl ("unsigned char", "mode_class", "NUM_MACHINE_MODES");
 
   for_all_modes (c, m)
   struct mode_data *m;
 
   print_decl ("unsigned char", "mode_class", "NUM_MACHINE_MODES");
 
   for_all_modes (c, m)
-    tagged_printf ("%s", mode_class_names[m->class], m->name);
+    tagged_printf ("%s", mode_class_names[m->cl], m->name);
 
   print_closer ();
 }
 
 static void
 
   print_closer ();
 }
 
 static void
-emit_mode_bitsize (void)
+emit_mode_precision (void)
 {
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
 
   struct mode_data *m;
 
-  print_decl ("unsigned short", "mode_bitsize", "NUM_MACHINE_MODES");
+  print_decl ("unsigned short", "mode_precision", "NUM_MACHINE_MODES");
 
   for_all_modes (c, m)
 
   for_all_modes (c, m)
-    if (m->bitsize != (unsigned int)-1)
-      tagged_printf ("%u", m->bitsize, m->name);
+    if (m->precision != (unsigned int)-1)
+      tagged_printf ("%u", m->precision, m->name);
     else
       tagged_printf ("%u*BITS_PER_UNIT", m->bytesize, m->name);
 
     else
       tagged_printf ("%u*BITS_PER_UNIT", m->bytesize, m->name);
 
@@ -900,7 +999,7 @@ emit_mode_bitsize (void)
 static void
 emit_mode_size (void)
 {
 static void
 emit_mode_size (void)
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
 
   print_maybe_const_decl ("%sunsigned char", "mode_size",
   struct mode_data *m;
 
   print_maybe_const_decl ("%sunsigned char", "mode_size",
@@ -913,18 +1012,15 @@ emit_mode_size (void)
 }
 
 static void
 }
 
 static void
-emit_mode_unit_size (void)
+emit_mode_nunits (void)
 {
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
 
   struct mode_data *m;
 
-  print_decl ("unsigned char", "mode_unit_size", "NUM_MACHINE_MODES");
+  print_decl ("unsigned char", "mode_nunits", "NUM_MACHINE_MODES");
 
   for_all_modes (c, m)
 
   for_all_modes (c, m)
-    tagged_printf ("%u",
-                  m->component
-                  ? m->component->bytesize : m->bytesize,
-                  m->name);
+    tagged_printf ("%u", m->ncomponents, m->name);
 
   print_closer ();
 }
 
   print_closer ();
 }
@@ -932,7 +1028,7 @@ emit_mode_unit_size (void)
 static void
 emit_mode_wider (void)
 {
 static void
 emit_mode_wider (void)
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
 
   print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES");
   struct mode_data *m;
 
   print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES");
@@ -943,12 +1039,45 @@ emit_mode_wider (void)
                   m->name);
 
   print_closer ();
                   m->name);
 
   print_closer ();
+  print_decl ("unsigned char", "mode_2xwider", "NUM_MACHINE_MODES");
+
+  for_all_modes (c, m)
+    {
+      struct mode_data * m2;
+
+      for (m2 = m;
+          m2 && m2 != void_mode;
+          m2 = m2->wider)
+       {
+         if (m2->bytesize < 2 * m->bytesize)
+           continue;
+         if (m->precision != (unsigned int) -1)
+           {
+             if (m2->precision != 2 * m->precision)
+               continue;
+           }
+         else
+           {
+             if (m2->precision != (unsigned int) -1)
+               continue;
+           }
+
+         break;
+       }
+      if (m2 == void_mode)
+       m2 = 0;
+      tagged_printf ("%smode",
+                    m2 ? m2->name : void_mode->name,
+                    m->name);
+    }
+
+  print_closer ();
 }
 
 static void
 emit_mode_mask (void)
 {
 }
 
 static void
 emit_mode_mask (void)
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
 
   print_decl ("unsigned HOST_WIDE_INT", "mode_mask_array",
   struct mode_data *m;
 
   print_decl ("unsigned HOST_WIDE_INT", "mode_mask_array",
@@ -960,8 +1089,8 @@ emit_mode_mask (void)
    : ((unsigned HOST_WIDE_INT) 1 << (m)) - 1\n");
 
   for_all_modes (c, m)
    : ((unsigned HOST_WIDE_INT) 1 << (m)) - 1\n");
 
   for_all_modes (c, m)
-    if (m->bitsize != (unsigned int)-1)
-      tagged_printf ("MODE_MASK (%u)", m->bitsize, m->name);
+    if (m->precision != (unsigned int)-1)
+      tagged_printf ("MODE_MASK (%u)", m->precision, m->name);
     else
       tagged_printf ("MODE_MASK (%u*BITS_PER_UNIT)", m->bytesize, m->name);
 
     else
       tagged_printf ("MODE_MASK (%u*BITS_PER_UNIT)", m->bytesize, m->name);
 
@@ -972,7 +1101,7 @@ emit_mode_mask (void)
 static void
 emit_mode_inner (void)
 {
 static void
 emit_mode_inner (void)
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
 
   print_decl ("unsigned char", "mode_inner", "NUM_MACHINE_MODES");
   struct mode_data *m;
 
   print_decl ("unsigned char", "mode_inner", "NUM_MACHINE_MODES");
@@ -988,7 +1117,7 @@ emit_mode_inner (void)
 static void
 emit_mode_base_align (void)
 {
 static void
 emit_mode_base_align (void)
 {
-  enum mode_class c;
+  int c;
   struct mode_data *m;
 
   print_maybe_const_decl ("%sunsigned char",
   struct mode_data *m;
 
   print_maybe_const_decl ("%sunsigned char",
@@ -1004,7 +1133,7 @@ emit_mode_base_align (void)
 static void
 emit_class_narrowest_mode (void)
 {
 static void
 emit_class_narrowest_mode (void)
 {
-  enum mode_class c;
+  int c;
 
   print_decl ("unsigned char", "class_narrowest_mode", "MAX_MODE_CLASS");
 
 
   print_decl ("unsigned char", "class_narrowest_mode", "MAX_MODE_CLASS");
 
@@ -1012,13 +1141,13 @@ emit_class_narrowest_mode (void)
     /* Bleah, all this to get the comment right for MIN_MODE_INT.  */
     tagged_printf ("MIN_%s", mode_class_names[c],
                   modes[c]
     /* Bleah, all this to get the comment right for MIN_MODE_INT.  */
     tagged_printf ("MIN_%s", mode_class_names[c],
                   modes[c]
-                  ? (modes[c]->bitsize != 1
+                  ? (modes[c]->precision != 1
                      ? modes[c]->name
                      : (modes[c]->next
                         ? modes[c]->next->name
                         : void_mode->name))
                   : void_mode->name);
                      ? modes[c]->name
                      : (modes[c]->next
                         ? modes[c]->next->name
                         : void_mode->name))
                   : void_mode->name);
-  
+
   print_closer ();
 }
 
   print_closer ();
 }
 
@@ -1040,15 +1169,24 @@ emit_real_format_for_mode (void)
                          format);
 #else
   print_decl ("struct real_format *\n", "real_format_for_mode",
                          format);
 #else
   print_decl ("struct real_format *\n", "real_format_for_mode",
-             "MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1");
+             "MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1 "
+             "+ MAX_MODE_DECIMAL_FLOAT - MIN_MODE_DECIMAL_FLOAT + 1");
 #endif
 
 #endif
 
+  /* The beginning of the table is entries for float modes.  */
   for (m = modes[MODE_FLOAT]; m; m = m->next)
     if (!strcmp (m->format, "0"))
       tagged_printf ("%s", m->format, m->name);
     else
       tagged_printf ("&%s", m->format, m->name);
 
   for (m = modes[MODE_FLOAT]; m; m = m->next)
     if (!strcmp (m->format, "0"))
       tagged_printf ("%s", m->format, m->name);
     else
       tagged_printf ("&%s", m->format, m->name);
 
+  /* The end of the table is entries for decimal float modes.  */
+  for (m = modes[MODE_DECIMAL_FLOAT]; m; m = m->next)
+    if (!strcmp (m->format, "0"))
+      tagged_printf ("%s", m->format, m->name);
+    else
+      tagged_printf ("&%s", m->format, m->name);
+
   print_closer ();
 }
 
   print_closer ();
 }
 
@@ -1056,37 +1194,162 @@ static void
 emit_mode_adjustments (void)
 {
   struct mode_adjust *a;
 emit_mode_adjustments (void)
 {
   struct mode_adjust *a;
+  struct mode_data *m;
 
 
-  puts ("\nvoid\ninit_adjust_machine_modes (void)\n{");
+  puts ("\
+\nvoid\
+\ninit_adjust_machine_modes (void)\
+\n{\
+\n  size_t s ATTRIBUTE_UNUSED;");
 
 
+  /* Size adjustments must be propagated to all containing modes.
+     A size adjustment forces us to recalculate the alignment too.  */
   for (a = adj_bytesize; a; a = a->next)
   for (a = adj_bytesize; a; a = a->next)
-    printf ("  /* %s:%d */\n  mode_size[%smode] = %s;\n",
-           a->file, a->line, a->mode->name, a->adjustment);
-  if (adj_bytesize && (adj_alignment || adj_format))
-    putchar ('\n');
+    {
+      printf ("\n  /* %s:%d */\n  s = %s;\n",
+             a->file, a->line, a->adjustment);
+      printf ("  mode_size[%smode] = s;\n", a->mode->name);
+      printf ("  mode_base_align[%smode] = s & (~s + 1);\n",
+             a->mode->name);
+
+      for (m = a->mode->contained; m; m = m->next_cont)
+       {
+         switch (m->cl)
+           {
+           case MODE_COMPLEX_INT:
+           case MODE_COMPLEX_FLOAT:
+             printf ("  mode_size[%smode] = 2*s;\n", m->name);
+             printf ("  mode_base_align[%smode] = s & (~s + 1);\n",
+                     m->name);
+             break;
+
+           case MODE_VECTOR_INT:
+           case MODE_VECTOR_FLOAT:
+           case MODE_VECTOR_FRACT:
+           case MODE_VECTOR_UFRACT:
+           case MODE_VECTOR_ACCUM:
+           case MODE_VECTOR_UACCUM:
+             printf ("  mode_size[%smode] = %d*s;\n",
+                     m->name, m->ncomponents);
+             printf ("  mode_base_align[%smode] = (%d*s) & (~(%d*s)+1);\n",
+                     m->name, m->ncomponents, m->ncomponents);
+             break;
+
+           default:
+             internal_error (
+             "mode %s is neither vector nor complex but contains %s",
+             m->name, a->mode->name);
+             /* NOTREACHED */
+           }
+       }
+    }
 
 
+  /* Alignment adjustments propagate too.
+     ??? This may not be the right thing for vector modes.  */
   for (a = adj_alignment; a; a = a->next)
   for (a = adj_alignment; a; a = a->next)
-    printf ("  /* %s:%d */\n  mode_base_align[%smode] = %s;\n",
-           a->file, a->line, a->mode->name, a->adjustment);
-  if (adj_alignment && adj_format)
-    putchar ('\n');
+    {
+      printf ("\n  /* %s:%d */\n  s = %s;\n",
+             a->file, a->line, a->adjustment);
+      printf ("  mode_base_align[%smode] = s;\n", a->mode->name);
+
+      for (m = a->mode->contained; m; m = m->next_cont)
+       {
+         switch (m->cl)
+           {
+           case MODE_COMPLEX_INT:
+           case MODE_COMPLEX_FLOAT:
+             printf ("  mode_base_align[%smode] = s;\n", m->name);
+             break;
+
+           case MODE_VECTOR_INT:
+           case MODE_VECTOR_FLOAT:
+           case MODE_VECTOR_FRACT:
+           case MODE_VECTOR_UFRACT:
+           case MODE_VECTOR_ACCUM:
+           case MODE_VECTOR_UACCUM:
+             printf ("  mode_base_align[%smode] = %d*s;\n",
+                     m->name, m->ncomponents);
+             break;
+
+           default:
+             internal_error (
+             "mode %s is neither vector nor complex but contains %s",
+             m->name, a->mode->name);
+             /* NOTREACHED */
+           }
+       }
+    }
 
 
+  /* Ibit adjustments don't have to propagate.  */
+  for (a = adj_ibit; a; a = a->next)
+    {
+      printf ("\n  /* %s:%d */\n  s = %s;\n",
+             a->file, a->line, a->adjustment);
+      printf ("  mode_ibit[%smode] = s;\n", a->mode->name);
+    }
+
+  /* Fbit adjustments don't have to propagate.  */
+  for (a = adj_fbit; a; a = a->next)
+    {
+      printf ("\n  /* %s:%d */\n  s = %s;\n",
+             a->file, a->line, a->adjustment);
+      printf ("  mode_fbit[%smode] = s;\n", a->mode->name);
+    }
+
+  /* Real mode formats don't have to propagate anywhere.  */
   for (a = adj_format; a; a = a->next)
   for (a = adj_format; a; a = a->next)
-    printf ("  /* %s:%d */\n  REAL_MODE_FORMAT (%smode) = %s;\n",
+    printf ("\n  /* %s:%d */\n  REAL_MODE_FORMAT (%smode) = %s;\n",
            a->file, a->line, a->mode->name, a->adjustment);
 
   puts ("}");
 }
 
            a->file, a->line, a->mode->name, a->adjustment);
 
   puts ("}");
 }
 
+/* Emit ibit for all modes.  */
+
+static void
+emit_mode_ibit (void)
+{
+  int c;
+  struct mode_data *m;
+
+  print_maybe_const_decl ("%sunsigned char",
+                         "mode_ibit", "NUM_MACHINE_MODES",
+                         ibit);
+
+  for_all_modes (c, m)
+    tagged_printf ("%u", m->ibit, m->name);
+
+  print_closer ();
+}
+
+/* Emit fbit for all modes.  */
+
+static void
+emit_mode_fbit (void)
+{
+  int c;
+  struct mode_data *m;
+
+  print_maybe_const_decl ("%sunsigned char",
+                         "mode_fbit", "NUM_MACHINE_MODES",
+                         fbit);
+
+  for_all_modes (c, m)
+    tagged_printf ("%u", m->fbit, m->name);
+
+  print_closer ();
+}
+
+
 static void
 emit_insn_modes_c (void)
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
   emit_mode_class ();
 static void
 emit_insn_modes_c (void)
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
   emit_mode_class ();
-  emit_mode_bitsize ();
+  emit_mode_precision ();
   emit_mode_size ();
   emit_mode_size ();
-  emit_mode_unit_size ();
+  emit_mode_nunits ();
   emit_mode_wider ();
   emit_mode_mask ();
   emit_mode_inner ();
   emit_mode_wider ();
   emit_mode_mask ();
   emit_mode_inner ();
@@ -1094,6 +1357,8 @@ emit_insn_modes_c (void)
   emit_class_narrowest_mode ();
   emit_real_format_for_mode ();
   emit_mode_adjustments ();
   emit_class_narrowest_mode ();
   emit_real_format_for_mode ();
   emit_mode_adjustments ();
+  emit_mode_ibit ();
+  emit_mode_fbit ();
 }
 
 static void
 }
 
 static void
@@ -1108,7 +1373,7 @@ emit_min_insn_modes_c (void)
 
 /* Master control.  */
 int
 
 /* Master control.  */
 int
-main(int argc, char **argv)
+main (int argc, char **argv)
 {
   bool gen_header = false, gen_min = false;
   progname = argv[0];
 {
   bool gen_header = false, gen_min = false;
   progname = argv[0];
@@ -1132,7 +1397,7 @@ main(int argc, char **argv)
 
   if (have_error)
     return FATAL_EXIT_CODE;
 
   if (have_error)
     return FATAL_EXIT_CODE;
-  
+
   calc_wider_mode ();
 
   if (gen_header)
   calc_wider_mode ();
 
   if (gen_header)