Add a simple dissasembler to igen
authorAndrew Cagney <cagney@redhat.com>
Thu, 29 May 1997 07:06:41 +0000 (07:06 +0000)
committerAndrew Cagney <cagney@redhat.com>
Thu, 29 May 1997 07:06:41 +0000 (07:06 +0000)
sim/igen/ChangeLog
sim/igen/igen.c
sim/igen/table.c [new file with mode: 0644]
sim/igen/table.h [new file with mode: 0644]

index b9835de588d49cecea6b4fad6f9fdf3837de9a1e..808f861116716142717f97d53ef66b1948764f63 100644 (file)
@@ -1,3 +1,34 @@
+Thu May 29 10:29:57 1997  Andrew Cagney  <cagney@b1.cygnus.com>
+
+       * lf.c (lf_write): New function write an N character buffer to the
+       file.
+
+       * igen.c (print_itrace): When available, use the assembler to
+       print the insn-trace.
+       (print_itrace_prefix): New function, print first part of call to
+       print_one_insn.
+       (print_itrace_format): New function, print fmt argument for
+       print_one_insn.
+       
+       * table.c (table_entry_read): Save any assembler lines instead of
+       discarding them.
+
+Wed May 28 09:55:29 1997  Andrew Cagney  <cagney@b1.cygnus.com>
+
+       * gen-icache.c (print_icache_body): Process immeds.
+
+       * gen-semantics.c (print_semantic_body): When computing NIA, skip
+       any immed words that follow the instruction word.
+
+       * ld-insn.c (parse_insn_format): Parse immeds appended to an
+       instruction.
+
+       * igen.c (main): Allow any register to be specified as the zero
+       register.
+       (semantic_zero_reg): Global, index to zero register.
+
+       * gen-semantics.c (print_semantic_body): Zero selected register.
+
 Tue May 27 14:12:32 1997  Andrew Cagney  <cagney@b1.cygnus.com>
 
        * igen.h: Stop options and code gen type bit masks overlaping.
index a8475ed77cba82d392e4e57b04b6cb1bf0a46ec5..2354d611cfb52a9ddd65dc0406b9a41f4da4f8c1 100644 (file)
@@ -47,6 +47,7 @@ int insn_bit_size = default_insn_bit_size;
 int insn_specifying_widths = 0;
 const char *global_name_prefix = "";
 const char *global_uname_prefix = "";
+int semantic_zero_reg_nr = 0;
 
 int code = generate_calls;
 
