OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [sim/] [igen/] [ld-insn.c] - Diff between revs 827 and 840

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 827 Rev 840
/* The IGEN simulator generator for GDB, the GNU Debugger.
/* The IGEN simulator generator for GDB, the GNU Debugger.
 
 
   Copyright 2002, 2007, 2008 Free Software Foundation, Inc.
   Copyright 2002, 2007, 2008 Free Software Foundation, Inc.
 
 
   Contributed by Andrew Cagney.
   Contributed by Andrew Cagney.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 
 
#include "misc.h"
#include "misc.h"
#include "lf.h"
#include "lf.h"
#include "table.h"
#include "table.h"
#include "filter.h"
#include "filter.h"
#include "igen.h"
#include "igen.h"
#include "ld-insn.h"
#include "ld-insn.h"
 
 
static insn_word_entry *
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;
  char *chp;
  insn_word_entry *word = ZALLOC (insn_word_entry);
  insn_word_entry *word = ZALLOC (insn_word_entry);
 
 
  /* create a leading sentinal */
  /* create a leading sentinal */
  word->first = ZALLOC (insn_field_entry);
  word->first = ZALLOC (insn_field_entry);
  word->first->first = -1;
  word->first->first = -1;
  word->first->last = -1;
  word->first->last = -1;
  word->first->width = 0;
  word->first->width = 0;
 
 
  /* and a trailing sentinal */
  /* and a trailing sentinal */
  word->last = ZALLOC (insn_field_entry);
  word->last = ZALLOC (insn_field_entry);
  word->last->first = options.insn_bit_size;
  word->last->first = options.insn_bit_size;
  word->last->last = options.insn_bit_size;
  word->last->last = options.insn_bit_size;
  word->last->width = 0;
  word->last->width = 0;
 
 
  /* link them together */
  /* link them together */
  word->first->next = word->last;
  word->first->next = word->last;
  word->last->prev = word->first;
  word->last->prev = word->first;
 
 
  /* now work through the formats */
  /* now work through the formats */
  chp = skip_spaces (string);
  chp = skip_spaces (string);
 
 
  while (*chp != '\0')
  while (*chp != '\0')
    {
    {
      char *start_pos;
      char *start_pos;
      int strlen_pos;
      int strlen_pos;
      char *start_val;
      char *start_val;
      int strlen_val;
      int strlen_val;
      insn_field_entry *new_field;
      insn_field_entry *new_field;
 
 
      /* create / link in the new field */
      /* create / link in the new field */
      new_field = ZALLOC (insn_field_entry);
      new_field = ZALLOC (insn_field_entry);
      new_field->next = word->last;
      new_field->next = word->last;
      new_field->prev = word->last->prev;
      new_field->prev = word->last->prev;
      new_field->next->prev = new_field;
      new_field->next->prev = new_field;
      new_field->prev->next = new_field;
      new_field->prev->next = new_field;
      new_field->word_nr = word_nr;
      new_field->word_nr = word_nr;
 
 
      /* break out the first field (if present) */
      /* break out the first field (if present) */
      start_pos = chp;
      start_pos = chp;
      chp = skip_to_separator (chp, ".,!");
      chp = skip_to_separator (chp, ".,!");
      strlen_pos = back_spaces (start_pos, chp) - start_pos;
      strlen_pos = back_spaces (start_pos, chp) - start_pos;
 
 
      /* break out the second field (if present) */
      /* break out the second field (if present) */
      if (*chp != '.')
      if (*chp != '.')
        {
        {
          /* assume what was specified was the value (and not the start
          /* assume what was specified was the value (and not the start
             position).  Assume the value length implicitly specifies
             position).  Assume the value length implicitly specifies
             the number of bits */
             the number of bits */
          start_val = start_pos;
          start_val = start_pos;
          strlen_val = strlen_pos;
          strlen_val = strlen_pos;
          start_pos = "";
          start_pos = "";
          strlen_pos = 0;
          strlen_pos = 0;
        }
        }
      else
      else
        {
        {
          chp++;                /* skip `.' */
          chp++;                /* skip `.' */
          chp = skip_spaces (chp);
          chp = skip_spaces (chp);
          start_val = chp;
          start_val = chp;
          if (*chp == '/' || *chp == '*')
          if (*chp == '/' || *chp == '*')
            {
            {
              do
              do
                {
                {
                  chp++;
                  chp++;
                }
                }
              while (*chp == '/' || *chp == '*');
              while (*chp == '/' || *chp == '*');
            }
            }
          else if (isalpha (*start_val))
          else if (isalpha (*start_val))
            {
            {
              do
              do
                {
                {
                  chp++;
                  chp++;
                }
                }
              while (isalnum (*chp) || *chp == '_');
              while (isalnum (*chp) || *chp == '_');
            }
            }
          else if (isdigit (*start_val))
          else if (isdigit (*start_val))
            {
            {
              do
              do
                {
                {
                  chp++;
                  chp++;
                }
                }
              while (isalnum (*chp));
              while (isalnum (*chp));
            }
            }
          strlen_val = chp - start_val;
          strlen_val = chp - start_val;
          chp = skip_spaces (chp);
          chp = skip_spaces (chp);
        }
        }
      if (strlen_val == 0)
      if (strlen_val == 0)
        error (line, "Empty value field\n");
        error (line, "Empty value field\n");
 
 
      /* break out any conditional fields - { [ "!" | "=" [ <value> | <field-name> } */
      /* break out any conditional fields - { [ "!" | "=" [ <value> | <field-name> } */
      while (*chp == '!' || *chp == '=')
      while (*chp == '!' || *chp == '=')
        {
        {
          char *start;
          char *start;
          char *end;
          char *end;
          int len;
          int len;
          insn_field_cond *new_cond = ZALLOC (insn_field_cond);
          insn_field_cond *new_cond = ZALLOC (insn_field_cond);
 
 
          /* determine the conditional test */
          /* determine the conditional test */
          switch (*chp)
          switch (*chp)
            {
            {
            case '=':
            case '=':
              new_cond->test = insn_field_cond_eq;
              new_cond->test = insn_field_cond_eq;
              break;
              break;
            case '!':
            case '!':
              new_cond->test = insn_field_cond_ne;
              new_cond->test = insn_field_cond_ne;
              break;
              break;
            default:
            default:
              ASSERT (0);
              ASSERT (0);
            }
            }
 
 
          /* save the value */
          /* save the value */
          chp++;
          chp++;
          chp = skip_spaces (chp);
          chp = skip_spaces (chp);
          start = chp;
          start = chp;
          chp = skip_to_separator (chp, "+,:!=");
          chp = skip_to_separator (chp, "+,:!=");
          end = back_spaces (start, chp);
          end = back_spaces (start, chp);
          len = end - start;
          len = end - start;
          if (len == 0)
          if (len == 0)
            error (line, "Missing or invalid conditional value\n");
            error (line, "Missing or invalid conditional value\n");
          new_cond->string = NZALLOC (char, len + 1);
          new_cond->string = NZALLOC (char, len + 1);
          strncpy (new_cond->string, start, len);
          strncpy (new_cond->string, start, len);
 
 
          /* determine the conditional type */
          /* determine the conditional type */
          if (isdigit (*start))
          if (isdigit (*start))
            {
            {
              /* [ "!" | "=" ] <value> */
              /* [ "!" | "=" ] <value> */
              new_cond->type = insn_field_cond_value;
              new_cond->type = insn_field_cond_value;
              new_cond->value = a2i (new_cond->string);
              new_cond->value = a2i (new_cond->string);
            }
            }
          else
          else
            {
            {
              /* [ "!" | "=" ] <field>  - check field valid */
              /* [ "!" | "=" ] <field>  - check field valid */
              new_cond->type = insn_field_cond_field;
              new_cond->type = insn_field_cond_field;
              /* new_cond->field is determined in later */
              /* new_cond->field is determined in later */
            }
            }
 
 
          /* Only a single `=' is permitted. */
          /* Only a single `=' is permitted. */
          if ((new_cond->test == insn_field_cond_eq
          if ((new_cond->test == insn_field_cond_eq
               && new_field->conditions != NULL)
               && new_field->conditions != NULL)
              || (new_field->conditions != NULL
              || (new_field->conditions != NULL
                  && new_field->conditions->test == insn_field_cond_eq))
                  && new_field->conditions->test == insn_field_cond_eq))
            error (line, "Only single conditional when `=' allowed\n");
            error (line, "Only single conditional when `=' allowed\n");
 
 
          /* insert it */
          /* insert it */
          {
          {
            insn_field_cond **last = &new_field->conditions;
            insn_field_cond **last = &new_field->conditions;
            while (*last != NULL)
            while (*last != NULL)
              last = &(*last)->next;
              last = &(*last)->next;
            *last = new_cond;
            *last = new_cond;
          }
          }
        }
        }
 
 
      /* NOW verify that the field was finished */
      /* NOW verify that the field was finished */
      if (*chp == ',')
      if (*chp == ',')
        {
        {
          chp = skip_spaces (chp + 1);
          chp = skip_spaces (chp + 1);
          if (*chp == '\0')
          if (*chp == '\0')
            error (line, "empty field\n");
            error (line, "empty field\n");
        }
        }
      else if (*chp != '\0')
      else if (*chp != '\0')
        {
        {
          error (line, "Missing field separator\n");
          error (line, "Missing field separator\n");
        }
        }
 
 
      /* copy the value */
      /* copy the value */
      new_field->val_string = NZALLOC (char, strlen_val + 1);
      new_field->val_string = NZALLOC (char, strlen_val + 1);
      strncpy (new_field->val_string, start_val, strlen_val);
      strncpy (new_field->val_string, start_val, strlen_val);
      if (isdigit (new_field->val_string[0]))
      if (isdigit (new_field->val_string[0]))
        {
        {
          if (strlen_pos == 0)
          if (strlen_pos == 0)
            {
            {
              /* when the length/pos field is omited, an integer field
              /* when the length/pos field is omited, an integer field
                 is always binary */
                 is always binary */
              unsigned64 val = 0;
              unsigned64 val = 0;
              int i;
              int i;
              for (i = 0; i < strlen_val; i++)
              for (i = 0; i < strlen_val; i++)
                {
                {
                  if (new_field->val_string[i] != '0'
                  if (new_field->val_string[i] != '0'
                      && new_field->val_string[i] != '1')
                      && new_field->val_string[i] != '1')
                    error (line, "invalid binary field %s\n",
                    error (line, "invalid binary field %s\n",
                           new_field->val_string);
                           new_field->val_string);
                  val = (val << 1) + (new_field->val_string[i] == '1');
                  val = (val << 1) + (new_field->val_string[i] == '1');
                }
                }
              new_field->val_int = val;
              new_field->val_int = val;
              new_field->type = insn_field_int;
              new_field->type = insn_field_int;
            }
            }
          else
          else
            {
            {
              new_field->val_int = a2i (new_field->val_string);
              new_field->val_int = a2i (new_field->val_string);
              new_field->type = insn_field_int;
              new_field->type = insn_field_int;
            }
            }
        }
        }
      else if (new_field->val_string[0] == '/')
      else if (new_field->val_string[0] == '/')
        {
        {
          new_field->type = insn_field_reserved;
          new_field->type = insn_field_reserved;
        }
        }
      else if (new_field->val_string[0] == '*')
      else if (new_field->val_string[0] == '*')
        {
        {
          new_field->type = insn_field_wild;
          new_field->type = insn_field_wild;
        }
        }
      else
      else
        {
        {
          new_field->type = insn_field_string;
          new_field->type = insn_field_string;
          if (filter_is_member (word->field_names, new_field->val_string))
          if (filter_is_member (word->field_names, new_field->val_string))
            error (line, "Field name %s is duplicated\n",
            error (line, "Field name %s is duplicated\n",
                   new_field->val_string);
                   new_field->val_string);
          filter_parse (&word->field_names, new_field->val_string);
          filter_parse (&word->field_names, new_field->val_string);
        }
        }
      if (new_field->type != insn_field_string
      if (new_field->type != insn_field_string
          && new_field->conditions != NULL)
          && new_field->conditions != NULL)
        error (line, "Conditionals can only be applied to named fields\n");
        error (line, "Conditionals can only be applied to named fields\n");
 
 
      /* the copy the position */
      /* the copy the position */
      new_field->pos_string = NZALLOC (char, strlen_pos + 1);
      new_field->pos_string = NZALLOC (char, strlen_pos + 1);
      strncpy (new_field->pos_string, start_pos, strlen_pos);
      strncpy (new_field->pos_string, start_pos, strlen_pos);
      if (strlen_pos == 0)
      if (strlen_pos == 0)
        {
        {
          new_field->first = new_field->prev->last + 1;
          new_field->first = new_field->prev->last + 1;
          if (new_field->first == 0      /* first field */
          if (new_field->first == 0      /* first field */
              && *chp == '\0'   /* no further fields */
              && *chp == '\0'   /* no further fields */
              && new_field->type == insn_field_string)
              && new_field->type == insn_field_string)
            {
            {
              /* A single string without any position, assume that it
              /* A single string without any position, assume that it
                 represents the entire instruction word */
                 represents the entire instruction word */
              new_field->width = options.insn_bit_size;
              new_field->width = options.insn_bit_size;
            }
            }
          else
          else
            {
            {
              /* No explicit width/position, assume value implicitly
              /* No explicit width/position, assume value implicitly
                 supplies the width */
                 supplies the width */
              new_field->width = strlen_val;
              new_field->width = strlen_val;
            }
            }
          new_field->last = new_field->first + new_field->width - 1;
          new_field->last = new_field->first + new_field->width - 1;
          if (new_field->last >= options.insn_bit_size)
          if (new_field->last >= options.insn_bit_size)
            error (line, "Bit position %d exceed instruction bit size (%d)\n",
            error (line, "Bit position %d exceed instruction bit size (%d)\n",
                   new_field->last, options.insn_bit_size);
                   new_field->last, options.insn_bit_size);
        }
        }
      else if (options.insn_specifying_widths)
      else if (options.insn_specifying_widths)
        {
        {
          new_field->first = new_field->prev->last + 1;
          new_field->first = new_field->prev->last + 1;
          new_field->width = a2i (new_field->pos_string);
          new_field->width = a2i (new_field->pos_string);
          new_field->last = new_field->first + new_field->width - 1;
          new_field->last = new_field->first + new_field->width - 1;
          if (new_field->last >= options.insn_bit_size)
          if (new_field->last >= options.insn_bit_size)
            error (line, "Bit position %d exceed instruction bit size (%d)\n",
            error (line, "Bit position %d exceed instruction bit size (%d)\n",
                   new_field->last, options.insn_bit_size);
                   new_field->last, options.insn_bit_size);
        }
        }
      else
      else
        {
        {
          new_field->first = target_a2i (options.hi_bit_nr,
          new_field->first = target_a2i (options.hi_bit_nr,
                                         new_field->pos_string);
                                         new_field->pos_string);
          new_field->last = new_field->next->first - 1; /* guess */
          new_field->last = new_field->next->first - 1; /* guess */
          new_field->width = new_field->last - new_field->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->last = new_field->first - 1; /*fix */
          new_field->prev->width = new_field->first - new_field->prev->first;   /*fix */
          new_field->prev->width = new_field->first - new_field->prev->first;   /*fix */
        }
        }
    }
    }
 
 
  /* fiddle first/last so that the sentinals disapear */
  /* fiddle first/last so that the sentinals disapear */
  ASSERT (word->first->last < 0);
  ASSERT (word->first->last < 0);
  ASSERT (word->last->first >= options.insn_bit_size);
  ASSERT (word->last->first >= options.insn_bit_size);
  word->first = word->first->next;
  word->first = word->first->next;
  word->last = word->last->prev;
  word->last = word->last->prev;
 
 
  /* check that the last field goes all the way to the last bit */
  /* check that the last field goes all the way to the last bit */
  if (word->last->last != options.insn_bit_size - 1)
  if (word->last->last != options.insn_bit_size - 1)
    {
    {
      if (options.warn.width)
      if (options.warn.width)
        options.warning (line, "Instruction format is not %d bits wide\n",
        options.warning (line, "Instruction format is not %d bits wide\n",
                         options.insn_bit_size);
                         options.insn_bit_size);
      word->last->last = options.insn_bit_size - 1;
      word->last->last = options.insn_bit_size - 1;
    }
    }
 
 
  /* now go over this again, pointing each bit position at a field
  /* now go over this again, pointing each bit position at a field
     record */
     record */
  {
  {
    insn_field_entry *field;
    insn_field_entry *field;
    for (field = word->first;
    for (field = word->first;
         field->last < options.insn_bit_size; field = field->next)
         field->last < options.insn_bit_size; field = field->next)
      {
      {
        int i;
        int i;
        for (i = field->first; i <= field->last; i++)
        for (i = field->first; i <= field->last; i++)
          {
          {
            word->bit[i] = ZALLOC (insn_bit_entry);
            word->bit[i] = ZALLOC (insn_bit_entry);
            word->bit[i]->field = field;
            word->bit[i]->field = field;
            switch (field->type)
            switch (field->type)
              {
              {
              case insn_field_invalid:
              case insn_field_invalid:
                ASSERT (0);
                ASSERT (0);
                break;
                break;
              case insn_field_int:
              case insn_field_int:
                word->bit[i]->mask = 1;
                word->bit[i]->mask = 1;
                word->bit[i]->value = ((field->val_int
                word->bit[i]->value = ((field->val_int
                                        & ((insn_uint) 1 <<
                                        & ((insn_uint) 1 <<
                                           (field->last - i))) != 0);
                                           (field->last - i))) != 0);
              case insn_field_reserved:
              case insn_field_reserved:
              case insn_field_wild:
              case insn_field_wild:
              case insn_field_string:
              case insn_field_string:
                /* if we encounter a constant conditional, encode
                /* if we encounter a constant conditional, encode
                   their bit value. */
                   their bit value. */
                if (field->conditions != NULL
                if (field->conditions != NULL
                    && field->conditions->test == insn_field_cond_eq
                    && field->conditions->test == insn_field_cond_eq
                    && field->conditions->type == insn_field_cond_value)
                    && field->conditions->type == insn_field_cond_value)
                  {
                  {
                    word->bit[i]->mask = 1;
                    word->bit[i]->mask = 1;
                    word->bit[i]->value = ((field->conditions->value
                    word->bit[i]->value = ((field->conditions->value
                                            & ((insn_uint) 1 <<
                                            & ((insn_uint) 1 <<
                                               (field->last - i))) != 0);
                                               (field->last - i))) != 0);
                  }
                  }
                break;
                break;
              }
              }
          }
          }
      }
      }
  }
  }
 
 
  return word;
  return word;
}
}
 
 
 
 
static void
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;
  insn_word_entry **last_word = &insn->words;
  char *chp;
  char *chp;
 
 
  /* now work through the formats */
  /* now work through the formats */
  insn->nr_words = 0;
  insn->nr_words = 0;
  chp = formats;
  chp = formats;
 
 
  while (1)
  while (1)
    {
    {
      char *start_pos;
      char *start_pos;
      char *end_pos;
      char *end_pos;
      int strlen_pos;
      int strlen_pos;
      char *format;
      char *format;
      insn_word_entry *new_word;
      insn_word_entry *new_word;
 
 
      /* skip leading spaces */
      /* skip leading spaces */
      chp = skip_spaces (chp);
      chp = skip_spaces (chp);
 
 
      /* break out the format */
      /* break out the format */
      start_pos = chp;
      start_pos = chp;
      chp = skip_to_separator (chp, "+");
      chp = skip_to_separator (chp, "+");
      end_pos = back_spaces (start_pos, chp);
      end_pos = back_spaces (start_pos, chp);
      strlen_pos = end_pos - start_pos;
      strlen_pos = end_pos - start_pos;
 
 
      /* check that something was there */
      /* check that something was there */
      if (strlen_pos == 0)
      if (strlen_pos == 0)
        error (insn->line, "missing or empty instruction format\n");
        error (insn->line, "missing or empty instruction format\n");
 
 
      /* parse the field */
      /* parse the field */
      format = NZALLOC (char, strlen_pos + 1);
      format = NZALLOC (char, strlen_pos + 1);
      strncpy (format, start_pos, strlen_pos);
      strncpy (format, start_pos, strlen_pos);
      new_word = parse_insn_word (insn->line, format, insn->nr_words);
      new_word = parse_insn_word (insn->line, format, insn->nr_words);
      insn->nr_words++;
      insn->nr_words++;
      if (filter_is_common (insn->field_names, new_word->field_names))
      if (filter_is_common (insn->field_names, new_word->field_names))
        error (insn->line, "Field name duplicated between two words\n");
        error (insn->line, "Field name duplicated between two words\n");
      filter_add (&insn->field_names, new_word->field_names);
      filter_add (&insn->field_names, new_word->field_names);
 
 
      /* insert it */
      /* insert it */
      *last_word = new_word;
      *last_word = new_word;
      last_word = &new_word->next;
      last_word = &new_word->next;
 
 
      /* last format? */
      /* last format? */
      if (*chp == '\0')
      if (*chp == '\0')
        break;
        break;
      ASSERT (*chp == '+');
      ASSERT (*chp == '+');
      chp++;
      chp++;
    }
    }
 
 
  /* create a quick access array (indexed by word) of the same structure */
  /* create a quick access array (indexed by word) of the same structure */
  {
  {
    int i;
    int i;
    insn_word_entry *word;
    insn_word_entry *word;
    insn->word = NZALLOC (insn_word_entry *, insn->nr_words + 1);
    insn->word = NZALLOC (insn_word_entry *, insn->nr_words + 1);
    for (i = 0, word = insn->words;
    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;
      insn->word[i] = word;
  }
  }
 
 
  /* Go over all fields that have conditionals refering to other
  /* Go over all fields that have conditionals refering to other
     fields.  Link the fields up.  Verify that the two fields have the
     fields.  Link the fields up.  Verify that the two fields have the
     same size. Verify that the two fields are different */
     same size. Verify that the two fields are different */
  {
  {
    int i;
    int i;
    for (i = 0; i < insn->nr_words; i++)
    for (i = 0; i < insn->nr_words; i++)
      {
      {
        insn_word_entry *word = insn->word[i];
        insn_word_entry *word = insn->word[i];
        insn_field_entry *f;
        insn_field_entry *f;
        for (f = word->first; f->last < options.insn_bit_size; f = f->next)
        for (f = word->first; f->last < options.insn_bit_size; f = f->next)
          {
          {
            insn_field_cond *cond;
            insn_field_cond *cond;
            for (cond = f->conditions; cond != NULL; cond = cond->next)
            for (cond = f->conditions; cond != NULL; cond = cond->next)
              {
              {
                if (cond->type == insn_field_cond_field)
                if (cond->type == insn_field_cond_field)
                  {
                  {
                    int j;
                    int j;
                    if (strcmp (cond->string, f->val_string) == 0)
                    if (strcmp (cond->string, f->val_string) == 0)
                      error (insn->line,
                      error (insn->line,
                             "Conditional `%s' of field `%s' refers to its self\n",
                             "Conditional `%s' of field `%s' refers to its self\n",
                             cond->string, f->val_string);
                             cond->string, f->val_string);
                    for (j = 0; j <= i && cond->field == NULL; j++)
                    for (j = 0; j <= i && cond->field == NULL; j++)
                      {
                      {
                        insn_word_entry *refered_word = insn->word[j];
                        insn_word_entry *refered_word = insn->word[j];
                        insn_field_entry *refered_field;
                        insn_field_entry *refered_field;
                        for (refered_field = refered_word->first;
                        for (refered_field = refered_word->first;
                             refered_field != NULL && cond->field == NULL;
                             refered_field != NULL && cond->field == NULL;
                             refered_field = refered_field->next)
                             refered_field = refered_field->next)
                          {
                          {
                            if (refered_field->type == insn_field_string
                            if (refered_field->type == insn_field_string
                                && strcmp (refered_field->val_string,
                                && strcmp (refered_field->val_string,
                                           cond->string) == 0)
                                           cond->string) == 0)
                              {
                              {
                                /* found field being refered to by conditonal */
                                /* found field being refered to by conditonal */
                                cond->field = refered_field;
                                cond->field = refered_field;
                                /* check refered to and this field are
                                /* check refered to and this field are
                                   the same size */
                                   the same size */
                                if (f->width != refered_field->width)
                                if (f->width != refered_field->width)
                                  error (insn->line,
                                  error (insn->line,
                                         "Conditional `%s' of field `%s' should be of size %s\n",
                                         "Conditional `%s' of field `%s' should be of size %s\n",
                                         cond->string, f->val_string,
                                         cond->string, f->val_string,
                                         refered_field->width);
                                         refered_field->width);
                              }
                              }
                          }
                          }
                      }
                      }
                    if (cond->field == NULL)
                    if (cond->field == NULL)
                      error (insn->line,
                      error (insn->line,
                             "Conditional `%s' of field `%s' not yet defined\n",
                             "Conditional `%s' of field `%s' not yet defined\n",
                             cond->string, f->val_string);
                             cond->string, f->val_string);
                  }
                  }
              }
              }
          }
          }
      }
      }
  }
  }
 
 
}
}
 
 
typedef enum
typedef enum
{
{
  unknown_record = 0,
  unknown_record = 0,
  insn_record,                  /* default */
  insn_record,                  /* default */
  code_record,
  code_record,
  cache_record,
  cache_record,
  compute_record,
  compute_record,
  scratch_record,
  scratch_record,
  option_record,
  option_record,
  string_function_record,
  string_function_record,
  function_record,
  function_record,
  internal_record,
  internal_record,
  define_record,
  define_record,
  include_record,
  include_record,
  model_processor_record,
  model_processor_record,
  model_macro_record,
  model_macro_record,
  model_data_record,
  model_data_record,
  model_static_record,
  model_static_record,
  model_function_record,
  model_function_record,
  model_internal_record,
  model_internal_record,
}
}
insn_record_type;
insn_record_type;
 
 
static const name_map insn_type_map[] = {
static const name_map insn_type_map[] = {
  {"option", option_record},
  {"option", option_record},
  {"cache", cache_record},
  {"cache", cache_record},
  {"compute", compute_record},
  {"compute", compute_record},
  {"scratch", scratch_record},
  {"scratch", scratch_record},
  {"define", define_record},
  {"define", define_record},
  {"include", include_record},
  {"include", include_record},
  {"%s", string_function_record},
  {"%s", string_function_record},
  {"function", function_record},
  {"function", function_record},
  {"internal", internal_record},
  {"internal", internal_record},
  {"model", model_processor_record},
  {"model", model_processor_record},
  {"model-macro", model_macro_record},
  {"model-macro", model_macro_record},
  {"model-data", model_data_record},
  {"model-data", model_data_record},
  {"model-static", model_static_record},
  {"model-static", model_static_record},
  {"model-internal", model_internal_record},
  {"model-internal", model_internal_record},
  {"model-function", model_function_record},
  {"model-function", model_function_record},
  {NULL, insn_record},
  {NULL, insn_record},
};
};
 
 
 
 
static int
static int
record_is_old (table_entry *entry)
record_is_old (table_entry *entry)
{
{
  if (entry->nr_fields > record_type_field
  if (entry->nr_fields > record_type_field
      && strlen (entry->field[record_type_field]) == 0)
      && strlen (entry->field[record_type_field]) == 0)
    return 1;
    return 1;
  return 0;
  return 0;
}
}
 
 
static insn_record_type
static insn_record_type
record_type (table_entry *entry)
record_type (table_entry *entry)
{
{
  switch (entry->type)
  switch (entry->type)
    {
    {
    case table_code_entry:
    case table_code_entry:
      return code_record;
      return code_record;
 
 
    case table_colon_entry:
    case table_colon_entry:
      if (record_is_old (entry))
      if (record_is_old (entry))
        {
        {
          /* old-format? */
          /* old-format? */
          if (entry->nr_fields > old_record_type_field)
          if (entry->nr_fields > old_record_type_field)
            {
            {
              int i = name2i (entry->field[old_record_type_field],
              int i = name2i (entry->field[old_record_type_field],
                              insn_type_map);
                              insn_type_map);
              return i;
              return i;
            }
            }
          else
          else
            {
            {
              return unknown_record;
              return unknown_record;
            }
            }
        }
        }
      else if (entry->nr_fields > record_type_field
      else if (entry->nr_fields > record_type_field
               && entry->field[0][0] == '\0')
               && entry->field[0][0] == '\0')
        {
        {
          /* new-format? */
          /* new-format? */
          int i = name2i (entry->field[record_type_field],
          int i = name2i (entry->field[record_type_field],
                          insn_type_map);
                          insn_type_map);
          return i;
          return i;
        }
        }
      else
      else
        return insn_record;     /* default */
        return insn_record;     /* default */
    }
    }
  return unknown_record;
  return unknown_record;
}
}
 
 
static int
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)
  if (entry->type != table_colon_entry)
    return 0;
    return 0;
  if (entry->nr_fields < nr_fields)
  if (entry->nr_fields < nr_fields)
    return 0;
    return 0;
  if (entry->field[0][0] != ch && ch != '\0')
  if (entry->field[0][0] != ch && ch != '\0')
    return 0;
    return 0;
  return 1;
  return 1;
}
}
 
 
static table_entry *
static table_entry *
parse_model_data_record (insn_table *isa,
parse_model_data_record (insn_table *isa,
                         table *file,
                         table *file,
                         table_entry *record,
                         table_entry *record,
                         int nr_fields, model_data **list)
                         int nr_fields, model_data **list)
{
{
  table_entry *model_record = record;
  table_entry *model_record = record;
  table_entry *code_record = NULL;
  table_entry *code_record = NULL;
  model_data *new_data;
  model_data *new_data;
  if (record->nr_fields < nr_fields)
  if (record->nr_fields < nr_fields)
    error (record->line, "Incorrect number of fields\n");
    error (record->line, "Incorrect number of fields\n");
  record = table_read (file);
  record = table_read (file);
  if (record->type == table_code_entry)
  if (record->type == table_code_entry)
    {
    {
      code_record = record;
      code_record = record;
      record = table_read (file);
      record = table_read (file);
    }
    }
  /* create the new data record */
  /* create the new data record */
  new_data = ZALLOC (model_data);
  new_data = ZALLOC (model_data);
  new_data->line = model_record->line;
  new_data->line = model_record->line;
  filter_parse (&new_data->flags,
  filter_parse (&new_data->flags,
                model_record->field[record_filter_flags_field]);
                model_record->field[record_filter_flags_field]);
  new_data->entry = model_record;
  new_data->entry = model_record;
  new_data->code = code_record;
  new_data->code = code_record;
  /* append it if not filtered out */
  /* append it if not filtered out */
  if (!is_filtered_out (options.flags_filter,
  if (!is_filtered_out (options.flags_filter,
                        model_record->field[record_filter_flags_field])
                        model_record->field[record_filter_flags_field])
      && !is_filtered_out (options.model_filter,
      && !is_filtered_out (options.model_filter,
                           model_record->field[record_filter_models_field]))
                           model_record->field[record_filter_models_field]))
    {
    {
      while (*list != NULL)
      while (*list != NULL)
        list = &(*list)->next;
        list = &(*list)->next;
      *list = new_data;
      *list = new_data;
    }
    }
  return record;
  return record;
}
}
 
 
 
 
typedef enum
typedef enum
{
{
  insn_bit_size_option = 1,
  insn_bit_size_option = 1,
  insn_specifying_widths_option,
  insn_specifying_widths_option,
  hi_bit_nr_option,
  hi_bit_nr_option,
  flags_filter_option,
  flags_filter_option,
  model_filter_option,
  model_filter_option,
  multi_sim_option,
  multi_sim_option,
  format_names_option,
  format_names_option,
  gen_delayed_branch,
  gen_delayed_branch,
  unknown_option,
  unknown_option,
}
}
option_names;
option_names;
 
 
static const name_map option_map[] = {
static const name_map option_map[] = {
  {"insn-bit-size", insn_bit_size_option},
  {"insn-bit-size", insn_bit_size_option},
  {"insn-specifying-widths", insn_specifying_widths_option},
  {"insn-specifying-widths", insn_specifying_widths_option},
  {"hi-bit-nr", hi_bit_nr_option},
  {"hi-bit-nr", hi_bit_nr_option},
  {"flags-filter", flags_filter_option},
  {"flags-filter", flags_filter_option},
  {"model-filter", model_filter_option},
  {"model-filter", model_filter_option},
  {"multi-sim", multi_sim_option},
  {"multi-sim", multi_sim_option},
  {"format-names", format_names_option},
  {"format-names", format_names_option},
  {"gen-delayed-branch", gen_delayed_branch},
  {"gen-delayed-branch", gen_delayed_branch},
  {NULL, unknown_option},
  {NULL, unknown_option},
};
};
 
 
static table_entry *
static table_entry *
parse_include_record (table *file, table_entry *record)
parse_include_record (table *file, table_entry *record)
{
{
  /* parse the include record */
  /* parse the include record */
  if (record->nr_fields < nr_include_fields)
  if (record->nr_fields < nr_include_fields)
    error (record->line, "Incorrect nr fields for include record\n");
    error (record->line, "Incorrect nr fields for include record\n");
  /* process it */
  /* process it */
  if (!is_filtered_out (options.flags_filter,
  if (!is_filtered_out (options.flags_filter,
                        record->field[record_filter_flags_field])
                        record->field[record_filter_flags_field])
      && !is_filtered_out (options.model_filter,
      && !is_filtered_out (options.model_filter,
                           record->field[record_filter_models_field]))
                           record->field[record_filter_models_field]))
    {
    {
      table_push (file, record->line, options.include,
      table_push (file, record->line, options.include,
                  record->field[include_filename_field]);
                  record->field[include_filename_field]);
    }
    }
  /* nb: can't read next record until after the file has been pushed */
  /* nb: can't read next record until after the file has been pushed */
  record = table_read (file);
  record = table_read (file);
  return record;
  return record;
}
}
 
 
 
 
static table_entry *
static table_entry *
parse_option_record (table *file, table_entry *record)
parse_option_record (table *file, table_entry *record)
{
{
  table_entry *option_record;
  table_entry *option_record;
  /* parse the option record */
  /* parse the option record */
  option_record = record;
  option_record = record;
  if (record->nr_fields < nr_option_fields)
  if (record->nr_fields < nr_option_fields)
    error (record->line, "Incorrect nr of fields for option record\n");
    error (record->line, "Incorrect nr of fields for option record\n");
  record = table_read (file);
  record = table_read (file);
  /* process it */
  /* process it */
  if (!is_filtered_out (options.flags_filter,
  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,
      && !is_filtered_out (options.model_filter,
                           option_record->field[record_filter_models_field]))
                           option_record->field[record_filter_models_field]))
    {
    {
      char *name = option_record->field[option_name_field];
      char *name = option_record->field[option_name_field];
      option_names option = name2i (name, option_map);
      option_names option = name2i (name, option_map);
      char *value = option_record->field[option_value_field];
      char *value = option_record->field[option_value_field];
      switch (option)
      switch (option)
        {
        {
        case insn_bit_size_option:
        case insn_bit_size_option:
          {
          {
            options.insn_bit_size = a2i (value);
            options.insn_bit_size = a2i (value);
            if (options.insn_bit_size < 0
            if (options.insn_bit_size < 0
                || options.insn_bit_size > max_insn_bit_size)
                || options.insn_bit_size > max_insn_bit_size)
              error (option_record->line,
              error (option_record->line,
                     "Instruction bit size out of range\n");
                     "Instruction bit size out of range\n");
            if (options.hi_bit_nr != options.insn_bit_size - 1
            if (options.hi_bit_nr != options.insn_bit_size - 1
                && options.hi_bit_nr != 0)
                && options.hi_bit_nr != 0)
              error (option_record->line,
              error (option_record->line,
                     "insn-bit-size / hi-bit-nr conflict\n");
                     "insn-bit-size / hi-bit-nr conflict\n");
            break;
            break;
          }
          }
        case insn_specifying_widths_option:
        case insn_specifying_widths_option:
          {
          {
            options.insn_specifying_widths = a2i (value);
            options.insn_specifying_widths = a2i (value);
            break;
            break;
          }
          }
        case hi_bit_nr_option:
        case hi_bit_nr_option:
          {
          {
            options.hi_bit_nr = a2i (value);
            options.hi_bit_nr = a2i (value);
            if (options.hi_bit_nr != 0
            if (options.hi_bit_nr != 0
                && options.hi_bit_nr != options.insn_bit_size - 1)
                && options.hi_bit_nr != options.insn_bit_size - 1)
              error (option_record->line,
              error (option_record->line,
                     "hi-bit-nr / insn-bit-size conflict\n");
                     "hi-bit-nr / insn-bit-size conflict\n");
            break;
            break;
          }
          }
        case flags_filter_option:
        case flags_filter_option:
          {
          {
            filter_parse (&options.flags_filter, value);
            filter_parse (&options.flags_filter, value);
            break;
            break;
          }
          }
        case model_filter_option:
        case model_filter_option:
          {
          {
            filter_parse (&options.model_filter, value);
            filter_parse (&options.model_filter, value);
            break;
            break;
          }
          }
        case multi_sim_option:
        case multi_sim_option:
          {
          {
            options.gen.multi_sim = a2i (value);
            options.gen.multi_sim = a2i (value);
            break;
            break;
          }
          }
        case format_names_option:
        case format_names_option:
          {
          {
            filter_parse (&options.format_name_filter, value);
            filter_parse (&options.format_name_filter, value);
            break;
            break;
          }
          }
        case gen_delayed_branch:
        case gen_delayed_branch:
          {
          {
            options.gen.delayed_branch = a2i (value);
            options.gen.delayed_branch = a2i (value);
            break;
            break;
          }
          }
        case unknown_option:
        case unknown_option:
          {
          {
            error (option_record->line, "Unknown option - %s\n", name);
            error (option_record->line, "Unknown option - %s\n", name);
            break;
            break;
          }
          }
        }
        }
    }
    }
  return record;
  return record;
}
}
 
 
 
 
static table_entry *
static table_entry *
parse_function_record (table *file,
parse_function_record (table *file,
                       table_entry *record,
                       table_entry *record,
                       function_entry ** list,
                       function_entry ** list,
                       function_entry ** list_entry,
                       function_entry ** list_entry,
                       int is_internal, model_table *model)
                       int is_internal, model_table *model)
{
{
  function_entry *new_function;
  function_entry *new_function;
  new_function = ZALLOC (function_entry);
  new_function = ZALLOC (function_entry);
  new_function->line = record->line;
  new_function->line = record->line;
  new_function->is_internal = is_internal;
  new_function->is_internal = is_internal;
  /* parse the function header */
  /* parse the function header */
  if (record_is_old (record))
  if (record_is_old (record))
    {
    {
      if (record->nr_fields < nr_old_function_fields)
      if (record->nr_fields < nr_old_function_fields)
        error (record->line, "Missing fields from (old) function record\n");
        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];
      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)
      if (record->nr_fields > old_function_param_field)
        new_function->param = record->field[old_function_param_field];
        new_function->param = record->field[old_function_param_field];
      new_function->name = record->field[old_function_name_field];
      new_function->name = record->field[old_function_name_field];
    }
    }
  else
  else
    {
    {
      if (record->nr_fields < nr_function_fields)
      if (record->nr_fields < nr_function_fields)
        error (record->line, "Missing fields from function record\n");
        error (record->line, "Missing fields from function record\n");
      filter_parse (&new_function->flags,
      filter_parse (&new_function->flags,
                    record->field[record_filter_flags_field]);
                    record->field[record_filter_flags_field]);
      filter_parse (&new_function->models,
      filter_parse (&new_function->models,
                    record->field[record_filter_models_field]);
                    record->field[record_filter_models_field]);
      new_function->type = record->field[function_typedef_field];
      new_function->type = record->field[function_typedef_field];
      new_function->param = record->field[function_param_field];
      new_function->param = record->field[function_param_field];
      new_function->name = record->field[function_name_field];
      new_function->name = record->field[function_name_field];
    }
    }
  record = table_read (file);
  record = table_read (file);
  /* parse any function-model records */
  /* parse any function-model records */
  while (record != NULL
  while (record != NULL
         && record_prefix_is (record, '*', nr_function_model_fields))
         && record_prefix_is (record, '*', nr_function_model_fields))
    {
    {
      char *model_name = record->field[function_model_name_field] + 1;  /*skip `*' */
      char *model_name = record->field[function_model_name_field] + 1;  /*skip `*' */
      filter_parse (&new_function->models, model_name);
      filter_parse (&new_function->models, model_name);
      if (!filter_is_subset (model->processors, new_function->models))
      if (!filter_is_subset (model->processors, new_function->models))
        {
        {
          error (record->line, "machine model `%s' undefined\n", model_name);
          error (record->line, "machine model `%s' undefined\n", model_name);
        }
        }
      record = table_read (file);
      record = table_read (file);
    }
    }
  /* parse the function body */
  /* parse the function body */
  if (record->type == table_code_entry)
  if (record->type == table_code_entry)
    {
    {
      new_function->code = record;
      new_function->code = record;
      record = table_read (file);
      record = table_read (file);
    }
    }
  /* insert it */
  /* insert it */
  if (!filter_is_subset (options.flags_filter, new_function->flags))
  if (!filter_is_subset (options.flags_filter, new_function->flags))
    {
    {
      if (options.warn.discard)
      if (options.warn.discard)
        notify (new_function->line, "Discarding function %s - filter flags\n",
        notify (new_function->line, "Discarding function %s - filter flags\n",
                new_function->name);
                new_function->name);
    }
    }
  else if (new_function->models != NULL
  else if (new_function->models != NULL
           && !filter_is_common (options.model_filter, new_function->models))
           && !filter_is_common (options.model_filter, new_function->models))
    {
    {
      if (options.warn.discard)
      if (options.warn.discard)
        notify (new_function->line,
        notify (new_function->line,
                "Discarding function %s - filter models\n",
                "Discarding function %s - filter models\n",
                new_function->name);
                new_function->name);
    }
    }
  else
  else
    {
    {
      while (*list != NULL)
      while (*list != NULL)
        list = &(*list)->next;
        list = &(*list)->next;
      *list = new_function;
      *list = new_function;
      if (list_entry != NULL)
      if (list_entry != NULL)
        *list_entry = new_function;
        *list_entry = new_function;
    }
    }
  /* done */
  /* done */
  return record;
  return record;
}
}
 
 
static void
static void
parse_insn_model_record (table *file,
parse_insn_model_record (table *file,
                         table_entry *record,
                         table_entry *record,
                         insn_entry * insn, model_table *model)
                         insn_entry * insn, model_table *model)
{
{
  insn_model_entry **last_insn_model;
  insn_model_entry **last_insn_model;
  insn_model_entry *new_insn_model = ZALLOC (insn_model_entry);
  insn_model_entry *new_insn_model = ZALLOC (insn_model_entry);
  /* parse it */
  /* parse it */
  new_insn_model->line = record->line;
  new_insn_model->line = record->line;
  if (record->nr_fields > insn_model_unit_data_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->unit_data = record->field[insn_model_unit_data_field];
  new_insn_model->insn = insn;
  new_insn_model->insn = insn;
  /* parse the model names, verify that all were defined */
  /* parse the model names, verify that all were defined */
  new_insn_model->names = NULL;
  new_insn_model->names = NULL;
  filter_parse (&new_insn_model->names,
  filter_parse (&new_insn_model->names,
                record->field[insn_model_name_field] + 1 /*skip `*' */ );
                record->field[insn_model_name_field] + 1 /*skip `*' */ );
  if (new_insn_model->names == NULL)
  if (new_insn_model->names == NULL)
    {
    {
      /* No processor names - a generic model entry, enter it into all
      /* No processor names - a generic model entry, enter it into all
         the non-empty fields */
         the non-empty fields */
      int index;
      int index;
      for (index = 0; index < model->nr_models; index++)
      for (index = 0; index < model->nr_models; index++)
        if (insn->model[index] == 0)
        if (insn->model[index] == 0)
          {
          {
            insn->model[index] = new_insn_model;
            insn->model[index] = new_insn_model;
          }
          }
      /* also add the complete processor set to this processor's set */
      /* also add the complete processor set to this processor's set */
      filter_add (&insn->processors, model->processors);
      filter_add (&insn->processors, model->processors);
    }
    }
  else
  else
    {
    {
      /* Find the corresponding master model record for each name so
      /* Find the corresponding master model record for each name so
         that they can be linked in. */
         that they can be linked in. */
      int index;
      int index;
      char *name = "";
      char *name = "";
      while (1)
      while (1)
        {
        {
          name = filter_next (new_insn_model->names, name);
          name = filter_next (new_insn_model->names, name);
          if (name == NULL)
          if (name == NULL)
            break;
            break;
          index = filter_is_member (model->processors, name) - 1;
          index = filter_is_member (model->processors, name) - 1;
          if (index < 0)
          if (index < 0)
            {
            {
              error (new_insn_model->line,
              error (new_insn_model->line,
                     "machine model `%s' undefined\n", name);
                     "machine model `%s' undefined\n", name);
            }
            }
          /* store it in the corresponding model array entry */
          /* store it in the corresponding model array entry */
          if (insn->model[index] != NULL && insn->model[index]->names != NULL)
          if (insn->model[index] != NULL && insn->model[index]->names != NULL)
            {
            {
              warning (new_insn_model->line,
              warning (new_insn_model->line,
                       "machine model `%s' previously defined\n", name);
                       "machine model `%s' previously defined\n", name);
              error (insn->model[index]->line, "earlier definition\n");
              error (insn->model[index]->line, "earlier definition\n");
            }
            }
          insn->model[index] = new_insn_model;
          insn->model[index] = new_insn_model;
          /* also add the name to the instructions processor set as an
          /* also add the name to the instructions processor set as an
             alternative lookup mechanism */
             alternative lookup mechanism */
          filter_parse (&insn->processors, name);
          filter_parse (&insn->processors, name);
        }
        }
    }
    }
#if 0
#if 0
  /* for some reason record the max length of any
  /* for some reason record the max length of any
     function unit field */
     function unit field */
  int len = strlen (insn_model_ptr->field[insn_model_fields]);
  int len = strlen (insn_model_ptr->field[insn_model_fields]);
  if (model->max_model_fields_len < len)
  if (model->max_model_fields_len < len)
    model->max_model_fields_len = len;
    model->max_model_fields_len = len;
#endif
#endif
  /* link it in */
  /* link it in */
  last_insn_model = &insn->models;
  last_insn_model = &insn->models;
  while ((*last_insn_model) != NULL)
  while ((*last_insn_model) != NULL)
    last_insn_model = &(*last_insn_model)->next;
    last_insn_model = &(*last_insn_model)->next;
  *last_insn_model = new_insn_model;
  *last_insn_model = new_insn_model;
}
}
 
 
 
 
static void
static void
parse_insn_mnemonic_record (table *file,
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 **last_insn_mnemonic;
  insn_mnemonic_entry *new_insn_mnemonic = ZALLOC (insn_mnemonic_entry);
  insn_mnemonic_entry *new_insn_mnemonic = ZALLOC (insn_mnemonic_entry);
  /* parse it */
  /* parse it */
  new_insn_mnemonic->line = record->line;
  new_insn_mnemonic->line = record->line;
  ASSERT (record->nr_fields > insn_mnemonic_format_field);
  ASSERT (record->nr_fields > insn_mnemonic_format_field);
  new_insn_mnemonic->format = record->field[insn_mnemonic_format_field];
  new_insn_mnemonic->format = record->field[insn_mnemonic_format_field];
  ASSERT (new_insn_mnemonic->format[0] == '"');
  ASSERT (new_insn_mnemonic->format[0] == '"');
  if (new_insn_mnemonic->format[strlen (new_insn_mnemonic->format) - 1] !=
  if (new_insn_mnemonic->format[strlen (new_insn_mnemonic->format) - 1] !=
      '"')
      '"')
    error (new_insn_mnemonic->line,
    error (new_insn_mnemonic->line,
           "Missing closing double quote in mnemonic field\n");
           "Missing closing double quote in mnemonic field\n");
  if (record->nr_fields > insn_mnemonic_condition_field)
  if (record->nr_fields > insn_mnemonic_condition_field)
    new_insn_mnemonic->condition =
    new_insn_mnemonic->condition =
      record->field[insn_mnemonic_condition_field];
      record->field[insn_mnemonic_condition_field];
  new_insn_mnemonic->insn = insn;
  new_insn_mnemonic->insn = insn;
  /* insert it */
  /* insert it */
  last_insn_mnemonic = &insn->mnemonics;
  last_insn_mnemonic = &insn->mnemonics;
  while ((*last_insn_mnemonic) != NULL)
  while ((*last_insn_mnemonic) != NULL)
    last_insn_mnemonic = &(*last_insn_mnemonic)->next;
    last_insn_mnemonic = &(*last_insn_mnemonic)->next;
  insn->nr_mnemonics++;
  insn->nr_mnemonics++;
  *last_insn_mnemonic = new_insn_mnemonic;
  *last_insn_mnemonic = new_insn_mnemonic;
}
}
 
 
 
 
static table_entry *
static table_entry *
parse_macro_record (table *file, table_entry *record)
parse_macro_record (table *file, table_entry *record)
{
{
#if 1
#if 1
  error (record->line, "Macros are not implemented");
  error (record->line, "Macros are not implemented");
#else
#else
  /* parse the define record */
  /* parse the define record */
  if (record->nr_fields < nr_define_fields)
  if (record->nr_fields < nr_define_fields)
    error (record->line, "Incorrect nr fields for define record\n");
    error (record->line, "Incorrect nr fields for define record\n");
  /* process it */
  /* process it */
  if (!is_filtered_out (options.flags_filter,
  if (!is_filtered_out (options.flags_filter,
                        record->field[record_filter_flags_field])
                        record->field[record_filter_flags_field])
      && !is_filtered_out (options.model_filter,
      && !is_filtered_out (options.model_filter,
                           record->field[record_filter_models_field]))
                           record->field[record_filter_models_field]))
    {
    {
      table_define (file,
      table_define (file,
                    record->line,
                    record->line,
                    record->field[macro_name_field],
                    record->field[macro_name_field],
                    record->field[macro_args_field],
                    record->field[macro_args_field],
                    record->field[macro_expr_field]);
                    record->field[macro_expr_field]);
    }
    }
  record = table_read (file);
  record = table_read (file);
#endif
#endif
  return record;
  return record;
}
}
 
 
 
 
insn_table *
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 *file = table_open (file_name);
  table_entry *record = table_read (file);
  table_entry *record = table_read (file);
 
 
  insn_table *isa = ZALLOC (insn_table);
  insn_table *isa = ZALLOC (insn_table);
  model_table *model = ZALLOC (model_table);
  model_table *model = ZALLOC (model_table);
 
 
  isa->model = model;
  isa->model = model;
  isa->caches = cache;
  isa->caches = cache;
 
 
  while (record != NULL)
  while (record != NULL)
    {
    {
 
 
      switch (record_type (record))
      switch (record_type (record))
        {
        {
 
 
        case include_record:
        case include_record:
          {
          {
            record = parse_include_record (file, record);
            record = parse_include_record (file, record);
            break;
            break;
          }
          }
 
 
        case option_record:
        case option_record:
          {
          {
            if (isa->insns != NULL)
            if (isa->insns != NULL)
              error (record->line, "Option after first instruction\n");
              error (record->line, "Option after first instruction\n");
            record = parse_option_record (file, record);
            record = parse_option_record (file, record);
            break;
            break;
          }
          }
 
 
        case string_function_record:
        case string_function_record:
          {
          {
            function_entry *function = NULL;
            function_entry *function = NULL;
            record = parse_function_record (file, record,
            record = parse_function_record (file, record,
                                            &isa->functions,
                                            &isa->functions,
                                            &function, 0 /*is-internal */ ,
                                            &function, 0 /*is-internal */ ,
                                            model);
                                            model);
            /* convert a string function record into an internal function */
            /* convert a string function record into an internal function */
            if (function != NULL)
            if (function != NULL)
              {
              {
                char *name = NZALLOC (char,
                char *name = NZALLOC (char,
                                      (strlen ("str_")
                                      (strlen ("str_")
                                       + strlen (function->name) + 1));
                                       + strlen (function->name) + 1));
                strcat (name, "str_");
                strcat (name, "str_");
                strcat (name, function->name);
                strcat (name, function->name);
                function->name = name;
                function->name = name;
                function->type = "const char *";
                function->type = "const char *";
              }
              }
            break;
            break;
          }
          }
 
 
        case function_record:   /* function record */
        case function_record:   /* function record */
          {
          {
            record = parse_function_record (file, record,
            record = parse_function_record (file, record,
                                            &isa->functions,
                                            &isa->functions,
                                            NULL, 0 /*is-internal */ ,
                                            NULL, 0 /*is-internal */ ,
                                            model);
                                            model);
            break;
            break;
          }
          }
 
 
        case internal_record:
        case internal_record:
          {
          {
            /* only insert it into the function list if it is unknown */
            /* only insert it into the function list if it is unknown */
            function_entry *function = NULL;
            function_entry *function = NULL;
            record = parse_function_record (file, record,
            record = parse_function_record (file, record,
                                            &isa->functions,
                                            &isa->functions,
                                            &function, 1 /*is-internal */ ,
                                            &function, 1 /*is-internal */ ,
                                            model);
                                            model);
            /* check what was inserted to see if a pseudo-instruction
            /* 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)
            if (function != NULL)
              {
              {
                insn_entry **insn = NULL;
                insn_entry **insn = NULL;
                if (strcmp (function->name, "illegal") == 0)
                if (strcmp (function->name, "illegal") == 0)
                  {
                  {
                    /* illegal function save it away */
                    /* illegal function save it away */
                    if (isa->illegal_insn != NULL)
                    if (isa->illegal_insn != NULL)
                      {
                      {
                        warning (function->line,
                        warning (function->line,
                                 "Multiple illegal instruction definitions\n");
                                 "Multiple illegal instruction definitions\n");
                        error (isa->illegal_insn->line,
                        error (isa->illegal_insn->line,
                               "Location of first illegal instruction\n");
                               "Location of first illegal instruction\n");
                      }
                      }
                    else
                    else
                      insn = &isa->illegal_insn;
                      insn = &isa->illegal_insn;
                  }
                  }
                if (insn != NULL)
                if (insn != NULL)
                  {
                  {
                    *insn = ZALLOC (insn_entry);
                    *insn = ZALLOC (insn_entry);
                    (*insn)->line = function->line;
                    (*insn)->line = function->line;
                    (*insn)->name = function->name;
                    (*insn)->name = function->name;
                    (*insn)->code = function->code;
                    (*insn)->code = function->code;
                  }
                  }
              }
              }
            break;
            break;
          }
          }
 
 
        case scratch_record:    /* cache macro records */
        case scratch_record:    /* cache macro records */
        case cache_record:
        case cache_record:
        case compute_record:
        case compute_record:
          {
          {
            cache_entry *new_cache;
            cache_entry *new_cache;
            /* parse the cache record */
            /* parse the cache record */
            if (record->nr_fields < nr_cache_fields)
            if (record->nr_fields < nr_cache_fields)
              error (record->line,
              error (record->line,
                     "Incorrect nr of fields for scratch/cache/compute record\n");
                     "Incorrect nr of fields for scratch/cache/compute record\n");
            /* create it */
            /* create it */
            new_cache = ZALLOC (cache_entry);
            new_cache = ZALLOC (cache_entry);
            new_cache->line = record->line;
            new_cache->line = record->line;
            filter_parse (&new_cache->flags,
            filter_parse (&new_cache->flags,
                          record->field[record_filter_flags_field]);
                          record->field[record_filter_flags_field]);
            filter_parse (&new_cache->models,
            filter_parse (&new_cache->models,
                          record->field[record_filter_models_field]);
                          record->field[record_filter_models_field]);
            new_cache->type = record->field[cache_typedef_field];
            new_cache->type = record->field[cache_typedef_field];
            new_cache->name = record->field[cache_name_field];
            new_cache->name = record->field[cache_name_field];
            filter_parse (&new_cache->original_fields,
            filter_parse (&new_cache->original_fields,
                          record->field[cache_original_fields_field]);
                          record->field[cache_original_fields_field]);
            new_cache->expression = record->field[cache_expression_field];
            new_cache->expression = record->field[cache_expression_field];
            /* insert it but only if not filtered out */
            /* insert it but only if not filtered out */
            if (!filter_is_subset (options.flags_filter, new_cache->flags))
            if (!filter_is_subset (options.flags_filter, new_cache->flags))
              {
              {
                notify (new_cache->line,
                notify (new_cache->line,
                        "Discarding cache entry %s - filter flags\n",
                        "Discarding cache entry %s - filter flags\n",
                        new_cache->name);
                        new_cache->name);
              }
              }
            else if (is_filtered_out (options.model_filter,
            else if (is_filtered_out (options.model_filter,
                                      record->
                                      record->
                                      field[record_filter_models_field]))
                                      field[record_filter_models_field]))
              {
              {
                notify (new_cache->line,
                notify (new_cache->line,
                        "Discarding cache entry %s - filter models\n",
                        "Discarding cache entry %s - filter models\n",
                        new_cache->name);
                        new_cache->name);
              }
              }
            else
            else
              {
              {
                cache_entry **last;
                cache_entry **last;
                last = &isa->caches;
                last = &isa->caches;
                while (*last != NULL)
                while (*last != NULL)
                  last = &(*last)->next;
                  last = &(*last)->next;
                *last = new_cache;
                *last = new_cache;
              }
              }
            /* advance things */
            /* advance things */
            record = table_read (file);
            record = table_read (file);
            break;
            break;
          }
          }
 
 
          /* model records */
          /* model records */
        case model_processor_record:
        case model_processor_record:
          {
          {
            model_entry *new_model;
            model_entry *new_model;
            /* parse the model */
            /* parse the model */
            if (record->nr_fields < nr_model_processor_fields)
            if (record->nr_fields < nr_model_processor_fields)
              error (record->line,
              error (record->line,
                     "Incorrect nr of fields for model record\n");
                     "Incorrect nr of fields for model record\n");
            if (isa->insns != NULL)
            if (isa->insns != NULL)
              error (record->line, "Model appears after first instruction\n");
              error (record->line, "Model appears after first instruction\n");
            new_model = ZALLOC (model_entry);
            new_model = ZALLOC (model_entry);
            filter_parse (&new_model->flags,
            filter_parse (&new_model->flags,
                          record->field[record_filter_flags_field]);
                          record->field[record_filter_flags_field]);
            new_model->line = record->line;
            new_model->line = record->line;
            new_model->name = record->field[model_name_field];
            new_model->name = record->field[model_name_field];
            new_model->full_name = record->field[model_full_name_field];
            new_model->full_name = record->field[model_full_name_field];
            new_model->unit_data = record->field[model_unit_data_field];
            new_model->unit_data = record->field[model_unit_data_field];
            /* only insert it if not filtered out */
            /* only insert it if not filtered out */
            if (!filter_is_subset (options.flags_filter, new_model->flags))
            if (!filter_is_subset (options.flags_filter, new_model->flags))
              {
              {
                notify (new_model->line,
                notify (new_model->line,
                        "Discarding processor model %s - filter flags\n",
                        "Discarding processor model %s - filter flags\n",
                        new_model->name);
                        new_model->name);
              }
              }
            else if (is_filtered_out (options.model_filter,
            else if (is_filtered_out (options.model_filter,
                                      record->
                                      record->
                                      field[record_filter_models_field]))
                                      field[record_filter_models_field]))
              {
              {
                notify (new_model->line,
                notify (new_model->line,
                        "Discarding processor model %s - filter models\n",
                        "Discarding processor model %s - filter models\n",
                        new_model->name);
                        new_model->name);
              }
              }
            else if (filter_is_member (model->processors, new_model->name))
            else if (filter_is_member (model->processors, new_model->name))
              {
              {
                error (new_model->line, "Duplicate processor model %s\n",
                error (new_model->line, "Duplicate processor model %s\n",
                       new_model->name);
                       new_model->name);
              }
              }
            else
            else
              {
              {
                model_entry **last;
                model_entry **last;
                last = &model->models;
                last = &model->models;
                while (*last != NULL)
                while (*last != NULL)
                  last = &(*last)->next;
                  last = &(*last)->next;
                *last = new_model;
                *last = new_model;
                /* count it */
                /* count it */
                model->nr_models++;
                model->nr_models++;
                filter_parse (&model->processors, new_model->name);
                filter_parse (&model->processors, new_model->name);
              }
              }
            /* advance things */
            /* advance things */
            record = table_read (file);
            record = table_read (file);
          }
          }
          break;
          break;
 
 
        case model_macro_record:
        case model_macro_record:
          record = parse_model_data_record (isa, file, record,
          record = parse_model_data_record (isa, file, record,
                                            nr_model_macro_fields,
                                            nr_model_macro_fields,
                                            &model->macros);
                                            &model->macros);
          break;
          break;
 
 
        case model_data_record:
        case model_data_record:
          record = parse_model_data_record (isa, file, record,
          record = parse_model_data_record (isa, file, record,
                                            nr_model_data_fields,
                                            nr_model_data_fields,
                                            &model->data);
                                            &model->data);
          break;
          break;
 
 
        case model_static_record:
        case model_static_record:
          record = parse_function_record (file, record,
          record = parse_function_record (file, record,
                                          &model->statics,
                                          &model->statics,
                                          NULL, 0 /*is internal */ ,
                                          NULL, 0 /*is internal */ ,
                                          model);
                                          model);
          break;
          break;
 
 
        case model_internal_record:
        case model_internal_record:
          record = parse_function_record (file, record,
          record = parse_function_record (file, record,
                                          &model->internals,
                                          &model->internals,
                                          NULL, 1 /*is internal */ ,
                                          NULL, 1 /*is internal */ ,
                                          model);
                                          model);
          break;
          break;
 
 
        case model_function_record:
        case model_function_record:
          record = parse_function_record (file, record,
          record = parse_function_record (file, record,
                                          &model->functions,
                                          &model->functions,
                                          NULL, 0 /*is internal */ ,
                                          NULL, 0 /*is internal */ ,
                                          model);
                                          model);
          break;
          break;
 
 
        case insn_record:       /* instruction records */
        case insn_record:       /* instruction records */
          {
          {
            insn_entry *new_insn;
            insn_entry *new_insn;
            char *format;
            char *format;
            /* parse the instruction */
            /* parse the instruction */
            if (record->nr_fields < nr_insn_fields)
            if (record->nr_fields < nr_insn_fields)
              error (record->line,
              error (record->line,
                     "Incorrect nr of fields for insn record\n");
                     "Incorrect nr of fields for insn record\n");
            new_insn = ZALLOC (insn_entry);
            new_insn = ZALLOC (insn_entry);
            new_insn->line = record->line;
            new_insn->line = record->line;
            filter_parse (&new_insn->flags,
            filter_parse (&new_insn->flags,
                          record->field[record_filter_flags_field]);
                          record->field[record_filter_flags_field]);
            /* save the format field.  Can't parse it until after the
            /* save the format field.  Can't parse it until after the
               filter-out checks.  Could be filtered out because the
               filter-out checks.  Could be filtered out because the
               format is invalid */
               format is invalid */
            format = record->field[insn_word_field];
            format = record->field[insn_word_field];
            new_insn->format_name = record->field[insn_format_name_field];
            new_insn->format_name = record->field[insn_format_name_field];
            if (options.format_name_filter != NULL
            if (options.format_name_filter != NULL
                && !filter_is_member (options.format_name_filter,
                && !filter_is_member (options.format_name_filter,
                                      new_insn->format_name))
                                      new_insn->format_name))
              error (new_insn->line,
              error (new_insn->line,
                     "Unreconized instruction format name `%s'\n",
                     "Unreconized instruction format name `%s'\n",
                     new_insn->format_name);
                     new_insn->format_name);
            filter_parse (&new_insn->options,
            filter_parse (&new_insn->options,
                          record->field[insn_options_field]);
                          record->field[insn_options_field]);
            new_insn->name = record->field[insn_name_field];
            new_insn->name = record->field[insn_name_field];
            record = table_read (file);
            record = table_read (file);
            /* Parse any model/assember records */
            /* Parse any model/assember records */
            new_insn->nr_models = model->nr_models;
            new_insn->nr_models = model->nr_models;
            new_insn->model =
            new_insn->model =
              NZALLOC (insn_model_entry *, model->nr_models + 1);
              NZALLOC (insn_model_entry *, model->nr_models + 1);
            while (record != NULL)
            while (record != NULL)
              {
              {
                if (record_prefix_is (record, '*', nr_insn_model_fields))
                if (record_prefix_is (record, '*', nr_insn_model_fields))
                  parse_insn_model_record (file, record, new_insn, model);
                  parse_insn_model_record (file, record, new_insn, model);
                else
                else
                  if (record_prefix_is (record, '"', nr_insn_mnemonic_fields))
                  if (record_prefix_is (record, '"', nr_insn_mnemonic_fields))
                  parse_insn_mnemonic_record (file, record, new_insn);
                  parse_insn_mnemonic_record (file, record, new_insn);
                else
                else
                  break;
                  break;
                /* advance */
                /* advance */
                record = table_read (file);
                record = table_read (file);
              }
              }
            /* Parse the code record */
            /* Parse the code record */
            if (record != NULL && record->type == table_code_entry)
            if (record != NULL && record->type == table_code_entry)
              {
              {
                new_insn->code = record;
                new_insn->code = record;
                record = table_read (file);
                record = table_read (file);
              }
              }
            else if (options.warn.unimplemented)
            else if (options.warn.unimplemented)
              notify (new_insn->line, "unimplemented\n");
              notify (new_insn->line, "unimplemented\n");
            /* insert it */
            /* insert it */
            if (!filter_is_subset (options.flags_filter, new_insn->flags))
            if (!filter_is_subset (options.flags_filter, new_insn->flags))
              {
              {
                if (options.warn.discard)
                if (options.warn.discard)
                  notify (new_insn->line,
                  notify (new_insn->line,
                          "Discarding instruction %s (flags-filter)\n",
                          "Discarding instruction %s (flags-filter)\n",
                          new_insn->name);
                          new_insn->name);
              }
              }
            else if (new_insn->processors != NULL
            else if (new_insn->processors != NULL
                     && options.model_filter != NULL
                     && options.model_filter != NULL
                     && !filter_is_common (options.model_filter,
                     && !filter_is_common (options.model_filter,
                                           new_insn->processors))
                                           new_insn->processors))
              {
              {
                /* only discard an instruction based in the processor
                /* only discard an instruction based in the processor
                   model when both the instruction and the options are
                   model when both the instruction and the options are
                   nonempty */
                   nonempty */
                if (options.warn.discard)
                if (options.warn.discard)
                  notify (new_insn->line,
                  notify (new_insn->line,
                          "Discarding instruction %s (processor-model)\n",
                          "Discarding instruction %s (processor-model)\n",
                          new_insn->name);
                          new_insn->name);
              }
              }
            else
            else
              {
              {
                insn_entry **last;
                insn_entry **last;
                /* finish the parsing */
                /* finish the parsing */
                parse_insn_words (new_insn, format);
                parse_insn_words (new_insn, format);
                /* append it */
                /* append it */
                last = &isa->insns;
                last = &isa->insns;
                while (*last)
                while (*last)
                  last = &(*last)->next;
                  last = &(*last)->next;
                *last = new_insn;
                *last = new_insn;
                /* update global isa counters */
                /* update global isa counters */
                isa->nr_insns++;
                isa->nr_insns++;
                if (isa->max_nr_words < new_insn->nr_words)
                if (isa->max_nr_words < new_insn->nr_words)
                  isa->max_nr_words = new_insn->nr_words;
                  isa->max_nr_words = new_insn->nr_words;
                filter_add (&isa->flags, new_insn->flags);
                filter_add (&isa->flags, new_insn->flags);
                filter_add (&isa->options, new_insn->options);
                filter_add (&isa->options, new_insn->options);
              }
              }
            break;
            break;
          }
          }
 
 
        case define_record:
        case define_record:
          record = parse_macro_record (file, record);
          record = parse_macro_record (file, record);
          break;
          break;
 
 
        case unknown_record:
        case unknown_record:
        case code_record:
        case code_record:
          error (record->line, "Unknown or unexpected entry\n");
          error (record->line, "Unknown or unexpected entry\n");
 
 
 
 
        }
        }
    }
    }
  return isa;
  return isa;
}
}
 
 
 
 
void
void
print_insn_words (lf *file, insn_entry * insn)
print_insn_words (lf *file, insn_entry * insn)
{
{
  insn_word_entry *word = insn->words;
  insn_word_entry *word = insn->words;
  if (word != NULL)
  if (word != NULL)
    {
    {
      while (1)
      while (1)
        {
        {
          insn_field_entry *field = word->first;
          insn_field_entry *field = word->first;
          while (1)
          while (1)
            {
            {
              if (options.insn_specifying_widths)
              if (options.insn_specifying_widths)
                lf_printf (file, "%d.", field->width);
                lf_printf (file, "%d.", field->width);
              else
              else
                lf_printf (file, "%d.",
                lf_printf (file, "%d.",
                           i2target (options.hi_bit_nr, field->first));
                           i2target (options.hi_bit_nr, field->first));
              switch (field->type)
              switch (field->type)
                {
                {
                case insn_field_invalid:
                case insn_field_invalid:
                  ASSERT (0);
                  ASSERT (0);
                  break;
                  break;
                case insn_field_int:
                case insn_field_int:
                  lf_printf (file, "0x%lx", (long) field->val_int);
                  lf_printf (file, "0x%lx", (long) field->val_int);
                  break;
                  break;
                case insn_field_reserved:
                case insn_field_reserved:
                  lf_printf (file, "/");
                  lf_printf (file, "/");
                  break;
                  break;
                case insn_field_wild:
                case insn_field_wild:
                  lf_printf (file, "*");
                  lf_printf (file, "*");
                  break;
                  break;
                case insn_field_string:
                case insn_field_string:
                  lf_printf (file, "%s", field->val_string);
                  lf_printf (file, "%s", field->val_string);
                  break;
                  break;
                }
                }
              if (field == word->last)
              if (field == word->last)
                break;
                break;
              field = field->next;
              field = field->next;
              lf_printf (file, ",");
              lf_printf (file, ",");
            }
            }
          word = word->next;
          word = word->next;
          if (word == NULL)
          if (word == NULL)
            break;
            break;
          lf_printf (file, "+");
          lf_printf (file, "+");
        }
        }
    }
    }
}
}


 
 
 
 
