* elf64-ppc.c (dec_dynrel_count): Don't error when elf_gc_sweep_symbol
[external/binutils.git] / sim / igen / ld-insn.c
index 8d33a3e..1cbb9b8 100644 (file)
@@ -1,22 +1,23 @@
-/*  This file is part of the program psim.
+/* The IGEN simulator generator for GDB, the GNU Debugger.
 
-    Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
+   Copyright 2002-2013 Free Software Foundation, Inc.
 
-    This program 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 of the License, or
-    (at your option) any later version.
+   Contributed by Andrew Cagney.
 
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-    */
+   This file is part of GDB.
+
+   This program 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 #include "misc.h"
@@ -27,9 +28,7 @@
 #include "ld-insn.h"
 
 static insn_word_entry *
-parse_insn_word (line_ref *line,
-                char *string,
-                int word_nr)
+parse_insn_word (line_ref *line, char *string, int word_nr)
 {
   char *chp;
   insn_word_entry *word = ZALLOC (insn_word_entry);
@@ -53,215 +52,253 @@ parse_insn_word (line_ref *line,
   /* now work through the formats */
   chp = skip_spaces (string);
 
-  while (*chp != '\0') {
-    char *start_pos;
-    int strlen_pos;
-    char *start_val;
-    int strlen_val;
-    insn_field_entry *new_field;
-
-    /* create / link in the new field */
-    new_field = ZALLOC (insn_field_entry);
-    new_field->next = word->last;
-    new_field->prev = word->last->prev;
-    new_field->next->prev = new_field;
-    new_field->prev->next = new_field;
-    new_field->word_nr = word_nr;
-
-    /* break out the first field (if present) */
-    start_pos = chp;
-    chp = skip_to_separator (chp, ".,!");
-    strlen_pos = back_spaces (start_pos, chp) - start_pos;
-
-    /* break out the second field (if present) */
-    if (*chp != '.')
-      {
-       /* assume what was specified was the value (and not the start
-           position).  Assume the value length implicitly specifies
-           the number of bits */
-       start_val = start_pos;
-       strlen_val = strlen_pos;
-       start_pos = "";
-       strlen_pos = 0;
-      }
-    else
-      {
-       chp++; /* skip `.' */
-       chp = skip_spaces (chp);
-       start_val = chp;
-       if (*chp == '/' || *chp == '*')
-         {
-           do
-             {
-               chp++;
-             }
-           while (*chp == '/' || *chp == '*');
-         }
-       else if (isalpha(*start_val))
-         {
-           do
-             {
-               chp++;
-             }
-           while (isalnum(*chp) || *chp == '_');
-         }
-       else if (isdigit(*start_val))
-         {
-           do {
-             chp++;
+  while (*chp != '\0')
+    {
+      char *start_pos;
+      int strlen_pos;
+      char *start_val;
+      int strlen_val;
+      insn_field_entry *new_field;
+
+      /* create / link in the new field */
+      new_field = ZALLOC (insn_field_entry);
+      new_field->next = word->last;
+      new_field->prev = word->last->prev;
+      new_field->next->prev = new_field;
+      new_field->prev->next = new_field;
+      new_field->word_nr = word_nr;
+
+      /* break out the first field (if present) */
+      start_pos = chp;
+      chp = skip_to_separator (chp, ".,!");
+      strlen_pos = back_spaces (start_pos, chp) - start_pos;
+
+      /* break out the second field (if present) */
+      if (*chp != '.')
+       {
+         /* assume what was specified was the value (and not the start
+            position).  Assume the value length implicitly specifies
+            the number of bits */
+         start_val = start_pos;
+         strlen_val = strlen_pos;
+         start_pos = "";
+         strlen_pos = 0;
+       }
+      else
+       {
+         chp++;                /* skip `.' */
+         chp = skip_spaces (chp);
+         start_val = chp;
+         if (*chp == '/' || *chp == '*')
+           {
+             do
+               {
+                 chp++;
+               }
+             while (*chp == '/' || *chp == '*');
            }
-           while (isalnum(*chp));
-         }
-       strlen_val = chp - start_val;
-       chp = skip_spaces (chp);
-      }
-    if (strlen_val == 0)
-      error (line, "Empty value field");
-    
-    /* break out any conditional fields - { "!" <value> } */
-    while (*chp == '!')
-      {
-       char *start;
-       int len;
-       insn_field_exclusion *new_exclusion = ZALLOC (insn_field_exclusion);
-       insn_field_exclusion **last;
-       
-       /* what type of conditional field */
-       chp++; 
-       chp = skip_spaces (chp);
-       /* the value */
-       start = chp;
-       chp = skip_digits (chp);
-       len = chp - start;
-       if (len == 0)
-         error (line, "Missing or invalid conditional value\n");
-       /* fill in the entry */
-       new_exclusion->string = NZALLOC (char, len + 1);
-       strncpy (new_exclusion->string, start, len);
-       new_exclusion->value = a2i (new_exclusion->string);
-       /* insert it */
-       last = &new_field->exclusions;
-       while (*last != NULL)
-         last = &(*last)->next;
-       *last = new_exclusion;
-       chp = skip_spaces (chp);
-      }
+         else if (isalpha (*start_val))
+           {
+             do
+               {
+                 chp++;
+               }
+             while (isalnum (*chp) || *chp == '_');
+           }
+         else if (isdigit (*start_val))
+           {
+             do
+               {
+                 chp++;
+               }
+             while (isalnum (*chp));
+           }
+         strlen_val = chp - start_val;
+         chp = skip_spaces (chp);
+       }
+      if (strlen_val == 0)
+       error (line, "Empty value field\n");
 
-    /* NOW verify that the field ws finished */
-    if (*chp == ',')
-      {
-       chp = skip_spaces (chp + 1);
-       if (*chp == '\0')
-         error (line, "empty field\n");
-      }
-    else if (*chp != '\0')
-      {
-       error (line, "Missing field separator");
-      }
+      /* break out any conditional fields - { [ "!" | "=" [ <value> | <field-name> } */
+      while (*chp == '!' || *chp == '=')
+       {
+         char *start;
+         char *end;
+         int len;
+         insn_field_cond *new_cond = ZALLOC (insn_field_cond);
 
-    /* copy the value */
-    new_field->val_string = NZALLOC (char, strlen_val+1);
-    strncpy (new_field->val_string, start_val, strlen_val);
-    if (isdigit (new_field->val_string[0]))
-      {
-       if (strlen_pos == 0)
-         {
-           /* when the length/pos field is omited, an integer field
-               is always binary */
-           unsigned64 val = 0;
-           int i;
-           for (i = 0; i < strlen_val; i++)
-             {
-               if (new_field->val_string[i] != '0'
-                   && new_field->val_string[i] != '1')
-                 error (line, "invalid binary field %s\n",
-                        new_field->val_string);
-               val = (val << 1) + (new_field->val_string[i] == '1');
-             }
-           new_field->val_int = val;
-           new_field->type = insn_field_int;
-         }
-       else
-         {
-           new_field->val_int = a2i (new_field->val_string);
-           new_field->type = insn_field_int;
-         }
-      }
-    else if (new_field->val_string[0] == '/')
-      {
-       new_field->type = insn_field_reserved;
-      }
-    else if (new_field->val_string[0] == '*')
-      {
-       new_field->type = insn_field_wild;
-      }
-    else
-      {
-       new_field->type = insn_field_string;
-       if (filter_is_member (word->field_names, new_field->val_string))
-         error (line, "Field name %s is duplicated\n", new_field->val_string);
-       filter_parse (&word->field_names, new_field->val_string);
-      }
-    if (new_field->type != insn_field_string
-       && new_field->exclusions != NULL)
-      error (line, "Exclusions only apply to name fields\n");
-
-    /* the copy the position */
-    new_field->pos_string = NZALLOC (char, strlen_pos + 1);
-    strncpy (new_field->pos_string, start_pos, strlen_pos);
-    if (strlen_pos == 0)
-      {
-       new_field->first = new_field->prev->last + 1;
-       if (new_field->first == 0 /* first field */
-           && *chp == '\0' /* no further fields */
-           && new_field->type == insn_field_string)
-         {
-           /* A single string without any position, assume that it
-               represents the entire instruction word */
-           new_field->width = options.insn_bit_size;
-         }
-       else
+         /* determine the conditional test */
+         switch (*chp)
+           {
+           case '=':
+             new_cond->test = insn_field_cond_eq;
+             break;
+           case '!':
+             new_cond->test = insn_field_cond_ne;
+             break;
+           default:
+             ASSERT (0);
+           }
+
+         /* save the value */
+         chp++;
+         chp = skip_spaces (chp);
+         start = chp;
+         chp = skip_to_separator (chp, "+,:!=");
+         end = back_spaces (start, chp);
+         len = end - start;
+         if (len == 0)
+           error (line, "Missing or invalid conditional value\n");
+         new_cond->string = NZALLOC (char, len + 1);
+         strncpy (new_cond->string, start, len);
+
+         /* determine the conditional type */
+         if (isdigit (*start))
+           {
+             /* [ "!" | "=" ] <value> */
+             new_cond->type = insn_field_cond_value;
+             new_cond->value = a2i (new_cond->string);
+           }
+         else
+           {
+             /* [ "!" | "=" ] <field>  - check field valid */
+             new_cond->type = insn_field_cond_field;
+             /* new_cond->field is determined in later */
+           }
+
+         /* Only a single `=' is permitted. */
+         if ((new_cond->test == insn_field_cond_eq
+              && new_field->conditions != NULL)
+             || (new_field->conditions != NULL
+                 && new_field->conditions->test == insn_field_cond_eq))
+           error (line, "Only single conditional when `=' allowed\n");
+
+         /* insert it */
          {
-           /* No explicit width/position, assume value implicitly
-              supplies the width */
-           new_field->width = strlen_val;
+           insn_field_cond **last = &new_field->conditions;
+           while (*last != NULL)
+             last = &(*last)->next;
+           *last = new_cond;
          }
-       new_field->last = new_field->first + new_field->width - 1;
-       if (new_field->last >= options.insn_bit_size)
-         error (line, "Bit position %d exceed instruction bit size (%d)\n",
-                new_field->last, options.insn_bit_size);
-      }
-    else if (options.insn_specifying_widths)
-      {
-       new_field->first = new_field->prev->last + 1;
-       new_field->width = a2i(new_field->pos_string);
-       new_field->last = new_field->first + new_field->width - 1;
-       if (new_field->last >= options.insn_bit_size)
-         error (line, "Bit position %d exceed instruction bit size (%d)\n",
-                new_field->last, options.insn_bit_size);
-      }
-    else
-      {
-       new_field->first = target_a2i(options.hi_bit_nr,
-                                     new_field->pos_string);
-       new_field->last = new_field->next->first - 1; /* guess */
-       new_field->width = new_field->last - new_field->first + 1; /* guess */
-       new_field->prev->last = new_field->first - 1; /*fix*/
-       new_field->prev->width = new_field->first - new_field->prev->first; /*fix*/
-      }
-  }
+       }
+
+      /* NOW verify that the field was finished */
+      if (*chp == ',')
+       {
+         chp = skip_spaces (chp + 1);
+         if (*chp == '\0')
+           error (line, "empty field\n");
+       }
+      else if (*chp != '\0')
+       {
+         error (line, "Missing field separator\n");
+       }
+
+      /* copy the value */
+      new_field->val_string = NZALLOC (char, strlen_val + 1);
+      strncpy (new_field->val_string, start_val, strlen_val);
+      if (isdigit (new_field->val_string[0]))
+       {
+         if (strlen_pos == 0)
+           {
+             /* when the length/pos field is omited, an integer field
+                is always binary */
+             unsigned64 val = 0;
+             int i;
+             for (i = 0; i < strlen_val; i++)
+               {
+                 if (new_field->val_string[i] != '0'
+                     && new_field->val_string[i] != '1')
+                   error (line, "invalid binary field %s\n",
+                          new_field->val_string);
+                 val = (val << 1) + (new_field->val_string[i] == '1');
+               }
+             new_field->val_int = val;
+             new_field->type = insn_field_int;
+           }
+         else
+           {
+             new_field->val_int = a2i (new_field->val_string);
+             new_field->type = insn_field_int;
+           }
+       }
+      else if (new_field->val_string[0] == '/')
+       {
+         new_field->type = insn_field_reserved;
+       }
+      else if (new_field->val_string[0] == '*')
+       {
+         new_field->type = insn_field_wild;
+       }
+      else
+       {
+         new_field->type = insn_field_string;
+         if (filter_is_member (word->field_names, new_field->val_string))
+           error (line, "Field name %s is duplicated\n",
+                  new_field->val_string);
+         filter_parse (&word->field_names, new_field->val_string);
+       }
+      if (new_field->type != insn_field_string
+         && new_field->conditions != NULL)
+       error (line, "Conditionals can only be applied to named fields\n");
+
+      /* the copy the position */
+      new_field->pos_string = NZALLOC (char, strlen_pos + 1);
+      strncpy (new_field->pos_string, start_pos, strlen_pos);
+      if (strlen_pos == 0)
+       {
+         new_field->first = new_field->prev->last + 1;
+         if (new_field->first == 0     /* first field */
+             && *chp == '\0'   /* no further fields */
+             && new_field->type == insn_field_string)
+           {
+             /* A single string without any position, assume that it
+                represents the entire instruction word */
+             new_field->width = options.insn_bit_size;
+           }
+         else
+           {
+             /* No explicit width/position, assume value implicitly
+                supplies the width */
+             new_field->width = strlen_val;
+           }
+         new_field->last = new_field->first + new_field->width - 1;
+         if (new_field->last >= options.insn_bit_size)
+           error (line, "Bit position %d exceed instruction bit size (%d)\n",
+                  new_field->last, options.insn_bit_size);
+       }
+      else if (options.insn_specifying_widths)
+       {
+         new_field->first = new_field->prev->last + 1;
+         new_field->width = a2i (new_field->pos_string);
+         new_field->last = new_field->first + new_field->width - 1;
+         if (new_field->last >= options.insn_bit_size)
+           error (line, "Bit position %d exceed instruction bit size (%d)\n",
+                  new_field->last, options.insn_bit_size);
+       }
+      else
+       {
+         new_field->first = target_a2i (options.hi_bit_nr,
+                                        new_field->pos_string);
+         new_field->last = new_field->next->first - 1; /* guess */
+         new_field->width = new_field->last - new_field->first + 1;    /* guess */
+         new_field->prev->last = new_field->first - 1; /*fix */
+         new_field->prev->width = new_field->first - new_field->prev->first;   /*fix */
+       }
+    }
 
   /* fiddle first/last so that the sentinals disapear */
-  ASSERT(word->first->last < 0);
-  ASSERT(word->last->first >= options.insn_bit_size);
+  ASSERT (word->first->last < 0);
+  ASSERT (word->last->first >= options.insn_bit_size);
   word->first = word->first->next;
   word->last = word->last->prev;
 
   /* check that the last field goes all the way to the last bit */
   if (word->last->last != options.insn_bit_size - 1)
     {
-      options.warning (line, "Instruction format is not %d bits wide\n",
-                      options.insn_bit_size);
+      if (options.warn.width)
+       options.warning (line, "Instruction format is not %d bits wide\n",
+                        options.insn_bit_size);
       word->last->last = options.insn_bit_size - 1;
     }
 
@@ -270,8 +307,7 @@ parse_insn_word (line_ref *line,
   {
     insn_field_entry *field;
     for (field = word->first;
-        field->last < options.insn_bit_size;
-        field = field->next)
+        field->last < options.insn_bit_size; field = field->next)
       {
        int i;
        for (i = field->first; i <= field->last; i++)
@@ -280,14 +316,28 @@ parse_insn_word (line_ref *line,
            word->bit[i]->field = field;
            switch (field->type)
              {
+             case insn_field_invalid:
+               ASSERT (0);
+               break;
              case insn_field_int:
                word->bit[i]->mask = 1;
                word->bit[i]->value = ((field->val_int
-                                       & ((insn_uint)1 << (field->last - i)))
-                                      != 0);
+                                       & ((insn_uint) 1 <<
+                                          (field->last - i))) != 0);
              case insn_field_reserved:
              case insn_field_wild:
              case insn_field_string:
+               /* if we encounter a constant conditional, encode
+                  their bit value. */
+               if (field->conditions != NULL
+                   && field->conditions->test == insn_field_cond_eq
+                   && field->conditions->type == insn_field_cond_value)
+                 {
+                   word->bit[i]->mask = 1;
+                   word->bit[i]->value = ((field->conditions->value
+                                           & ((insn_uint) 1 <<
+                                              (field->last - i))) != 0);
+                 }
                break;
              }
          }
@@ -299,8 +349,7 @@ parse_insn_word (line_ref *line,
 
 
 static void
-parse_insn_words (insn_entry *insn,
-                 char *formats)
+parse_insn_words (insn_entry * insn, char *formats)
 {
   insn_word_entry **last_word = &insn->words;
   char *chp;
@@ -350,21 +399,77 @@ parse_insn_words (insn_entry *insn,
       chp++;
     }
 
-  /* now create a quick access array of the same structure */
+  /* create a quick access array (indexed by word) of the same structure */
   {
     int i;
     insn_word_entry *word;
     insn->word = NZALLOC (insn_word_entry *, insn->nr_words + 1);
     for (i = 0, word = insn->words;
-        i < insn->nr_words;
-        i++, word = word->next)
+        i < insn->nr_words; i++, word = word->next)
       insn->word[i] = word;
   }
+
+  /* Go over all fields that have conditionals refering to other
+     fields.  Link the fields up.  Verify that the two fields have the
+     same size. Verify that the two fields are different */
+  {
+    int i;
+    for (i = 0; i < insn->nr_words; i++)
+      {
+       insn_word_entry *word = insn->word[i];
+       insn_field_entry *f;
+       for (f = word->first; f->last < options.insn_bit_size; f = f->next)
+         {
+           insn_field_cond *cond;
+           for (cond = f->conditions; cond != NULL; cond = cond->next)
+             {
+               if (cond->type == insn_field_cond_field)
+                 {
+                   int j;
+                   if (strcmp (cond->string, f->val_string) == 0)
+                     error (insn->line,
+                            "Conditional `%s' of field `%s' refers to its self\n",
+                            cond->string, f->val_string);
+                   for (j = 0; j <= i && cond->field == NULL; j++)
+                     {
+                       insn_word_entry *refered_word = insn->word[j];
+                       insn_field_entry *refered_field;
+                       for (refered_field = refered_word->first;
+                            refered_field != NULL && cond->field == NULL;
+                            refered_field = refered_field->next)
+                         {
+                           if (refered_field->type == insn_field_string
+                               && strcmp (refered_field->val_string,
+                                          cond->string) == 0)
+                             {
+                               /* found field being refered to by conditonal */
+                               cond->field = refered_field;
+                               /* check refered to and this field are
+                                  the same size */
+                               if (f->width != refered_field->width)
+                                 error (insn->line,
+                                        "Conditional `%s' of field `%s' should be of size %s\n",
+                                        cond->string, f->val_string,
+                                        refered_field->width);
+                             }
+                         }
+                     }
+                   if (cond->field == NULL)
+                     error (insn->line,
+                            "Conditional `%s' of field `%s' not yet defined\n",
+                            cond->string, f->val_string);
+                 }
+             }
+         }
+      }
+  }
+
 }
 
-typedef enum {
+typedef enum
+{
   unknown_record = 0,
-  insn_record, /* default */
+  insn_record,                 /* default */
   code_record,
   cache_record,
   compute_record,
@@ -374,30 +479,33 @@ typedef enum {
   function_record,
   internal_record,
   define_record,
+  include_record,
   model_processor_record,
   model_macro_record,
   model_data_record,
   model_static_record,
   model_function_record,
   model_internal_record,
-} insn_record_type;
+}
+insn_record_type;
 
 static const name_map insn_type_map[] = {
-  { "option", option_record },
-  { "cache", cache_record },
-  { "compute", compute_record },
-  { "scratch", scratch_record },
-  { "define", define_record },
-  { "%s", string_function_record },
-  { "function", function_record },
-  { "internal", internal_record },
-  { "model", model_processor_record },
-  { "model-macro", model_macro_record },
-  { "model-data", model_data_record },
-  { "model-static", model_static_record },
-  { "model-internal", model_internal_record },
-  { "model-function", model_function_record },
-  { NULL, insn_record },
+  {"option", option_record},
+  {"cache", cache_record},
+  {"compute", compute_record},
+  {"scratch", scratch_record},
+  {"define", define_record},
+  {"include", include_record},
+  {"%s", string_function_record},
+  {"function", function_record},
+  {"internal", internal_record},
+  {"model", model_processor_record},
+  {"model-macro", model_macro_record},
+  {"model-data", model_data_record},
+  {"model-static", model_static_record},
+  {"model-internal", model_internal_record},
+  {"model-function", model_function_record},
+  {NULL, insn_record},
 };
 
 
@@ -442,15 +550,13 @@ record_type (table_entry *entry)
          return i;
        }
       else
-       return insn_record; /* default */
+       return insn_record;     /* default */
     }
   return unknown_record;
 }
 
 static int
-record_prefix_is (table_entry *entry,
-                 char ch,
-                 int nr_fields)
+record_prefix_is (table_entry *entry, char ch, int nr_fields)
 {
   if (entry->type != table_colon_entry)
     return 0;
@@ -465,8 +571,7 @@ static table_entry *
 parse_model_data_record (insn_table *isa,
                         table *file,
                         table_entry *record,
-                        int nr_fields,
-                        model_data **list)
+                        int nr_fields, model_data **list)
 {
   table_entry *model_record = record;
   table_entry *code_record = NULL;
@@ -486,15 +591,22 @@ parse_model_data_record (insn_table *isa,
                model_record->field[record_filter_flags_field]);
   new_data->entry = model_record;
   new_data->code = code_record;
-  /* append it */
-  while (*list != NULL)
-    list = &(*list)->next;
-  *list = new_data;
+  /* append it if not filtered out */
+  if (!is_filtered_out (options.flags_filter,
+                       model_record->field[record_filter_flags_field])
+      && !is_filtered_out (options.model_filter,
+                          model_record->field[record_filter_models_field]))
+    {
+      while (*list != NULL)
+       list = &(*list)->next;
+      *list = new_data;
+    }
   return record;
 }
 
 
-typedef enum {
+typedef enum
+{
   insn_bit_size_option = 1,
   insn_specifying_widths_option,
   hi_bit_nr_option,
@@ -502,23 +614,46 @@ typedef enum {
   model_filter_option,
   multi_sim_option,
   format_names_option,
+  gen_delayed_branch,
   unknown_option,
-} option_names;
+}
+option_names;
 
 static const name_map option_map[] = {
-  { "insn-bit-size", insn_bit_size_option },
-  { "insn-specifying-widths", insn_specifying_widths_option },
-  { "hi-bit-nr", hi_bit_nr_option },
-  { "flags-filter", flags_filter_option },
-  { "model-filter", model_filter_option },
-  { "multi-sim", multi_sim_option },
-  { "format-names", format_names_option },
-  { NULL, unknown_option },
+  {"insn-bit-size", insn_bit_size_option},
+  {"insn-specifying-widths", insn_specifying_widths_option},
+  {"hi-bit-nr", hi_bit_nr_option},
+  {"flags-filter", flags_filter_option},
+  {"model-filter", model_filter_option},
+  {"multi-sim", multi_sim_option},
+  {"format-names", format_names_option},
+  {"gen-delayed-branch", gen_delayed_branch},
+  {NULL, unknown_option},
 };
 
 static table_entry *
-parse_option_record (table *file,
-                    table_entry *record)
+parse_include_record (table *file, table_entry *record)
+{
+  /* parse the include record */
+  if (record->nr_fields < nr_include_fields)
+    error (record->line, "Incorrect nr fields for include record\n");
+  /* process it */
+  if (!is_filtered_out (options.flags_filter,
+                       record->field[record_filter_flags_field])
+      && !is_filtered_out (options.model_filter,
+                          record->field[record_filter_models_field]))
+    {
+      table_push (file, record->line, options.include,
+                 record->field[include_filename_field]);
+    }
+  /* nb: can't read next record until after the file has been pushed */
+  record = table_read (file);
+  return record;
+}
+
+
+static table_entry *
+parse_option_record (table *file, table_entry *record)
 {
   table_entry *option_record;
   /* parse the option record */
@@ -528,7 +663,9 @@ parse_option_record (table *file,
   record = table_read (file);
   /* process it */
   if (!is_filtered_out (options.flags_filter,
-                       option_record->field[record_filter_flags_field]))
+                       option_record->field[record_filter_flags_field])
+      && !is_filtered_out (options.model_filter,
+                          option_record->field[record_filter_models_field]))
     {
       char *name = option_record->field[option_name_field];
       option_names option = name2i (name, option_map);
@@ -540,10 +677,12 @@ parse_option_record (table *file,
            options.insn_bit_size = a2i (value);
            if (options.insn_bit_size < 0
                || options.insn_bit_size > max_insn_bit_size)
-             error (option_record->line, "Instruction bit size out of range\n");
+             error (option_record->line,
+                    "Instruction bit size out of range\n");
            if (options.hi_bit_nr != options.insn_bit_size - 1
                && options.hi_bit_nr != 0)
-             error (option_record->line, "insn-bit-size / hi-bit-nr conflict\n");
+             error (option_record->line,
+                    "insn-bit-size / hi-bit-nr conflict\n");
            break;
          }
        case insn_specifying_widths_option:
@@ -556,7 +695,8 @@ parse_option_record (table *file,
            options.hi_bit_nr = a2i (value);
            if (options.hi_bit_nr != 0
                && options.hi_bit_nr != options.insn_bit_size - 1)
-             error (option_record->line, "hi-bit-nr / insn-bit-size conflict\n");
+             error (option_record->line,
+                    "hi-bit-nr / insn-bit-size conflict\n");
            break;
          }
        case flags_filter_option:
@@ -579,53 +719,98 @@ parse_option_record (table *file,
            filter_parse (&options.format_name_filter, value);
            break;
          }
+       case gen_delayed_branch:
+         {
+           options.gen.delayed_branch = a2i (value);
+           break;
+         }
        case unknown_option:
          {
            error (option_record->line, "Unknown option - %s\n", name);
            break;
          }
        }
-    }  
+    }
   return record;
 }
 