@@ -216,54 +217,264 @@ print_function_name(lf *file,
 
 
 void
-print_my_defines(lf *file,
-                insn_bits *expanded_bits,
-                table_entry *file_entry)
+print_my_defines (lf *file,
+                 insn_bits *expanded_bits,
+                 table_entry *file_entry)
 {
   /* #define MY_INDEX xxxxx */
-  lf_indent_suppress(file);
-  lf_printf(file, "#undef MY_INDEX\n");
-  lf_indent_suppress(file);
-  lf_printf(file, "#define MY_INDEX ");
-  print_function_name(file,
-                      file_entry->fields[insn_name],
-                      NULL,
-                      function_name_prefix_itable);
-  lf_printf(file, "\n");
+  lf_indent_suppress (file);
+  lf_printf (file, "#undef MY_INDEX\n");
+  lf_indent_suppress (file);
+  lf_printf (file, "#define MY_INDEX ");
+  print_function_name (file,
+                      file_entry->fields[insn_name],
+                      NULL,
+                      function_name_prefix_itable);
+  lf_printf (file, "\n");
   /* #define MY_PREFIX xxxxxx */
-  lf_indent_suppress(file);
-  lf_printf(file, "#undef MY_PREFIX\n");
-  lf_indent_suppress(file);
-  lf_printf(file, "#define MY_PREFIX ");
-  print_function_name(file,
-                     file_entry->fields[insn_name],
-                     expanded_bits,
-                     function_name_prefix_none);
-  lf_printf(file, "\n");
+  lf_indent_suppress (file);
+  lf_printf (file, "#undef MY_PREFIX\n");
+  lf_indent_suppress (file);
+  lf_printf (file, "#define MY_PREFIX ");
+  print_function_name (file,
+                      file_entry->fields[insn_name],
+                      expanded_bits,
+                      function_name_prefix_none);
+  lf_printf (file, "\n");
+}
+
+
+static int
+print_itrace_prefix (lf *file,
+                    table_entry *file_entry,
+                    const char *phase_lc)
+{
+  const char *prefix = "trace_one_insn (";
+  int indent = strlen (prefix);
+  lf_printf (file, "%sSD, CPU, %s, TRACE_LINENUM_P (CPU),\n",
+            prefix, (code & generate_with_semantic_delayed_branch) ? "cia.ip" : "cia");
+  lf_indent (file, +indent);
+  lf_printf (file, "itable[MY_INDEX].file,\n");
+  lf_printf (file, "itable[MY_INDEX].line_nr,\n");
+  lf_printf (file, "\"%s\",\n", phase_lc);
+  return indent;
+}
+
+
+static void
+print_itrace_format (lf *file,
+                    table_assembler_entry *assembler)
+{
+  /* pass=1 is fmt string; pass=2 is is arguments */
+  int pass;
+  const char *chp;
+  /* print the format string */
+  for (pass = 1; pass <= 2; pass++)
+    {
+      const char *chp = assembler->format;
+      chp++; /* skip the leading quote */
+      /* prefix the format with the insn `name' */
+      if (pass == 1)
+       {
+         lf_printf (file, "\"%%s - %%s - ");
+       }
+      else
+       {
+         lf_printf (file, ",\n");
+         lf_printf (file, "itable[MY_INDEX].name");
+         lf_printf (file, ",\n");
+         lf_printf (file, "XSTRING(MY_PREFIX)");
+       }
+      /* write out the format/args */
+      while (*chp != '\0')
+       {
+         if (chp[0] == '\\' && (chp[1] == '<' || chp[1] == '>'))
+           {
+             if (pass == 1)
+               lf_putchr (file, chp[1]);
+             chp += 2;
+           }
+         else if (chp[0] == '<' || chp[0] == '%')
+           {
+             /* parse [ "%" ... ] "<" [ func "#" ] param ">" */
+             const char *fmt;
+             const char *func;
+             int strlen_func;
+             const char *param;
+             int strlen_param;
+             /* the "%" ... "<" format */
+             fmt = chp;
+             while (chp[0] != '<' && chp[0] != '\0')
+               chp++;
+             if (chp[0] != '<')
+               error ("%s:%d: Missing `<' after `%%'",
+                      assembler->file_name,
+                      assembler->line_nr);
+             chp++;
+             /* [ "func" # ] OR "param" */
+             func = chp;
+             param = chp;
+             while (chp[0] != '>' && chp[0] != '#' && chp[0] != '\0')
+               chp++;
+             strlen_func = chp - func;
+             if (chp[0] == '#')
+               {
+                 chp++;
+                 param = chp;
+                 while (chp[0] != '>' && chp[0] != '\0')
+                   chp++;
+               }
+             strlen_param = chp - param;
+             if (chp[0] != '>')
+               error ("%s:%d: Missing closing `>' in assembler string",
+                      assembler->file_name,
+                      assembler->line_nr);
+             chp++;
+             /* now process it */
+             if (pass == 2)
+               lf_printf (file, ",\n");
+             if (strncmp (fmt, "<", 1) == 0)
+               /* implicit long int format */
+               {
+                 if (pass == 1)
+                   lf_printf (file, "%%ld");
+                 else
+                   {
+                     lf_printf (file, "(long) ");
+                     lf_write (file, param, strlen_param);
+                   }
+               }
+             else if (strncmp (fmt, "%<", 2) == 0)
+               /* explicit format */
+               {
+                 if (pass == 1)
+                   lf_printf (file, "%%");
+                 else
+                   lf_write (file, param, strlen_param);
+               }
+             else if (strncmp (fmt, "%s<", 3) == 0)
+               /* string format */
+               {
+                 if (pass == 1)
+                   lf_printf (file, "%%s");
+                 else
+                   {
+                     lf_printf (file, "%sstr_", global_name_prefix);
+                     lf_write (file, func, strlen_func);
+                     lf_printf (file, " (_SD, ");
+                     lf_write (file, param, strlen_param);
+                     lf_printf (file, ")");
+                   }
+               }
+             else if (strncmp (fmt, "%lx<", 4) == 0)
+               /* simple hex */
+               {
+                 if (pass == 1)
+                   lf_printf (file, "%%lx");
+                 else
+                   {
+                     lf_printf (file, "(unsigned long) ");
+                     lf_write (file, param, strlen_param);
+                   }
+               }
+             else if (strncmp (fmt, "%08lx<", 6) == 0)
+               /* simple hex */
+               {
+                 if (pass == 1)
+                   lf_printf (file, "%%08lx");
+                 else
+                   {
+                     lf_printf (file, "(unsigned long) ");
+                     lf_write (file, param, strlen_param);
+                   }
+               }
+             else
+               error ("%s:%d: Unknown assembler string format",
+                      assembler->file_name,
+                      assembler->line_nr);
+           }
+         else
+           {
+             if (pass == 1)
+               lf_putchr (file, chp[0]);
+             chp += 1;
+           }
+       }
+    }
+  lf_printf (file, ");\n");
 }
 
 
 void
-print_itrace(lf *file,
-            table_entry *file_entry,
-            int idecode)
+print_itrace (lf *file,
+             table_entry *file_entry,
+             int idecode)
 {
   const char *phase = (idecode) ? "DECODE" : "INSN";
   const char *phase_lc = (idecode) ? "decode" : "insn";
-  lf_printf(file, "\n");
-  lf_indent_suppress(file);
-  lf_printf(file, "#if defined(WITH_TRACE)\n");
-  lf_printf(file, "/* trace the instructions execution if enabled */\n");
-  lf_printf(file, "if (TRACE_%s_P (CPU)) {\n", phase);
-  lf_printf(file, "  trace_one_insn (SD, CPU, %s, TRACE_LINENUM_P (CPU),\n",
-           (code & generate_with_semantic_delayed_branch) ? "cia.ip" : "cia");
-
-  lf_printf(file, "                  itable[MY_INDEX].file, itable[MY_INDEX].line_nr,\n");
-  lf_printf(file, "                  \"%s\", itable[MY_INDEX].name);\n", phase_lc);
-
-  lf_printf(file, "}\n");
-  lf_indent_suppress(file);
-  lf_printf(file, "#endif\n");
+  lf_printf (file, "\n");
+  lf_indent_suppress (file);
+  lf_printf (file, "#if defined (WITH_TRACE)\n");
+  lf_printf (file, "/* trace the instructions execution if enabled */\n");
+  lf_printf (file, "if (TRACE_%s_P (CPU)) {\n", phase);
+  lf_indent (file, +2);
+  if (file_entry->assembler != NULL)
+    {
+      table_assembler_entry *assembler = file_entry->assembler;
+      int is_first = 1;
+      do
+       {
+         if (assembler->condition != NULL)
+           {
+             int indent;
+             lf_printf (file, "%sif (%s)\n",
+                        is_first ? "" : "else ",
+                        assembler->condition);
+             lf_indent (file, +2);
+             indent = print_itrace_prefix (file, file_entry, phase_lc);
+             print_itrace_format (file, assembler);
+             lf_indent (file, -indent);
+             lf_indent (file, -2);
+             if (assembler->next == NULL)
+               error ("%s:%d: Missing final unconditional assembler",
+                      assembler->file_name,
+                      assembler->line_nr);
+           }
+         else
+           {
+             int indent;
+             if (!is_first)
+               {
+                 lf_printf (file, "else\n");
+                 lf_indent (file, +2);
+               }
+             indent = print_itrace_prefix (file, file_entry, phase_lc);
+             print_itrace_format (file, assembler);
+             lf_indent (file, -indent);
+             if (!is_first)
+               lf_indent (file, -2);
+             if (assembler->next != NULL)
+               error ("%s:%d: Unconditional assembler is not last",
+                      assembler->file_name,
+                      assembler->line_nr);
+           }
+         is_first = 0;
+         assembler = assembler->next;
+       }
+      while (assembler != NULL);
+    }
+  else
+    {
+      int indent = print_itrace_prefix (file, file_entry, phase_lc);
+      lf_printf (file, "\"%%s - %%s - ?\",\n");
+      lf_printf (file, "itable[MY_INDEX].name,\n");
+      lf_printf (file, "XSTRING(MY_PREFIX));\n");
+      lf_indent (file, -indent);
+    }
+  lf_indent (file, -2);
+  lf_printf (file, "}\n");
+  lf_indent_suppress (file);
+  lf_printf (file, "#endif\n");
 }
 
 
@@ -453,6 +664,7 @@ main(int argc,
     printf("                      insn-in-icache - save original instruction when cracking\n");
     printf("                      default-nia-minus-one - instead of cia + insn-size\n");
     printf("                      delayed-branch - instead of cia + insn-size\n");
+    printf("                      zero-r<N> - arch assumes GPR(<N>) == 0, keep it that way\n");
     printf("                      conditional-issue - conditionally issue each instruction\n");
     printf("                      validate-slot - perform slot verification as part of decode\n");
     printf("\n");
@@ -560,6 +772,10 @@ main(int argc,
       else if (strcmp(optarg, "conditional-issue") == 0) {
        code |= generate_with_semantic_conditional_issue;
       }
+      else if (strncmp (optarg, "zero-r", strlen ("zero-r")) == 0) {
+       code |= generate_with_semantic_zero_reg;
+       semantic_zero_reg_nr = atoi (optarg + strlen ("zero-r"));
+      }
       else if (strcmp(optarg, "verify-slot") == 0) {
        code |= generate_with_idecode_slot_verification;
       }
diff --git a/sim/igen/table.c b/sim/igen/table.c
new file mode 100644 (file)
index 0000000..461a632
--- /dev/null
@@ -0,0 +1,385 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994-1995,1997 Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+    */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#include "config.h"
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+struct _table {
+  size_t size;
+  char *buffer;
+  char *pos;
+  int nr_fields;
+  int nr_model_fields;
+  int line_nr;
+  char *file_name;
+  int current_file_line_offset;
+  char *current_file_name;
+};
+
+extern table *
+table_open(const char *file_name,
+          int nr_fields,
+          int nr_model_fields)
+{
+  int fd;
+  struct stat stat_buf;
+  table *file;
+
+  /* create a file descriptor */
+  file = ZALLOC(table);
+  ASSERT(file != NULL);
+  file->nr_fields = nr_fields;
+  file->nr_model_fields = nr_model_fields;
+
+  /* save the file name */
+  file->file_name = (char*)zalloc(strlen(file_name) + 1);
+  ASSERT(file->file_name != NULL);
+  strcpy(file->file_name, file_name);
+  file->current_file_name = file->file_name;
+
+  /* open the file */
+  fd = open(file->file_name, O_RDONLY, 0);
+  if (fd < 0) {
+    perror(file->file_name);
+    exit (1);
+  }
+
+  /* determine the size */
+  if (fstat(fd, &stat_buf) < 0) {
+    perror("table_open.fstat");
+    exit(1);
+  }
+  file->size = stat_buf.st_size;
+
+  /* allocate this much memory */
+  file->buffer = (char*)zalloc(file->size+1);
+  ASSERT(file->buffer != NULL);
+  file->pos = file->buffer;
+
+  /* read it in */
+  if (read(fd, file->buffer, file->size) < file->size) {
+    perror(file->file_name);
+    exit(1);
+  }
+  file->buffer[file->size] = '\0';
+
+  /* set the initial line numbering */
+  file->line_nr = 0;
+  file->current_file_line_offset = 0;
+
+  /* done */
+  close(fd);
+  return file;
+}
+
+
+extern table_entry *
+table_entry_read(table *file)
+{
+  int field;
+  table_entry *entry;
+
+  /* skip comments/blanks */
+  while(1) {
+    /* leading white space */
+    while (*file->pos != '\0'
+          && *file->pos != '\n'
+          && isspace(*file->pos))
+      file->pos++;
+    /* cpp line nr directive - # <line-nr> "<file>" */
+    if (file->pos[0] == '#'
+       && file->pos[1] == ' '
+       && isdigit(file->pos[2])) {
+      file->pos += strlen("# ");
+      /* parse the number */
+      file->current_file_line_offset = atoi(file->pos) - file->line_nr - 2;
+      /* skip to the file name */
+      while (file->pos[0] != '0'
+            && file->pos[0] != '"'
+            && file->pos[0] != '\0')
+       file->pos++;
+      if (file->pos[0] != '"') {
+       error("%s:%d: Missing opening quote",
+             file->file_name,
+             file->line_nr);
+      }
+      /* parse the file name */
+      file->pos++;
+      file->current_file_name = file->pos;
+      while (file->pos[0] != '"'
+            && file->pos[0] != '\0')
+       file->pos++;
+      if (file->pos[0] != '"') {
+       error("%s:%d: Missing closing quote",
+             file->file_name,
+             file->line_nr);
+      }
+      file->pos[0] = '\0';
+      file->pos ++;
+      while (file->pos[0] != '\0'
+            && file->pos[0] != '\n')
+       file->pos[0]++;
+      if (file->pos[0] != '\n')
+       error("%s:%d: Missing newline",
+             file->file_name,
+             file->line_nr);
+    }
+    /* comment - leading // or # - skip */
+    else if ((file->pos[0] == '/' && file->pos[1] == '/')
+            || (file->pos[0] == '#')) {
+      do {
+       file->pos++;
+      } while (*file->pos != '\0' && *file->pos != '\n');
+    }
+    /* end of line? */
+    if (*file->pos == '\n') {
+      file->pos++;
+      file->line_nr++;
+    }
+    else
+      break;
+  }
+  if (*file->pos == '\0')
+    return NULL;
+
+  /* create this new entry */
+  entry = (table_entry*)zalloc(sizeof(table_entry)
+                              + (file->nr_fields + 1) * sizeof(char*));
+  ASSERT(entry != NULL);
+  entry->file_name = file->current_file_name;
+  entry->nr_fields = file->nr_fields;
+
+  /* break the line into its colon delimitered fields */
+  for (field = 0; field < file->nr_fields-1; field++) {
+    entry->fields[field] = file->pos;
+    while(*file->pos && *file->pos != ':' && *file->pos != '\n')
+      file->pos++;
+    if (*file->pos == ':') {
+      *file->pos = '\0';
+      file->pos++;
+    }
+  }
+
+  /* any trailing stuff not the last field */
+  ASSERT(field == file->nr_fields-1);
+  entry->fields[field] = file->pos;
+  while (*file->pos && *file->pos != '\n') {
+    file->pos++;
+  }
+  if (*file->pos == '\n') {
+    *file->pos = '\0';
+    file->pos++;
+  }
+  file->line_nr++;
+
+  /* If following lines being with a double quote ("), add them to the
+     list of assembler lines */
+  {
+    table_assembler_entry **current = &entry->assembler;
+    while (*file->pos == '"') {
+      char *tmpchp;
+      const char *format;
+      int strlen_format;
+      const char *condition;
+      int strlen_condition;
+
+      /* skip over the format string */
+      format = file->pos;
+      strlen_format = 0;
+      do {
+       if (file->pos[0] == '\\' && file->pos[1] == '"')
+         file->pos += 2;
+       else
+         file->pos += 1;
+      } while (*file->pos != '\0' && *file->pos != '\n' && *file->pos != '"');
+      if (*file->pos != '"')
+       error ("%s:%d: Missing closing quote in assembler line",
+              file->file_name,
+              file->line_nr);
+      file->pos++;
+      strlen_format = file->pos - format;
+
+      /* skip over the boolean condition */
+      condition = NULL;
+      strlen_condition = 0;
+      if (*file->pos == ':')
+       {
+         file->pos++;
+         while (isspace(*file->pos) && *file->pos != '\0' && *file->pos != '\n')
+           file->pos++;
+         condition = file->pos;
+         while (*file->pos != '\0' && *file->pos != '\n')
+           file->pos++;
+         strlen_condition = file->pos - condition;
+       }
+
+      /* create the new assembler entry */
+      *current = ZALLOC (table_assembler_entry);
+      tmpchp = zalloc (strlen_format + 1);
+      strncpy (tmpchp, format, strlen_format);
+      (*current)->format = tmpchp;
+      (*current)->file_name = file->file_name;
+      (*current)->line_nr = file->line_nr;
+      if (condition != NULL && strlen_condition > 0)
+       {
+         tmpchp = zalloc (strlen_condition + 1);
+         strncpy (tmpchp, condition, strlen_condition);
+         (*current)->condition = tmpchp;
+       }
+      current = &(*current)->next;
+
+      /* end of line? */
+      if (*file->pos != '\n')
+       error ("%s:%d: Missing eoln in assembler line",
+              file->file_name,
+              file->line_nr);
+      file->pos++;
+      file->line_nr++;
+    }
+  }
+
+  /* if following lines begin with a star, add them to the model
+     section.  */
+  while ((file->nr_model_fields > 0) && (*file->pos == '*')) {
+    table_model_entry *model = (table_model_entry*)zalloc(sizeof(table_model_entry)
+                                                         + (file->nr_model_fields + 1) * sizeof(char*));
+    if (entry->model_last)
+      entry->model_last->next = model;
+    else
+      entry->model_first = model;
+    entry->model_last = model;
+
+    /* break the line into its colon delimitered fields */
+    file->pos++;
+    for (field = 0; field < file->nr_model_fields-1; field++) {
+      model->fields[field] = file->pos;
+      while(*file->pos && *file->pos != ':' && *file->pos != '\n')
+       file->pos++;
+      if (*file->pos == ':') {
+       *file->pos = '\0';
+       file->pos++;
+      }
+    }
+
+    /* any trailing stuff not the last field */
+    ASSERT(field == file->nr_model_fields-1);
+    model->fields[field] = file->pos;
+    while (*file->pos && *file->pos != '\n') {
+      file->pos++;
+    }
+    if (*file->pos == '\n') {
+      *file->pos = '\0';
+      file->pos++;
+    }
+
+    file->line_nr++;
+    model->line_nr = file->current_file_line_offset + file->line_nr;
+  }
+
+  entry->line_nr = file->current_file_line_offset + file->line_nr;
+
+  /* if following lines are tab indented, put in the annex */
+  if (*file->pos == '\t') {
+    entry->annex = file->pos;
+    do {
+      do {
+       file->pos++;
+      } while (*file->pos != '\0' && *file->pos != '\n');
+      if (*file->pos == '\n') {
+       char *save_pos = ++file->pos;
+       int extra_lines = 0;
+       file->line_nr++;
+       /* Allow tab indented to have blank lines */
+       while (*save_pos == '\n') {
+         save_pos++;
+         extra_lines++;
+       }
+       if (*save_pos == '\t') {
+         file->pos = save_pos;
+         file->line_nr += extra_lines;
+       }
+      }
+    } while (*file->pos != '\0' && *file->pos == '\t');
+    if (file->pos[-1] == '\n')
+      file->pos[-1] = '\0';
+  }
+  else
+    entry->annex = NULL;
+
+  /* return it */
+  return entry;
+
+}
+
+
+extern void
+dump_table_entry(table_entry *entry,
+                int indent)
+{
+  printf("(table_entry*)%p\n", entry);
+
+  if (entry != NULL) {
+    int field;
+    char sep;
+
+    sep = ' ';
+    dumpf(indent, "(fields");
+    for (field = 0; field < entry->nr_fields; field++) {
+      printf("%c%s", sep, entry->fields[field]);
+      sep = ':';
+    }
+    printf(")\n");
+
+    dumpf(indent, "(line_nr %d)\n", entry->line_nr);
+
+    dumpf(indent, "(file_name %s)\n", entry->file_name);
+
+    dumpf(indent, "(annex\n%s\n", entry->annex);
+    dumpf(indent, " )\n");
+
+  }
+}
+
+
+extern void
+table_entry_print_cpp_line_nr(lf *file,
+                             table_entry *entry)
+{
+  lf_print__external_reference(file, entry->line_nr, entry->file_name);
+}
+
+
diff --git a/sim/igen/table.h b/sim/igen/table.h
new file mode 100644 (file)
index 0000000..6b3f6e7
--- /dev/null
@@ -0,0 +1,70 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+    */
+
+
+/* load a table into memory */
+
+typedef struct _table table;
+
+typedef struct _table_model_entry table_model_entry;
+struct _table_model_entry {
+  table_model_entry *next;
+  int line_nr;
+  int nr_fields;
+  char *fields[0];     /* User defined */
+};
+
+typedef struct _table_assembler_entry table_assembler_entry;
+struct _table_assembler_entry {
+  const char *format;
+  const char *condition;
+  const char *file_name;
+  int line_nr;
+  table_assembler_entry *next;
+};
+
+typedef struct _table_entry table_entry;
+struct _table_entry {
+  int line_nr;
+  int nr_fields;
+  char *file_name;
+  table_assembler_entry *assembler;
+  table_model_entry *model_first;
+  table_model_entry *model_last;
+  char *annex;
+  char *fields[0];      /* User defined */
+};
+
+
+extern table *table_open
+(const char *file_name,
+ int max_nr_fields,
+ int max_nr_model_fields);
+
+extern table_entry *table_entry_read
+(table *file);
+
+extern void dump_table_entry
+(table_entry *entry,
+ int indent);
+
+extern void table_entry_print_cpp_line_nr
+(lf *file,
+ table_entry *entry);