void
void
function_entry_traverse (lf *file,
function_entry_traverse (lf *file,
                         function_entry * functions,
                         function_entry * functions,
                         function_entry_handler * handler, void *data)
                         function_entry_handler * handler, void *data)
{
{
  function_entry *function;
  function_entry *function;
  for (function = functions; function != NULL; function = function->next)
  for (function = functions; function != NULL; function = function->next)
    {
    {
      handler (file, function, data);
      handler (file, function, data);
    }
    }
}
}
 
 
void
void
insn_table_traverse_insn (lf *file,
insn_table_traverse_insn (lf *file,
                          insn_table *isa,
                          insn_table *isa,
                          insn_entry_handler * handler, void *data)
                          insn_entry_handler * handler, void *data)
{
{
  insn_entry *insn;
  insn_entry *insn;
  for (insn = isa->insns; insn != NULL; insn = insn->next)
  for (insn = isa->insns; insn != NULL; insn = insn->next)
    {
    {
      handler (file, isa, insn, data);
      handler (file, isa, insn, data);
    }
    }
}
}


 
 
static void
static void
dump_function_entry (lf *file,
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);
  lf_printf (file, "%s(function_entry *) 0x%lx", prefix, (long) entry);
  if (entry != NULL)
  if (entry != NULL)
    {
    {
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      lf_printf (file, "\n(type \"%s\")", entry->type);
      lf_printf (file, "\n(type \"%s\")", entry->type);
      lf_printf (file, "\n(name \"%s\")", entry->name);
      lf_printf (file, "\n(name \"%s\")", entry->name);
      lf_printf (file, "\n(param \"%s\")", entry->param);
      lf_printf (file, "\n(param \"%s\")", entry->param);
      dump_table_entry (file, "\n(code ", entry->code, ")");
      dump_table_entry (file, "\n(code ", entry->code, ")");
      lf_printf (file, "\n(is_internal %d)", entry->is_internal);
      lf_printf (file, "\n(is_internal %d)", entry->is_internal);
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
static void
static void
dump_function_entries (lf *file,
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_printf (file, "%s", prefix);
  lf_indent (file, +1);
  lf_indent (file, +1);
  while (entry != NULL)
  while (entry != NULL)
    {
    {
      dump_function_entry (file, "\n(", entry, ")");
      dump_function_entry (file, "\n(", entry, ")");
      entry = entry->next;
      entry = entry->next;
    }
    }
  lf_indent (file, -1);
  lf_indent (file, -1);
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
static char *
static char *
cache_entry_type_to_str (cache_entry_type type)
cache_entry_type_to_str (cache_entry_type type)
{
{
  switch (type)
  switch (type)
    {
    {
    case scratch_value:
    case scratch_value:
      return "scratch";
      return "scratch";
    case cache_value:
    case cache_value:
      return "cache";
      return "cache";
    case compute_value:
    case compute_value:
      return "compute";
      return "compute";
    }
    }
  ERROR ("Bad switch");
  ERROR ("Bad switch");
  return 0;
  return 0;
}
}
 
 
static void
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);
  lf_printf (file, "%s(cache_entry *) 0x%lx", prefix, (long) entry);
  if (entry != NULL)
  if (entry != NULL)
    {
    {
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      lf_printf (file, "\n(entry_type \"%s\")",
      lf_printf (file, "\n(entry_type \"%s\")",
                 cache_entry_type_to_str (entry->entry_type));
                 cache_entry_type_to_str (entry->entry_type));
      lf_printf (file, "\n(name \"%s\")", entry->name);
      lf_printf (file, "\n(name \"%s\")", entry->name);
      dump_filter (file, "\n(original_fields ", entry->original_fields, ")");
      dump_filter (file, "\n(original_fields ", entry->original_fields, ")");
      lf_printf (file, "\n(type \"%s\")", entry->type);
      lf_printf (file, "\n(type \"%s\")", entry->type);
      lf_printf (file, "\n(expression \"%s\")", entry->expression);
      lf_printf (file, "\n(expression \"%s\")", entry->expression);
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
void
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_printf (file, "%s", prefix);
  lf_indent (file, +1);
  lf_indent (file, +1);
  while (entry != NULL)
  while (entry != NULL)
    {
    {
      dump_cache_entry (file, "\n(", entry, ")");
      dump_cache_entry (file, "\n(", entry, ")");
      entry = entry->next;
      entry = entry->next;
    }
    }
  lf_indent (file, -1);
  lf_indent (file, -1);
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
static void
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);
  lf_printf (file, "%s(model_data *) 0x%lx", prefix, (long) entry);
  if (entry != NULL)
  if (entry != NULL)
    {
    {
      lf_indent (file, +1);
      lf_indent (file, +1);
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      dump_table_entry (file, "\n(entry ", entry->entry, ")");
      dump_table_entry (file, "\n(entry ", entry->entry, ")");
      dump_table_entry (file, "\n(code ", entry->code, ")");
      dump_table_entry (file, "\n(code ", entry->code, ")");
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
      lf_indent (file, -1);
      lf_indent (file, -1);
    }
    }
  lf_printf (file, "%s", prefix);
  lf_printf (file, "%s", prefix);
}
}
 
 
static void
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_printf (file, "%s", prefix);
  lf_indent (file, +1);
  lf_indent (file, +1);
  while (entry != NULL)
  while (entry != NULL)
    {
    {
      dump_model_data (file, "\n(", entry, ")");
      dump_model_data (file, "\n(", entry, ")");
      entry = entry->next;
      entry = entry->next;
    }
    }
  lf_indent (file, -1);
  lf_indent (file, -1);
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
static void
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);
  lf_printf (file, "%s(model_entry *) 0x%lx", prefix, (long) entry);
  if (entry != NULL)
  if (entry != NULL)
    {
    {
      lf_indent (file, +1);
      lf_indent (file, +1);
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      lf_printf (file, "\n(name \"%s\")", entry->name);
      lf_printf (file, "\n(name \"%s\")", entry->name);
      lf_printf (file, "\n(full_name \"%s\")", entry->full_name);
      lf_printf (file, "\n(full_name \"%s\")", entry->full_name);
      lf_printf (file, "\n(unit_data \"%s\")", entry->unit_data);
      lf_printf (file, "\n(unit_data \"%s\")", entry->unit_data);
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
      lf_indent (file, -1);
      lf_indent (file, -1);
    }
    }
  lf_printf (file, "%s", prefix);
  lf_printf (file, "%s", prefix);
}
}
 
 
static void
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_printf (file, "%s", prefix);
  lf_indent (file, +1);
  lf_indent (file, +1);
  while (entry != NULL)
  while (entry != NULL)
    {
    {
      dump_model_entry (file, "\n(", entry, ")");
      dump_model_entry (file, "\n(", entry, ")");
      entry = entry->next;
      entry = entry->next;
    }
    }
  lf_indent (file, -1);
  lf_indent (file, -1);
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
 
 
static void
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);
  lf_printf (file, "%s(model_table *) 0x%lx", prefix, (long) entry);
  if (entry != NULL)
  if (entry != NULL)
    {
    {
      lf_indent (file, +1);
      lf_indent (file, +1);
      dump_filter (file, "\n(processors ", entry->processors, ")");
      dump_filter (file, "\n(processors ", entry->processors, ")");
      lf_printf (file, "\n(nr_models %d)", entry->nr_models);
      lf_printf (file, "\n(nr_models %d)", entry->nr_models);
      dump_model_entries (file, "\n(models ", entry->models, ")");
      dump_model_entries (file, "\n(models ", entry->models, ")");
      dump_model_datas (file, "\n(macros ", entry->macros, ")");
      dump_model_datas (file, "\n(macros ", entry->macros, ")");
      dump_model_datas (file, "\n(data ", entry->data, ")");
      dump_model_datas (file, "\n(data ", entry->data, ")");
      dump_function_entries (file, "\n(statics ", entry->statics, ")");
      dump_function_entries (file, "\n(statics ", entry->statics, ")");
      dump_function_entries (file, "\n(internals ", entry->functions, ")");
      dump_function_entries (file, "\n(internals ", entry->functions, ")");
      dump_function_entries (file, "\n(functions ", entry->functions, ")");
      dump_function_entries (file, "\n(functions ", entry->functions, ")");
      lf_indent (file, -1);
      lf_indent (file, -1);
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
 
 
static char *
static char *
insn_field_type_to_str (insn_field_type type)
insn_field_type_to_str (insn_field_type type)
{
{
  switch (type)
  switch (type)
    {
    {
    case insn_field_invalid:
    case insn_field_invalid:
      ASSERT (0);
      ASSERT (0);
      return "(invalid)";
      return "(invalid)";
    case insn_field_int:
    case insn_field_int:
      return "int";
      return "int";
    case insn_field_reserved:
    case insn_field_reserved:
      return "reserved";
      return "reserved";
    case insn_field_wild:
    case insn_field_wild:
      return "wild";
      return "wild";
    case insn_field_string:
    case insn_field_string:
      return "string";
      return "string";
    }
    }
  ERROR ("bad switch");
  ERROR ("bad switch");
  return 0;
  return 0;
}
}
 
 
void
void
dump_insn_field (lf *file,
dump_insn_field (lf *file,
                 char *prefix, insn_field_entry *field, char *suffix)
                 char *prefix, insn_field_entry *field, char *suffix)
{
{
  char *sep = " ";
  char *sep = " ";
  lf_printf (file, "%s(insn_field_entry *) 0x%lx", prefix, (long) field);
  lf_printf (file, "%s(insn_field_entry *) 0x%lx", prefix, (long) field);
  if (field != NULL)
  if (field != NULL)
    {
    {
      lf_indent (file, +1);
      lf_indent (file, +1);
      lf_printf (file, "%s(first %d)", sep, field->first);
      lf_printf (file, "%s(first %d)", sep, field->first);
      lf_printf (file, "%s(last %d)", sep, field->last);
      lf_printf (file, "%s(last %d)", sep, field->last);
      lf_printf (file, "%s(width %d)", sep, field->width);
      lf_printf (file, "%s(width %d)", sep, field->width);
      lf_printf (file, "%s(type %s)", sep,
      lf_printf (file, "%s(type %s)", sep,
                 insn_field_type_to_str (field->type));
                 insn_field_type_to_str (field->type));
      switch (field->type)
      switch (field->type)
        {
        {
        case insn_field_invalid:
        case insn_field_invalid:
          ASSERT (0);
          ASSERT (0);
          break;
          break;
        case insn_field_int:
        case insn_field_int:
          lf_printf (file, "%s(val 0x%lx)", sep, (long) field->val_int);
          lf_printf (file, "%s(val 0x%lx)", sep, (long) field->val_int);
          break;
          break;
        case insn_field_reserved:
        case insn_field_reserved:
          /* nothing output */
          /* nothing output */
          break;
          break;
        case insn_field_wild:
        case insn_field_wild:
          /* nothing output */
          /* nothing output */
          break;
          break;
        case insn_field_string:
        case insn_field_string:
          lf_printf (file, "%s(val \"%s\")", sep, field->val_string);
          lf_printf (file, "%s(val \"%s\")", sep, field->val_string);
          break;
          break;
        }
        }
      lf_printf (file, "%s(next 0x%lx)", sep, (long) field->next);
      lf_printf (file, "%s(next 0x%lx)", sep, (long) field->next);
      lf_printf (file, "%s(prev 0x%lx)", sep, (long) field->prev);
      lf_printf (file, "%s(prev 0x%lx)", sep, (long) field->prev);
      lf_indent (file, -1);
      lf_indent (file, -1);
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
void
void
dump_insn_word_entry (lf *file,
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);
  lf_printf (file, "%s(insn_word_entry *) 0x%lx", prefix, (long) word);
  if (word != NULL)
  if (word != NULL)
    {
    {
      int i;
      int i;
      insn_field_entry *field;
      insn_field_entry *field;
      lf_indent (file, +1);
      lf_indent (file, +1);
      lf_printf (file, "\n(first 0x%lx)", (long) word->first);
      lf_printf (file, "\n(first 0x%lx)", (long) word->first);
      lf_printf (file, "\n(last 0x%lx)", (long) word->last);
      lf_printf (file, "\n(last 0x%lx)", (long) word->last);
      lf_printf (file, "\n(bit");
      lf_printf (file, "\n(bit");
      for (i = 0; i < options.insn_bit_size; i++)
      for (i = 0; i < options.insn_bit_size; i++)
        lf_printf (file, "\n ((value %d) (mask %d) (field 0x%lx))",
        lf_printf (file, "\n ((value %d) (mask %d) (field 0x%lx))",
                   word->bit[i]->value, word->bit[i]->mask,
                   word->bit[i]->value, word->bit[i]->mask,
                   (long) word->bit[i]->field);
                   (long) word->bit[i]->field);
      lf_printf (file, ")");
      lf_printf (file, ")");
      for (field = word->first; field != NULL; field = field->next)
      for (field = word->first; field != NULL; field = field->next)
        dump_insn_field (file, "\n(", field, ")");
        dump_insn_field (file, "\n(", field, ")");
      dump_filter (file, "\n(field_names ", word->field_names, ")");
      dump_filter (file, "\n(field_names ", word->field_names, ")");
      lf_printf (file, "\n(next 0x%lx)", (long) word->next);
      lf_printf (file, "\n(next 0x%lx)", (long) word->next);
      lf_indent (file, -1);
      lf_indent (file, -1);
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
static void
static void
dump_insn_word_entries (lf *file,
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);
  lf_printf (file, "%s", prefix);
  while (word != NULL)
  while (word != NULL)
    {
    {
      dump_insn_word_entry (file, "\n(", word, ")");
      dump_insn_word_entry (file, "\n(", word, ")");
      word = word->next;
      word = word->next;
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
static void
static void
dump_insn_model_entry (lf *file,
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);
  lf_printf (file, "%s(insn_model_entry *) 0x%lx", prefix, (long) model);
  if (model != NULL)
  if (model != NULL)
    {
    {
      lf_indent (file, +1);
      lf_indent (file, +1);
      dump_line_ref (file, "\n(line ", model->line, ")");
      dump_line_ref (file, "\n(line ", model->line, ")");
      dump_filter (file, "\n(names ", model->names, ")");
      dump_filter (file, "\n(names ", model->names, ")");
      lf_printf (file, "\n(full_name \"%s\")", model->full_name);
      lf_printf (file, "\n(full_name \"%s\")", model->full_name);
      lf_printf (file, "\n(unit_data \"%s\")", model->unit_data);
      lf_printf (file, "\n(unit_data \"%s\")", model->unit_data);
      lf_printf (file, "\n(insn (insn_entry *) 0x%lx)", (long) model->insn);
      lf_printf (file, "\n(insn (insn_entry *) 0x%lx)", (long) model->insn);
      lf_printf (file, "\n(next (insn_model_entry *) 0x%lx)",
      lf_printf (file, "\n(next (insn_model_entry *) 0x%lx)",
                 (long) model->next);
                 (long) model->next);
      lf_indent (file, -1);
      lf_indent (file, -1);
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
static void
static void
dump_insn_model_entries (lf *file,
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);
  lf_printf (file, "%s", prefix);
  while (model != NULL)
  while (model != NULL)
    {
    {
      dump_insn_model_entry (file, "\n", model, "");
      dump_insn_model_entry (file, "\n", model, "");
      model = model->next;
      model = model->next;
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
 
 
static void
static void
dump_insn_mnemonic_entry (lf *file,
dump_insn_mnemonic_entry (lf *file,
                          char *prefix,
                          char *prefix,
                          insn_mnemonic_entry *mnemonic, char *suffix)
                          insn_mnemonic_entry *mnemonic, char *suffix)
{
{
  lf_printf (file, "%s(insn_mnemonic_entry *) 0x%lx", prefix,
  lf_printf (file, "%s(insn_mnemonic_entry *) 0x%lx", prefix,
             (long) mnemonic);
             (long) mnemonic);
  if (mnemonic != NULL)
  if (mnemonic != NULL)
    {
    {
      lf_indent (file, +1);
      lf_indent (file, +1);
      dump_line_ref (file, "\n(line ", mnemonic->line, ")");
      dump_line_ref (file, "\n(line ", mnemonic->line, ")");
      lf_printf (file, "\n(format \"%s\")", mnemonic->format);
      lf_printf (file, "\n(format \"%s\")", mnemonic->format);
      lf_printf (file, "\n(condition \"%s\")", mnemonic->condition);
      lf_printf (file, "\n(condition \"%s\")", mnemonic->condition);
      lf_printf (file, "\n(insn (insn_entry *) 0x%lx)",
      lf_printf (file, "\n(insn (insn_entry *) 0x%lx)",
                 (long) mnemonic->insn);
                 (long) mnemonic->insn);
      lf_printf (file, "\n(next (insn_mnemonic_entry *) 0x%lx)",
      lf_printf (file, "\n(next (insn_mnemonic_entry *) 0x%lx)",
                 (long) mnemonic->next);
                 (long) mnemonic->next);
      lf_indent (file, -1);
      lf_indent (file, -1);
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
static void
static void
dump_insn_mnemonic_entries (lf *file,
dump_insn_mnemonic_entries (lf *file,
                            char *prefix,
                            char *prefix,
                            insn_mnemonic_entry *mnemonic, char *suffix)
                            insn_mnemonic_entry *mnemonic, char *suffix)
{
{
  lf_printf (file, "%s", prefix);
  lf_printf (file, "%s", prefix);
  while (mnemonic != NULL)
  while (mnemonic != NULL)
    {
    {
      dump_insn_mnemonic_entry (file, "\n", mnemonic, "");
      dump_insn_mnemonic_entry (file, "\n", mnemonic, "");
      mnemonic = mnemonic->next;
      mnemonic = mnemonic->next;
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
void
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);
  lf_printf (file, "%s(insn_entry *) 0x%lx", prefix, (long) entry);
  if (entry != NULL)
  if (entry != NULL)
    {
    {
      int i;
      int i;
      lf_indent (file, +1);
      lf_indent (file, +1);
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_line_ref (file, "\n(line ", entry->line, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      dump_filter (file, "\n(flags ", entry->flags, ")");
      lf_printf (file, "\n(nr_words %d)", entry->nr_words);
      lf_printf (file, "\n(nr_words %d)", entry->nr_words);
      dump_insn_word_entries (file, "\n(words ", entry->words, ")");
      dump_insn_word_entries (file, "\n(words ", entry->words, ")");
      lf_printf (file, "\n(word");
      lf_printf (file, "\n(word");
      for (i = 0; i < entry->nr_models; i++)
      for (i = 0; i < entry->nr_models; i++)
        lf_printf (file, " 0x%lx", (long) entry->word[i]);
        lf_printf (file, " 0x%lx", (long) entry->word[i]);
      lf_printf (file, ")");
      lf_printf (file, ")");
      dump_filter (file, "\n(field_names ", entry->field_names, ")");
      dump_filter (file, "\n(field_names ", entry->field_names, ")");
      lf_printf (file, "\n(format_name \"%s\")", entry->format_name);
      lf_printf (file, "\n(format_name \"%s\")", entry->format_name);
      dump_filter (file, "\n(options ", entry->options, ")");
      dump_filter (file, "\n(options ", entry->options, ")");
      lf_printf (file, "\n(name \"%s\")", entry->name);
      lf_printf (file, "\n(name \"%s\")", entry->name);
      lf_printf (file, "\n(nr_models %d)", entry->nr_models);
      lf_printf (file, "\n(nr_models %d)", entry->nr_models);
      dump_insn_model_entries (file, "\n(models ", entry->models, ")");
      dump_insn_model_entries (file, "\n(models ", entry->models, ")");
      lf_printf (file, "\n(model");
      lf_printf (file, "\n(model");
      for (i = 0; i < entry->nr_models; i++)
      for (i = 0; i < entry->nr_models; i++)
        lf_printf (file, " 0x%lx", (long) entry->model[i]);
        lf_printf (file, " 0x%lx", (long) entry->model[i]);
      lf_printf (file, ")");
      lf_printf (file, ")");
      dump_filter (file, "\n(processors ", entry->processors, ")");
      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, ")");
      dump_table_entry (file, "\n(code ", entry->code, ")");
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
      lf_printf (file, "\n(next 0x%lx)", (long) entry->next);
      lf_indent (file, -1);
      lf_indent (file, -1);
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
static void
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_printf (file, "%s", prefix);
  lf_indent (file, +1);
  lf_indent (file, +1);
  while (entry != NULL)
  while (entry != NULL)
    {
    {
      dump_insn_entry (file, "\n(", entry, ")");
      dump_insn_entry (file, "\n(", entry, ")");
      entry = entry->next;
      entry = entry->next;
    }
    }
  lf_indent (file, -1);
  lf_indent (file, -1);
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
 
 
 
 
void
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);
  lf_printf (file, "%s(insn_table *) 0x%lx", prefix, (long) isa);
  if (isa != NULL)
  if (isa != NULL)
    {
    {
      lf_indent (file, +1);
      lf_indent (file, +1);
      dump_cache_entries (file, "\n(caches ", isa->caches, ")");
      dump_cache_entries (file, "\n(caches ", isa->caches, ")");
      lf_printf (file, "\n(nr_insns %d)", isa->nr_insns);
      lf_printf (file, "\n(nr_insns %d)", isa->nr_insns);
      lf_printf (file, "\n(max_nr_words %d)", isa->max_nr_words);
      lf_printf (file, "\n(max_nr_words %d)", isa->max_nr_words);
      dump_insn_entries (file, "\n(insns ", isa->insns, ")");
      dump_insn_entries (file, "\n(insns ", isa->insns, ")");
      dump_function_entries (file, "\n(functions ", isa->functions, ")");
      dump_function_entries (file, "\n(functions ", isa->functions, ")");
      dump_insn_entry (file, "\n(illegal_insn ", isa->illegal_insn, ")");
      dump_insn_entry (file, "\n(illegal_insn ", isa->illegal_insn, ")");
      dump_model_table (file, "\n(model ", isa->model, ")");
      dump_model_table (file, "\n(model ", isa->model, ")");
      dump_filter (file, "\n(flags ", isa->flags, ")");
      dump_filter (file, "\n(flags ", isa->flags, ")");
      dump_filter (file, "\n(options ", isa->options, ")");
      dump_filter (file, "\n(options ", isa->options, ")");
      lf_indent (file, -1);
      lf_indent (file, -1);
    }
    }
  lf_printf (file, "%s", suffix);
  lf_printf (file, "%s", suffix);
}
}
 
 
#ifdef MAIN
#ifdef MAIN
 
 
igen_options options;
igen_options options;
 
 
int
int
main (int argc, char **argv)
main (int argc, char **argv)
{
{
  insn_table *isa;
  insn_table *isa;
  lf *l;
  lf *l;
 
 
  INIT_OPTIONS (options);
  INIT_OPTIONS (options);
 
 
  if (argc == 3)
  if (argc == 3)
    filter_parse (&options.flags_filter, argv[2]);
    filter_parse (&options.flags_filter, argv[2]);
  else if (argc != 2)
  else if (argc != 2)
    error (NULL, "Usage: insn <insn-table> [ <filter-in> ]\n");
    error (NULL, "Usage: insn <insn-table> [ <filter-in> ]\n");
 
 
  isa = load_insn_table (argv[1], NULL);
  isa = load_insn_table (argv[1], NULL);
  l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn");
  l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-ld-insn");
  dump_insn_table (l, "(isa ", isa, ")\n");
  dump_insn_table (l, "(isa ", isa, ")\n");
 
 
  return 0;
  return 0;
}
}
 
 
#endif
#endif
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.