+
 static table_entry *
 parse_function_record (table *file,
                       table_entry *record,
-                      function_entry **list,
-                      function_entry **list_entry,
-                      int is_internal)
+                      function_entry ** list,
+                      function_entry ** list_entry,
+                      int is_internal, model_table *model)
 {
   function_entry *new_function;
-  if (record->nr_fields < nr_function_fields)
-    error (record->line, "Missing fields from function record\n");
-  /* look for a body to the function */
   new_function = ZALLOC (function_entry);
-  /* parse the function header */
   new_function->line = record->line;
-  filter_parse (&new_function->flags,
-               record->field[record_filter_flags_field]);
+  new_function->is_internal = is_internal;
+  /* parse the function header */
   if (record_is_old (record))
-    new_function->type = record->field[old_function_typedef_field];
+    {
+      if (record->nr_fields < nr_old_function_fields)
+       error (record->line, "Missing fields from (old) function record\n");
+      new_function->type = record->field[old_function_typedef_field];
+      new_function->type = record->field[old_function_typedef_field];
+      if (record->nr_fields > old_function_param_field)
+       new_function->param = record->field[old_function_param_field];
+      new_function->name = record->field[old_function_name_field];
+    }
   else
-    new_function->type = record->field[function_typedef_field];
-  new_function->name = record->field[function_name_field];
-  if (record->nr_fields > function_param_field)
-    new_function->param = record->field[function_param_field];
-  new_function->is_internal = is_internal;
-  /* parse the function body */
+    {
+      if (record->nr_fields < nr_function_fields)
+       error (record->line, "Missing fields from function record\n");
+      filter_parse (&new_function->flags,
+                   record->field[record_filter_flags_field]);
+      filter_parse (&new_function->models,
+                   record->field[record_filter_models_field]);
+      new_function->type = record->field[function_typedef_field];
+      new_function->param = record->field[function_param_field];
+      new_function->name = record->field[function_name_field];
+    }
   record = table_read (file);
+  /* parse any function-model records */
+  while (record != NULL
+        && record_prefix_is (record, '*', nr_function_model_fields))
+    {
+      char *model_name = record->field[function_model_name_field] + 1; /*skip `*' */
+      filter_parse (&new_function->models, model_name);
+      if (!filter_is_subset (model->processors, new_function->models))
+       {
+         error (record->line, "machine model `%s' undefined\n", model_name);
+       }
+      record = table_read (file);
+    }
+  /* parse the function body */
   if (record->type == table_code_entry)
     {
       new_function->code = record;
       record = table_read (file);
     }
   /* insert it */
-  while (*list != NULL)
-    list = &(*list)->next;
-  *list = new_function;
-  if (list_entry != NULL)
-    *list_entry = new_function;
+  if (!filter_is_subset (options.flags_filter, new_function->flags))
+    {
+      if (options.warn.discard)
+       notify (new_function->line, "Discarding function %s - filter flags\n",
+               new_function->name);
+    }
+  else if (new_function->models != NULL
+          && !filter_is_common (options.model_filter, new_function->models))
+    {
+      if (options.warn.discard)
+       notify (new_function->line,
+               "Discarding function %s - filter models\n",
+               new_function->name);
+    }
+  else
+    {
+      while (*list != NULL)
+       list = &(*list)->next;
+      *list = new_function;
+      if (list_entry != NULL)
+       *list_entry = new_function;
+    }
   /* done */
   return record;
 }
@@ -633,24 +818,23 @@ parse_function_record (table *file,
 static void
 parse_insn_model_record (table *file,
                         table_entry *record,
-                        insn_entry *insn,
-                        model_table *model)
+                        insn_entry * insn, model_table *model)
 {
   insn_model_entry **last_insn_model;
   insn_model_entry *new_insn_model = ZALLOC (insn_model_entry);
   /* parse it */
   new_insn_model->line = record->line;
-  if (record->nr_fields > insn_model_name_field)
-    new_insn_model->name = record->field[insn_model_name_field];
   if (record->nr_fields > insn_model_unit_data_field)
     new_insn_model->unit_data = record->field[insn_model_unit_data_field];
   new_insn_model->insn = insn;
-  /* strip "\*[ ]*" from name */
-  new_insn_model->name = skip_spaces (new_insn_model->name + 1);
-  if (strlen (new_insn_model->name) == 0)
+  /* parse the model names, verify that all were defined */
+  new_insn_model->names = NULL;
+  filter_parse (&new_insn_model->names,
+               record->field[insn_model_name_field] + 1 /*skip `*' */ );
+  if (new_insn_model->names == NULL)
     {
-      /* No processor name - a generic model entry, enter it into all
-        the non-empty fields */
+      /* No processor names - a generic model entry, enter it into all
+         the non-empty fields */
       int index;
       for (index = 0; index < model->nr_models; index++)
        if (insn->model[index] == 0)
@@ -662,28 +846,34 @@ parse_insn_model_record (table *file,
     }
   else
     {
-      /* Find the corresponding master model record so it can be
-        linked in correctly */
+      /* Find the corresponding master model record for each name so
+         that they can be linked in. */
       int index;
-      index = filter_is_member (model->processors, new_insn_model->name) - 1;
-      if (index < 0)
+      char *name = "";
+      while (1)
        {
-         error (record->line, "machine model `%s' undefined\n",
-                new_insn_model->name);
+         name = filter_next (new_insn_model->names, name);
+         if (name == NULL)
+           break;
+         index = filter_is_member (model->processors, name) - 1;
+         if (index < 0)
+           {
+             error (new_insn_model->line,
+                    "machine model `%s' undefined\n", name);
+           }
+         /* store it in the corresponding model array entry */
+         if (insn->model[index] != NULL && insn->model[index]->names != NULL)
+           {
+             warning (new_insn_model->line,
+                      "machine model `%s' previously defined\n", name);
+             error (insn->model[index]->line, "earlier definition\n");
+           }
+         insn->model[index] = new_insn_model;
+         /* also add the name to the instructions processor set as an
+            alternative lookup mechanism */
+         filter_parse (&insn->processors, name);
        }
-      /* store it in the corresponding model array entry */
-      insn->model[index] = new_insn_model;
-      /* also add the name to the instructions processor set as an
-        alternative lookup mechanism */
-      filter_parse (&insn->processors, new_insn_model->name);
     }
-#if 0
-  /* for some reason record the max length of any
-     function unit field */
-  int len = strlen (insn_model_ptr->field[insn_model_fields]);
-  if (model->max_model_fields_len < len)
-    model->max_model_fields_len = len;
-#endif
   /* link it in */
   last_insn_model = &insn->models;
   while ((*last_insn_model) != NULL)
@@ -694,17 +884,22 @@ parse_insn_model_record (table *file,
 
 static void
 parse_insn_mnemonic_record (table *file,
-                           table_entry *record,
-                           insn_entry *insn)
+                           table_entry *record, insn_entry * insn)
 {
   insn_mnemonic_entry **last_insn_mnemonic;
   insn_mnemonic_entry *new_insn_mnemonic = ZALLOC (insn_mnemonic_entry);
   /* parse it */
   new_insn_mnemonic->line = record->line;
-  if (record->nr_fields > insn_mnemonic_format_field)
-    new_insn_mnemonic->format = record->field[insn_mnemonic_format_field];
+  ASSERT (record->nr_fields > insn_mnemonic_format_field);
+  new_insn_mnemonic->format = record->field[insn_mnemonic_format_field];
+  ASSERT (new_insn_mnemonic->format[0] == '"');
+  if (new_insn_mnemonic->format[strlen (new_insn_mnemonic->format) - 1] !=
+      '"')
+    error (new_insn_mnemonic->line,
+          "Missing closing double quote in mnemonic field\n");
   if (record->nr_fields > insn_mnemonic_condition_field)
-    new_insn_mnemonic->condition = record->field[insn_mnemonic_condition_field];
+    new_insn_mnemonic->condition =
+      record->field[insn_mnemonic_condition_field];
   new_insn_mnemonic->insn = insn;
   /* insert it */
   last_insn_mnemonic = &insn->mnemonics;
@@ -715,16 +910,42 @@ parse_insn_mnemonic_record (table *file,
 }
 
 
+static table_entry *
+parse_macro_record (table *file, table_entry *record)
+{
+#if 1
+  error (record->line, "Macros are not implemented");
+#else
+  /* parse the define record */
+  if (record->nr_fields < nr_define_fields)
+    error (record->line, "Incorrect nr fields for define record\n");
+  /* process it */
+  if (!is_filtered_out (options.flags_filter,
+                       record->field[record_filter_flags_field])
+      && !is_filtered_out (options.model_filter,
+                          record->field[record_filter_models_field]))
+    {
+      table_define (file,
+                   record->line,
+                   record->field[macro_name_field],
+                   record->field[macro_args_field],
+                   record->field[macro_expr_field]);
+    }
+  record = table_read (file);
+#endif
+  return record;
+}
+
+
 insn_table *
-load_insn_table (char *file_name,
-                cache_entry *cache)
+load_insn_table (char *file_name, cache_entry *cache)
 {
   table *file = table_open (file_name);
   table_entry *record = table_read (file);
 
   insn_table *isa = ZALLOC (insn_table);
   model_table *model = ZALLOC (model_table);
-  
+
   isa->model = model;
   isa->caches = cache;
 
@@ -734,6 +955,12 @@ load_insn_table (char *file_name,
       switch (record_type (record))
        {
 
+       case include_record:
+         {
+           record = parse_include_record (file, record);
+           break;
+         }
+
        case option_record:
          {
            if (isa->insns != NULL)
@@ -741,32 +968,34 @@ load_insn_table (char *file_name,
            record = parse_option_record (file, record);
            break;
          }
-       
+
        case string_function_record:
          {
-           /* convert a string function field into an internal function field */
-           char *name;
-           if (record->nr_fields < nr_function_fields)
-             error (record->line, "Incorrect nr of fields for %s record\n");
-           name = NZALLOC (char,
-                           (strlen ("str_")
-                            + strlen (record->field[function_name_field])
-                            + 1));
-           strcat (name, "str_");
-           strcat (name, record->field[function_name_field]);
-           record->field[record_type_field] = "function";
-           record->field[function_typedef_field] = "const char *";
-           record->field[function_name_field] = name;
-           /* HACK - comes round back as a function/internal record */
+           function_entry *function = NULL;
+           record = parse_function_record (file, record,
+                                           &isa->functions,
+                                           &function, 0 /*is-internal */ ,
+                                           model);
+           /* convert a string function record into an internal function */
+           if (function != NULL)
+             {
+               char *name = NZALLOC (char,
+                                     (strlen ("str_")
+                                      + strlen (function->name) + 1));
+               strcat (name, "str_");
+               strcat (name, function->name);
+               function->name = name;
+               function->type = "const char *";
+             }
            break;
          }
-       
-       case function_record: /* function record */
+
+       case function_record:   /* function record */
          {
            record = parse_function_record (file, record,
                                            &isa->functions,
-                                           NULL,
-                                           0/*is-internal*/);
+                                           NULL, 0 /*is-internal */ ,
+                                           model);
            break;
          }
 
@@ -776,10 +1005,10 @@ load_insn_table (char *file_name,
            function_entry *function = NULL;
            record = parse_function_record (file, record,
                                            &isa->functions,
-                                           &function,
-                                           1/*is-internal*/);
+                                           &function, 1 /*is-internal */ ,
+                                           model);
            /* check what was inserted to see if a pseudo-instruction
-               entry also needs to be created */
+              entry also needs to be created */
            if (function != NULL)
              {
                insn_entry **insn = NULL;
@@ -806,8 +1035,8 @@ load_insn_table (char *file_name,
              }
            break;
          }
-         
-       case scratch_record: /* cache macro records */
+
+       case scratch_record:    /* cache macro records */
        case cache_record:
        case compute_record:
          {
@@ -821,7 +1050,9 @@ load_insn_table (char *file_name,
            new_cache->line = record->line;
            filter_parse (&new_cache->flags,
                          record->field[record_filter_flags_field]);
-           new_cache->type = record->field[cache_type_field];
+           filter_parse (&new_cache->models,
+                         record->field[record_filter_models_field]);
+           new_cache->type = record->field[cache_typedef_field];
            new_cache->name = record->field[cache_name_field];
            filter_parse (&new_cache->original_fields,
                          record->field[cache_original_fields_field]);
@@ -829,7 +1060,16 @@ load_insn_table (char *file_name,
            /* insert it but only if not filtered out */
            if (!filter_is_subset (options.flags_filter, new_cache->flags))
              {
-               notify (new_cache->line, "Discarding cache entry %s\n",
+               notify (new_cache->line,
+                       "Discarding cache entry %s - filter flags\n",
+                       new_cache->name);
+             }
+           else if (is_filtered_out (options.model_filter,
+                                     record->
+                                     field[record_filter_models_field]))
+             {
+               notify (new_cache->line,
+                       "Discarding cache entry %s - filter models\n",
                        new_cache->name);
              }
            else
@@ -844,14 +1084,15 @@ load_insn_table (char *file_name,
            record = table_read (file);
            break;
          }
-       
-       /* model records */
+
+         /* model records */
        case model_processor_record:
          {
            model_entry *new_model;
            /* parse the model */
            if (record->nr_fields < nr_model_processor_fields)
-             error (record->line, "Incorrect nr of fields for model record\n");
+             error (record->line,
+                    "Incorrect nr of fields for model record\n");
            if (isa->insns != NULL)
              error (record->line, "Model appears after first instruction\n");
            new_model = ZALLOC (model_entry);
@@ -864,7 +1105,16 @@ load_insn_table (char *file_name,
            /* only insert it if not filtered out */
            if (!filter_is_subset (options.flags_filter, new_model->flags))
              {
-               notify (new_model->line, "Discarding processor model %s\n",
+               notify (new_model->line,
+                       "Discarding processor model %s - filter flags\n",
+                       new_model->name);
+             }
+           else if (is_filtered_out (options.model_filter,
+                                     record->
+                                     field[record_filter_models_field]))
+             {
+               notify (new_model->line,
+                       "Discarding processor model %s - filter models\n",
                        new_model->name);
              }
            else if (filter_is_member (model->processors, new_model->name))
@@ -880,67 +1130,69 @@ load_insn_table (char *file_name,
                  last = &(*last)->next;
                *last = new_model;
                /* count it */
-               model->nr_models ++;
+               model->nr_models++;
                filter_parse (&model->processors, new_model->name);
              }
            /* advance things */
            record = table_read (file);
          }
          break;
-         
+
        case model_macro_record:
          record = parse_model_data_record (isa, file, record,
                                            nr_model_macro_fields,
                                            &model->macros);
          break;
-         
+
        case model_data_record:
          record = parse_model_data_record (isa, file, record,
                                            nr_model_data_fields,
                                            &model->data);
          break;
-         
+
        case model_static_record:
          record = parse_function_record (file, record,
                                          &model->statics,
-                                         NULL,
-                                         0/*is internal*/);
+                                         NULL, 0 /*is internal */ ,
+                                         model);
          break;
-         
+
        case model_internal_record:
          record = parse_function_record (file, record,
                                          &model->internals,
-                                         NULL,
-                                         1/*is internal*/);
+                                         NULL, 1 /*is internal */ ,
+                                         model);
          break;
-         
+
        case model_function_record:
          record = parse_function_record (file, record,
                                          &model->functions,
-                                         NULL,
-                                         0/*is internal*/);
+                                         NULL, 0 /*is internal */ ,
+                                         model);
          break;
-         
-       case insn_record: /* instruction records */
+
+       case insn_record:       /* instruction records */
          {
            insn_entry *new_insn;
            char *format;
            /* parse the instruction */
            if (record->nr_fields < nr_insn_fields)
-             error (record->line, "Incorrect nr of fields for insn record\n");
+             error (record->line,
+                    "Incorrect nr of fields for insn record\n");
            new_insn = ZALLOC (insn_entry);
            new_insn->line = record->line;
            filter_parse (&new_insn->flags,
                          record->field[record_filter_flags_field]);
            /* save the format field.  Can't parse it until after the
-               filter-out checks.  Could be filtered out because the
-               format is invalid */
+              filter-out checks.  Could be filtered out because the
+              format is invalid */
            format = record->field[insn_word_field];
            new_insn->format_name = record->field[insn_format_name_field];
            if (options.format_name_filter != NULL
                && !filter_is_member (options.format_name_filter,
                                      new_insn->format_name))
-             error (new_insn->line, "Unreconized instruction format name `%s'\n",
+             error (new_insn->line,
+                    "Unreconized instruction format name `%s'\n",
                     new_insn->format_name);
            filter_parse (&new_insn->options,
                          record->field[insn_options_field]);
@@ -948,12 +1200,14 @@ load_insn_table (char *file_name,
            record = table_read (file);
            /* Parse any model/assember records */
            new_insn->nr_models = model->nr_models;
-           new_insn->model = NZALLOC (insn_model_entry*, model->nr_models + 1);
+           new_insn->model =
+             NZALLOC (insn_model_entry *, model->nr_models + 1);
            while (record != NULL)
              {
                if (record_prefix_is (record, '*', nr_insn_model_fields))
                  parse_insn_model_record (file, record, new_insn, model);
-               else if (record_prefix_is (record, '"', nr_insn_mnemonic_fields))
+               else
+                 if (record_prefix_is (record, '"', nr_insn_mnemonic_fields))
                  parse_insn_mnemonic_record (file, record, new_insn);
                else
                  break;
@@ -966,6 +1220,8 @@ load_insn_table (char *file_name,
                new_insn->code = record;
                record = table_read (file);
              }
+           else if (options.warn.unimplemented)
+             notify (new_insn->line, "unimplemented\n");
            /* insert it */
            if (!filter_is_subset (options.flags_filter, new_insn->flags))
              {
@@ -980,8 +1236,8 @@ load_insn_table (char *file_name,
                                           new_insn->processors))
              {
                /* only discard an instruction based in the processor
-                   model when both the instruction and the options are
-                   nonempty */
+                  model when both the instruction and the options are
+                  nonempty */
                if (options.warn.discard)
                  notify (new_insn->line,
                          "Discarding instruction %s (processor-model)\n",
@@ -998,7 +1254,7 @@ load_insn_table (char *file_name,
                  last = &(*last)->next;
                *last = new_insn;
                /* update global isa counters */
-               isa->nr_insns ++;
+               isa->nr_insns++;
                if (isa->max_nr_words < new_insn->nr_words)
                  isa->max_nr_words = new_insn->nr_words;
                filter_add (&isa->flags, new_insn->flags);
@@ -1006,9 +1262,16 @@ load_insn_table (char *file_name,
              }
            break;
          }
-      
-       default:
-         error (record->line, "Unknown entry\n");
+
+       case define_record:
+         record = parse_macro_record (file, record);
+         break;
+
+       case unknown_record:
+       case code_record:
+         error (record->line, "Unknown or unexpected entry\n");
+
+
        }
     }
   return isa;
@@ -1016,8 +1279,7 @@ load_insn_table (char *file_name,
 
 
 void
-print_insn_words (lf *file,
-                 insn_entry *insn)
+print_insn_words (lf *file, insn_entry * insn)
 {
   insn_word_entry *word = insn->words;
   if (word != NULL)
@@ -1027,12 +1289,18 @@ print_insn_words (lf *file,
          insn_field_entry *field = word->first;
          while (1)
            {
+             insn_field_cond *cond;
+
              if (options.insn_specifying_widths)
                lf_printf (file, "%d.", field->width);
              else
-               lf_printf (file, "%d.", i2target (options.hi_bit_nr, field->first));
+               lf_printf (file, "%d.",
+                          i2target (options.hi_bit_nr, field->first));
              switch (field->type)
                {
+               case insn_field_invalid:
+                 ASSERT (0);
+                 break;
                case insn_field_int:
                  lf_printf (file, "0x%lx", (long) field->val_int);
                  break;
@@ -1044,6 +1312,34 @@ print_insn_words (lf *file,
                  break;
                case insn_field_string:
                  lf_printf (file, "%s", field->val_string);
+
+                 if (field->conditions == NULL)
+                   break;
+
+                 if (field->conditions->test == insn_field_cond_eq)
+                   {
+                     if (field->conditions->type == insn_field_cond_value)
+                       lf_printf (file, "=%ld",
+                                  (long) field->conditions->value);
+                     else
+                       lf_printf (file, "=%s", field->conditions->string);
+
+                     /* There can be only one equality condition.  */
+                     ASSERT (field->conditions->next == NULL);
+                     break;
+                   }
+
+                 for (cond = field->conditions;
+                      cond != NULL;
+                      cond = cond->next)
+                   {
+                     ASSERT (cond->test == insn_field_cond_ne);
+
+                     if (cond->type == insn_field_cond_value)
+                       lf_printf (file, "!%ld", (long) cond->value);
+                     else
+                       lf_printf (file, "!%s", cond->string);
+                   }
                  break;
                }
              if (field == word->last)
@@ -1058,14 +1354,13 @@ print_insn_words (lf *file,
        }
     }
 }
+\f
 
 
-\f
 void
 function_entry_traverse (lf *file,
-                        function_entry *functions,
-                        function_entry_handler *handler,
-                        void *data)
+                        function_entry * functions,
+                        function_entry_handler * handler, void *data)
 {
   function_entry *function;
   for (function = functions; function != NULL; function = function->next)
@@ -1077,8 +1372,7 @@ function_entry_traverse (lf *file,
 void
 insn_table_traverse_insn (lf *file,
                          insn_table *isa,
-                         insn_entry_handler *handler,
-                         void *data)
+                         insn_entry_handler * handler, void *data)
 {
   insn_entry *insn;
   for (insn = isa->insns; insn != NULL; insn = insn->next)
@@ -1086,13 +1380,11 @@ insn_table_traverse_insn (lf *file,
       handler (file, isa, insn, data);
     }
 }
-
 \f
+
 static void
 dump_function_entry (lf *file,
-                    char *prefix,
-                    function_entry *entry,
-                    char *suffix)
+                    char *prefix, function_entry * entry, char *suffix)
 {
   lf_printf (file, "%s(function_entry *) 0x%lx", prefix, (long) entry);
   if (entry != NULL)
@@ -1111,9 +1403,7 @@ dump_function_entry (lf *file,
 
 static void
 dump_function_entries (lf *file,
-                      char *prefix,
-                      function_entry *entry,
-                      char *suffix)
+                      char *prefix, function_entry * entry, char *suffix)
 {
   lf_printf (file, "%s", prefix);
   lf_indent (file, +1);
@@ -1131,26 +1421,27 @@ cache_entry_type_to_str (cache_entry_type type)
 {
   switch (type)
     {
-    case scratch_value: return "scratch";
-    case cache_value: return "cache";
-    case compute_value: return "compute";
+    case scratch_value:
+      return "scratch";
+    case cache_value:
+      return "cache";
+    case compute_value:
+      return "compute";
     }
   ERROR ("Bad switch");
   return 0;
 }
 
 static void
-dump_cache_entry (lf *file,
-                 char *prefix,
-                 cache_entry *entry,
-                 char *suffix)
+dump_cache_entry (lf *file, char *prefix, cache_entry *entry, char *suffix)
 {
   lf_printf (file, "%s(cache_entry *) 0x%lx", prefix, (long) entry);
   if (entry != NULL)
     {
       dump_line_ref (file, "\n(line ", entry->line, ")");
       dump_filter (file, "\n(flags ", entry->flags, ")");
-      lf_printf (file, "\n(entry_type \"%s\")", cache_entry_type_to_str (entry->entry_type));
+      lf_printf (file, "\n(entry_type \"%s\")",
+                cache_entry_type_to_str (entry->entry_type));
       lf_printf (file, "\n(name \"%s\")", entry->name);
       dump_filter (file, "\n(original_fields ", entry->original_fields, ")");
       lf_printf (file, "\n(type \"%s\")", entry->type);
@@ -1161,10 +1452,7 @@ dump_cache_entry (lf *file,
 }
 
 void
-dump_cache_entries (lf *file,
-                   char *prefix,
-                   cache_entry *entry,
-                   char *suffix)
+dump_cache_entries (lf *file, char *prefix, cache_entry *entry, char *suffix)
 {
   lf_printf (file, "%s", prefix);
   lf_indent (file, +1);
@@ -1178,10 +1466,7 @@ dump_cache_entries (lf *file,
 }
 
 static void
-dump_model_data (lf *file,
-                char *prefix,
-                model_data *entry,
-                char *suffix)
+dump_model_data (lf *file, char *prefix, model_data *entry, char *suffix)
 {
   lf_printf (file, "%s(model_data *) 0x%lx", prefix, (long) entry);
   if (entry != NULL)
@@ -1198,10 +1483,7 @@ dump_model_data (lf *file,
 }
 
 static void
-dump_model_datas (lf *file,
-                 char *prefix,
-                 model_data *entry,
-                 char *suffix)
+dump_model_datas (lf *file, char *prefix, model_data *entry, char *suffix)
 {
   lf_printf (file, "%s", prefix);
   lf_indent (file, +1);
@@ -1215,10 +1497,7 @@ dump_model_datas (lf *file,
 }
 
 static void
-dump_model_entry (lf *file,
-                 char *prefix,
-                 model_entry *entry,
-                 char *suffix)
+dump_model_entry (lf *file, char *prefix, model_entry *entry, char *suffix)
 {
   lf_printf (file, "%s(model_entry *) 0x%lx", prefix, (long) entry);
   if (entry != NULL)
@@ -1236,10 +1515,7 @@ dump_model_entry (lf *file,
 }
 
 static void
-dump_model_entries (lf *file,
-                   char *prefix,
-                   model_entry *entry,
-                   char *suffix)
+dump_model_entries (lf *file, char *prefix, model_entry *entry, char *suffix)
 {
   lf_printf (file, "%s", prefix);
   lf_indent (file, +1);
@@ -1254,10 +1530,7 @@ dump_model_entries (lf *file,
 
 
 static void
-dump_model_table (lf *file,
-                 char *prefix,
-                 model_table *entry,
-                 char *suffix)
+dump_model_table (lf *file, char *prefix, model_table *entry, char *suffix)
 {
   lf_printf (file, "%s(model_table *) 0x%lx", prefix, (long) entry);
   if (entry != NULL)
@@ -1282,10 +1555,17 @@ insn_field_type_to_str (insn_field_type type)
 {
   switch (type)
     {
-    case insn_field_int: return "int";
-    case insn_field_reserved: return "reserved";
-    case insn_field_wild: return "wild";
-    case insn_field_string: return "string";
+    case insn_field_invalid:
+      ASSERT (0);
+      return "(invalid)";
+    case insn_field_int:
+      return "int";
+    case insn_field_reserved:
+      return "reserved";
+    case insn_field_wild:
+      return "wild";
+    case insn_field_string:
+      return "string";
     }
   ERROR ("bad switch");
   return 0;
@@ -1293,9 +1573,7 @@ insn_field_type_to_str (insn_field_type type)
 
 void
 dump_insn_field (lf *file,
-                char *prefix,
-                insn_field_entry *field,
-                char *suffix)
+                char *prefix, insn_field_entry *field, char *suffix)
 {
   char *sep = " ";
   lf_printf (file, "%s(insn_field_entry *) 0x%lx", prefix, (long) field);
@@ -1305,9 +1583,13 @@ dump_insn_field (lf *file,
       lf_printf (file, "%s(first %d)", sep, field->first);
       lf_printf (file, "%s(last %d)", sep, field->last);
       lf_printf (file, "%s(width %d)", sep, field->width);
-      lf_printf (file, "%s(type %s)", sep, insn_field_type_to_str (field->type));
+      lf_printf (file, "%s(type %s)", sep,
+                insn_field_type_to_str (field->type));
       switch (field->type)
        {
+       case insn_field_invalid:
+         ASSERT (0);
+         break;
        case insn_field_int:
          lf_printf (file, "%s(val 0x%lx)", sep, (long) field->val_int);
          break;
@@ -1330,9 +1612,7 @@ dump_insn_field (lf *file,
 
 void
 dump_insn_word_entry (lf *file,
-                     char *prefix,
-                     insn_word_entry *word,
-                     char *suffix)
+                     char *prefix, insn_word_entry *word, char *suffix)
 {
   lf_printf (file, "%s(insn_word_entry *) 0x%lx", prefix, (long) word);
   if (word != NULL)
@@ -1345,7 +1625,8 @@ dump_insn_word_entry (lf *file,
       lf_printf (file, "\n(bit");
       for (i = 0; i < options.insn_bit_size; i++)
        lf_printf (file, "\n ((value %d) (mask %d) (field 0x%lx))",
-                  word->bit[i]->value, word->bit[i]->mask, (long) word->bit[i]->field);
+                  word->bit[i]->value, word->bit[i]->mask,
+                  (long) word->bit[i]->field);
       lf_printf (file, ")");
       for (field = word->first; field != NULL; field = field->next)
        dump_insn_field (file, "\n(", field, ")");
@@ -1358,9 +1639,7 @@ dump_insn_word_entry (lf *file,
 
 static void
 dump_insn_word_entries (lf *file,
-                       char *prefix,
-                       insn_word_entry *word,
-                       char *suffix)
+                       char *prefix, insn_word_entry *word, char *suffix)
 {
   lf_printf (file, "%s", prefix);
   while (word != NULL)
@@ -1373,16 +1652,14 @@ dump_insn_word_entries (lf *file,
 
 static void
 dump_insn_model_entry (lf *file,
-                      char *prefix,
-                      insn_model_entry *model,
-                      char *suffix)
+                      char *prefix, insn_model_entry *model, char *suffix)
 {
   lf_printf (file, "%s(insn_model_entry *) 0x%lx", prefix, (long) model);
   if (model != NULL)
     {
       lf_indent (file, +1);
       dump_line_ref (file, "\n(line ", model->line, ")");
-      lf_printf (file, "\n(name \"%s\")", model->name);
+      dump_filter (file, "\n(names ", model->names, ")");
       lf_printf (file, "\n(full_name \"%s\")", model->full_name);
       lf_printf (file, "\n(unit_data \"%s\")", model->unit_data);
       lf_printf (file, "\n(insn (insn_entry *) 0x%lx)", (long) model->insn);
@@ -1395,9 +1672,7 @@ dump_insn_model_entry (lf *file,
 
 static void
 dump_insn_model_entries (lf *file,
-                        char *prefix,
-                        insn_model_entry *model,
-                        char *suffix)
+                        char *prefix, insn_model_entry *model, char *suffix)
 {
   lf_printf (file, "%s", prefix);
   while (model != NULL)
@@ -1412,10 +1687,10 @@ dump_insn_model_entries (lf *file,
 static void
 dump_insn_mnemonic_entry (lf *file,
                          char *prefix,
-                         insn_mnemonic_entry *mnemonic,
-                         char *suffix)
+                         insn_mnemonic_entry *mnemonic, char *suffix)
 {
-  lf_printf (file, "%s(insn_mnemonic_entry *) 0x%lx", prefix, (long) mnemonic);
+  lf_printf (file, "%s(insn_mnemonic_entry *) 0x%lx", prefix,
+            (long) mnemonic);
   if (mnemonic != NULL)
     {
       lf_indent (file, +1);
@@ -1434,8 +1709,7 @@ dump_insn_mnemonic_entry (lf *file,
 static void
 dump_insn_mnemonic_entries (lf *file,
                            char *prefix,
-                           insn_mnemonic_entry *mnemonic,
-                           char *suffix)
+                           insn_mnemonic_entry *mnemonic, char *suffix)
 {
   lf_printf (file, "%s", prefix);
   while (mnemonic != NULL)
@@ -1447,10 +1721,7 @@ dump_insn_mnemonic_entries (lf *file,
 }
 
 void
-dump_insn_entry (lf *file,
-                char *prefix,
-                insn_entry *entry,
-                char *suffix)
+dump_insn_entry (lf *file, char *prefix, insn_entry * entry, char *suffix)
 {
   lf_printf (file, "%s(insn_entry *) 0x%lx", prefix, (long) entry);
   if (entry != NULL)
@@ -1476,19 +1747,17 @@ dump_insn_entry (lf *file,
        lf_printf (file, " 0x%lx", (long) entry->model[i]);
       lf_printf (file, ")");
       dump_filter (file, "\n(processors ", entry->processors, ")");
-      dump_insn_mnemonic_entries (file, "\n(mnemonics ", entry->mnemonics, ")");
+      dump_insn_mnemonic_entries (file, "\n(mnemonics ", entry->mnemonics,
+                                 ")");
       dump_table_entry (file, "\n(code ", entry->code, ")");
       lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
       lf_indent (file, -1);
-  }
+    }
   lf_printf (file, "%s", suffix);
 }
 
 static void
-dump_insn_entries (lf *file,
-                  char *prefix,
-                  insn_entry *entry,
-                  char *suffix)
+dump_insn_entries (lf *file, char *prefix, insn_entry * entry, char *suffix)
 {
   lf_printf (file, "%s", prefix);
   lf_indent (file, +1);
@@ -1504,10 +1773,7 @@ dump_insn_entries (lf *file,
 
 
 void
-dump_insn_table (lf *file,
-                char *prefix,
-                insn_table *isa,
-                char *suffix)
+dump_insn_table (lf *file, char *prefix, insn_table *isa, char *suffix)
 {
   lf_printf (file, "%s(insn_table *) 0x%lx", prefix, (long) isa);
   if (isa != NULL)