Instruction decode generator taken from the PowerPC simulator
authorAndrew Cagney <cagney@redhat.com>
Fri, 21 Feb 1997 02:49:21 +0000 (02:49 +0000)
committerAndrew Cagney <cagney@redhat.com>
Fri, 21 Feb 1997 02:49:21 +0000 (02:49 +0000)
and being made more generic.

21 files changed:
sim/igen/Makefile.in [new file with mode: 0644]
sim/igen/config.in [new file with mode: 0644]
sim/igen/configure.in [new file with mode: 0644]
sim/igen/filter.c [new file with mode: 0644]
sim/igen/filter.h [new file with mode: 0644]
sim/igen/filter_host.c [new file with mode: 0644]
sim/igen/filter_host.h [new file with mode: 0644]
sim/igen/gen-engine.h [new file with mode: 0644]
sim/igen/gen-icache.h [new file with mode: 0644]
sim/igen/gen-idecode.h [new file with mode: 0644]
sim/igen/gen-itable.h [new file with mode: 0644]
sim/igen/gen-model.c [new file with mode: 0644]
sim/igen/gen-model.h [new file with mode: 0644]
sim/igen/gen-semantics.h [new file with mode: 0644]
sim/igen/gen-support.h [new file with mode: 0644]
sim/igen/ld-cache.c [new file with mode: 0644]
sim/igen/ld-cache.h [new file with mode: 0644]
sim/igen/ld-decode.c [new file with mode: 0644]
sim/igen/ld-decode.h [new file with mode: 0644]
sim/igen/misc.c [new file with mode: 0644]
sim/igen/misc.h [new file with mode: 0644]

diff --git a/sim/igen/Makefile.in b/sim/igen/Makefile.in
new file mode 100644 (file)
index 0000000..5c64c3b
--- /dev/null
@@ -0,0 +1,175 @@
+#
+#   This file is part of the program psim.
+#
+#   Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
+#   Copyright (C) 1997, Free Software Foundation, Inc.
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   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.
+#
+
+default: all
+
+VPATH = @srcdir@
+srcdir = @srcdir@
+srcroot = $(srcdir)/../..
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+host_alias = @host_alias@
+target_alias = @target_alias@
+program_transform_name = @program_transform_name@
+bindir = @bindir@
+libdir = @libdir@
+tooldir = $(libdir)/$(target_alias)
+
+datadir = @datadir@
+mandir = @mandir@
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = @infodir@
+includedir = @includedir@
+
+SHELL = /bin/sh
+
+INSTALL = $(srcroot)/install.sh -c
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
+INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1
+
+AR = @AR@
+AR_FLAGS = rc
+CC = @CC@
+CFLAGS = @CFLAGS@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+BISON = bison
+MAKEINFO = makeinfo
+RANLIB = @RANLIB@
+
+STD_CFLAGS     = $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(WARNING_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES)
+NOWARN_CFLAGS  = $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES)
+BUILD_CFLAGS   = -g -O $(INCLUDES) $(WARNING_CFLAGS)
+
+BUILD_LDFLAGS  =
+
+.NOEXPORT:
+MAKEOVERRIDES=
+
+LIB_INCLUDES   = -I$(srcdir)/../../include
+INCLUDES       = -I. -I$(srcdir) $(LIB_INCLUDES)
+
+LIBIBERTY_LIB  = ../../libiberty/libiberty.a
+
+
+IGENLIB= libigen.a
+
+all:   igen $(IGENLIB)
+
+.c.o:
+       $(CC_FOR_BUILD) -c $(STD_CFLAGS) $<
+
+filter_filename.o: filter_filename.c filter_filename.h config.h ppc-config.h
+
+igen: igen.o $(IGENLIB)
+       $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o igen igen.o $(IGENLIB) $(LIBIBERTY_LIB)
+
+IGEN_OBJS=\
+       table.o \
+       lf.o misc.o \
+       filter_host.o \
+       ld-decode.o \
+       ld-cache.o \
+       filter.o \
+       ld-insn.o \
+       gen-model.o \
+       gen-itable.o \
+       gen-icache.o \
+       gen-semantics.o \
+       gen-idecode.o \
+       gen-support.o \
+       gen-engine.o
+
+igen.o: igen.c misc.h filter_host.h lf.h table.h ld-decode.h ld-cache.h ld-insn.h filter.h gen-model.h gen-itable.h gen-icache.h gen-idecode.h gen-engine.h gen-semantics.h gen-support.h igen.h 
+       $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/igen.c
+
+$(IGENLIB): $(IGEN_OBJS)
+       rm -f $(IGENLIB)
+       $(AR) $(AR_FLAGS) $(IGENLIB) $(IGEN_OBJS)
+       $(RANLIB) $(IGENLIB)
+
+
+tmp-filter: filter.c misc.h misc.o
+       $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-filter -DMAIN $(srcdir)/filter.c misc.o $(BUILD_LIBS)
+
+tmp-ld-decode: ld-decode.o misc.o lf.o table.o filter_host.o 
+       $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-ld-decode -DMAIN $(srcdir)/ld-decode.c misc.o lf.o table.o filter_host.o $(BUILD_LIBS)
+
+tmp-ld-cache: ld-cache.o misc.o lf.o table.o filter_host.o 
+       $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-ld-cache -DMAIN $(srcdir)/ld-cache.c misc.o lf.o table.o filter_host.o $(BUILD_LIBS)
+
+tmp-ld-insn: ld-insn.o misc.o lf.o table.o ld-decode.o filter_host.o filter.o
+       $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-ld-insn -DMAIN $(srcdir)/ld-insn.c misc.o lf.o table.o ld-decode.o filter_host.o filter.o $(BUILD_LIBS)
+
+filter_host.o: filter_host.c filter_host.h
+table.o: table.c misc.h filter_host.h lf.h table.h
+lf.o: lf.c misc.h filter_host.h lf.h
+filter.o: filter.c misc.h lf.h table.h filter.h
+ld-decode.o: ld-decode.c misc.h lf.h table.h ld-decode.h
+ld-cache.o: ld-cache.c misc.h lf.h table.h ld-cache.h
+ld-insn.o: ld-insn.c misc.h lf.h table.h ld-insn.h ld-decode.h igen.h
+gen-model.o: gen-model.c misc.h lf.h table.h gen-model.h ld-decode.h igen.h ld-insn.h
+gen-itable.o: gen-itable.c misc.h lf.h table.h gen-itable.h ld-decode.h igen.h ld-insn.h igen.h
+gen-icache.o: gen-icache.c misc.h lf.h table.h gen-icache.h ld-decode.h igen.h ld-insn.h gen-semantics.h gen-idecode.h
+gen-semantics.o: gen-semantics.c misc.h lf.h table.h gen-semantics.h ld-decode.h igen.h ld-insn.h
+gen-idecode.o: gen-idecode.c misc.h lf.h table.h gen-idecode.h gen-icache.h gen-semantics.h ld-decode.h igen.h ld-insn.h 
+gen-engine.o: gen-engine.c misc.h lf.h table.h gen-idecode.h gen-engine.h gen-icache.h gen-semantics.h ld-decode.h igen.h ld-insn.h 
+gen-support.o: gen-support.c misc.h lf.h table.h gen-support.h ld-decode.h igen.h ld-insn.h
+misc.o: misc.c misc.h filter_host.h
+
+
+tags etags: TAGS
+
+TAGS:
+       etags $(srcdir)/*.h $(srcdir)/*.c
+
+clean mostlyclean:
+       rm -f tmp-* *.[oasi] core igen
+
+distclean realclean: clean
+       rm -f TAGS Makefile config.cache config.status config.h defines.h stamp-h config.log
+
+maintainer-clean: distclean
+       rm -f *~ *.log ppc-config.h core *.core
+
+Makefile: Makefile.in config.status
+       CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
+
+config.h: stamp-h ; @true
+stamp-h: config.in config.status
+       CONFIG_FILES= CONFIG_HEADERS=config.h:config.in $(SHELL) ./config.status
+
+config.status: configure
+       $(SHELL) ./config.status --recheck
+
+install:
+#
diff --git a/sim/igen/config.in b/sim/igen/config.in
new file mode 100644 (file)
index 0000000..4fcf519
--- /dev/null
@@ -0,0 +1,31 @@
+/* config.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if you have the <dirent.h> header file.  */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <ndir.h> header file.  */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <stdlib.h> header file.  */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file.  */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/dir.h> header file.  */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/ndir.h> header file.  */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/stat.h> header file.  */
+#undef HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/types.h> header file.  */
+#undef HAVE_SYS_TYPES_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
diff --git a/sim/igen/configure.in b/sim/igen/configure.in
new file mode 100644 (file)
index 0000000..0e203d3
--- /dev/null
@@ -0,0 +1,34 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.5)dnl
+AC_INIT(Makefile.in)
+
+AC_PROG_INSTALL
+AC_PROG_CC
+
+# Put a plausible default for CC_FOR_BUILD in Makefile.
+if test "x$cross_compiling" = "xno"; then
+  CC_FOR_BUILD='$(CC)'
+else
+  CC_FOR_BUILD=gcc
+fi
+
+
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
+AC_CANONICAL_SYSTEM
+AC_ARG_PROGRAM
+
+. ${srcdir}/../../bfd/configure.host
+
+AC_CONFIG_HEADER(config.h:config.in)
+
+AC_CHECK_HEADERS(stdlib.h string.h strings.h sys/stat.h sys/types.h unistd.h)
+AC_HEADER_DIRENT
+
+AC_SUBST(CC_FOR_BUILD)
+AC_SUBST(CFLAGS)
+AR=${AR-ar}
+AC_SUBST(AR)
+AC_PROG_RANLIB
+
+AC_OUTPUT(Makefile,
+[case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac])
diff --git a/sim/igen/filter.c b/sim/igen/filter.c
new file mode 100644 (file)
index 0000000..c901a17
--- /dev/null
@@ -0,0 +1,150 @@
+/*  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.
+    */
+
+
+#include <stdio.h>
+
+#include "config.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#include "misc.h"
+#include "filter.h"
+
+struct _filter {
+  char *flag;
+  filter *next;
+};
+
+
+filter *
+new_filter(const char *filt,
+          filter *filters)
+{
+  while (strlen(filt) > 0) {
+    filter *new_filter;
+    /* break up the filt list */
+    char *end = strchr(filt, ',');
+    char *next;
+    int len;
+    if (end == NULL) {
+      end = strchr(filt, '\0');
+      next = end;
+    }
+    else {
+      next = end + 1;
+    }
+    len = end - filt;
+    /* add to filter list */
+    new_filter = ZALLOC(filter);
+    new_filter->flag = (char*)zalloc(len + 1);
+    strncpy(new_filter->flag, filt, len);
+    new_filter->next = filters;
+    filters = new_filter;
+    filt = next;
+  }
+  return filters;
+}
+
+
+int
+is_filtered_out(const char *flags,
+               filter *filters)
+{
+  while (strlen(flags) > 0) {
+    int present;
+    filter *filt = filters;
+    /* break the string up */
+    char *end = strchr(flags, ',');
+    char *next;
+    int len;
+    if (end == NULL) {
+      end = strchr(flags, '\0');
+      next = end;
+    }
+    else {
+      next = end + 1;
+    }
+    len = end - flags;
+    /* check that it is present */
+    present = 0;
+    filt = filters;
+    while (filt != NULL) {
+      if (strncmp(flags, filt->flag, len) == 0
+         && strlen(filt->flag) == len) {
+       present = 1;
+       break;
+      }
+      filt = filt->next;
+    }
+    if (!present)
+      return 1;
+    flags = next;
+  }
+  return 0;
+}
+
+
+int
+it_is(const char *flag,
+      const char *flags)
+{
+  int flag_len = strlen(flag);
+  while (*flags != '\0') {
+    if (!strncmp(flags, flag, flag_len)
+       && (flags[flag_len] == ',' || flags[flag_len] == '\0'))
+      return 1;
+    while (*flags != ',') {
+      if (*flags == '\0')
+       return 0;
+      flags++;
+    }
+    flags++;
+  }
+  return 0;
+}
+
+
+#ifdef MAIN
+int
+main(int argc, char **argv)
+{
+  filter *filters = NULL;
+  int i;
+  if (argc < 2) {
+    printf("Usage: filter <flags> <filter> ...\n");
+    exit (1);
+  }
+  /* load the filter up */
+  for (i = 2; i < argc; i++) 
+    filters = new_filter(argv[i], filters);
+  if (is_filtered_out(argv[1], filters))
+    printf("fail\n");
+  else
+    printf("pass\n");
+  return 0;
+}
+#endif
diff --git a/sim/igen/filter.h b/sim/igen/filter.h
new file mode 100644 (file)
index 0000000..814f704
--- /dev/null
@@ -0,0 +1,43 @@
+/*  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.
+    */
+
+
+typedef struct _filter filter;
+
+
+/* append the filter onto the end of the list */
+
+extern filter *new_filter
+(const char *filt,
+ filter *filters);
+
+
+/* returns true if the flags are non empty and some are missing from the filter list */
+
+extern int is_filtered_out
+(const char *flags,
+ filter *filters);
+
+/* true if the flag is in the list */
+
+extern int it_is
+(const char *flag,
+ const char *flags);
+
diff --git a/sim/igen/filter_host.c b/sim/igen/filter_host.c
new file mode 100644 (file)
index 0000000..c15fef1
--- /dev/null
@@ -0,0 +1,37 @@
+/*  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.
+    */
+
+#include "config.h"
+#include "filter_host.h"
+
+/* Shorten traces by eliminating the directory component to filenames.  */
+const char *
+filter_filename (const char *filename)
+{
+  const char *p = filename;
+  const char *last = filename;
+  int ch;
+
+  while ((ch = *p++) != '\0' && ch != ':')
+    if (ch == '/')
+      last = p;
+
+  return last;
+}
diff --git a/sim/igen/filter_host.h b/sim/igen/filter_host.h
new file mode 100644 (file)
index 0000000..a60b4f2
--- /dev/null
@@ -0,0 +1,27 @@
+/*  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.
+    */
+
+#ifndef _FILTER_FILENAME_H
+#define _FILTER_FILENAME_H
+
+/* Remove directory part from filename */
+extern const char *
+filter_filename(const char *filename);
+#endif
diff --git a/sim/igen/gen-engine.h b/sim/igen/gen-engine.h
new file mode 100644 (file)
index 0000000..5b97de2
--- /dev/null
@@ -0,0 +1,29 @@
+/*  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.
+    */
+
+extern void gen_engine_h
+(lf *file,
+ insn_table *table,
+ cache_table *cache_rules);
+
+extern void gen_engine_c
+(lf *file,
+ insn_table *table,
+ cache_table *cache_rules);
diff --git a/sim/igen/gen-icache.h b/sim/igen/gen-icache.h
new file mode 100644 (file)
index 0000000..c5ba71f
--- /dev/null
@@ -0,0 +1,68 @@
+/*  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.
+    */
+
+
+
+/* Output code to manipulate the instruction cache: either create it
+   or reference it */
+
+typedef enum {
+  declare_variables,
+  define_variables,
+  undef_variables,
+} icache_decl_type;
+
+typedef enum {
+  do_not_use_icache = 0,
+  get_values_from_icache = 0x1,
+  put_values_in_icache = 0x2,
+  both_values_and_icache = 0x3,
+} icache_body_type;
+
+extern void print_icache_body
+(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ cache_table *cache_rules,
+ icache_decl_type what_to_declare,
+ icache_body_type what_to_do);
+
+
+/* Output an instruction cache decode function */
+
+extern insn_handler print_icache_declaration;
+extern insn_handler print_icache_definition;
+
+
+/* Output an instruction cache support function */
+
+extern function_handler print_icache_internal_function_declaration;
+extern function_handler print_icache_internal_function_definition;
+
+
+/* Output the instruction cache table data structure */
+
+extern void print_icache_struct
+(insn_table *instructions,
+ cache_table *cache_rules,
+ lf *file);
+
+
+/* Output a single instructions decoder */
diff --git a/sim/igen/gen-idecode.h b/sim/igen/gen-idecode.h
new file mode 100644 (file)
index 0000000..f46376b
--- /dev/null
@@ -0,0 +1,40 @@
+/*  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.
+    */
+
+extern void gen_idecode_h
+(lf *file,
+ insn_table *table,
+ cache_table *cache_rules);
+
+extern void gen_idecode_c
+(lf *file,
+ insn_table *table,
+ cache_table *cache_rules);
+
+
+/* Output code to do any final checks on the decoded instruction.
+   This includes things like verifying any on decoded fields have the
+   correct value and checking that (for floating point) floating point
+   hardware isn't disabled */
+
+extern void print_idecode_validate
+(lf *file,
+ insn *instruction,
+ opcode_field *opcodes);
diff --git a/sim/igen/gen-itable.h b/sim/igen/gen-itable.h
new file mode 100644 (file)
index 0000000..341dc67
--- /dev/null
@@ -0,0 +1,28 @@
+/*  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.
+    */
+
+
+extern void gen_itable_h
+(insn_table *table,
+ lf *file);
+
+extern void gen_itable_c
+(insn_table *table,
+ lf *file);
diff --git a/sim/igen/gen-model.c b/sim/igen/gen-model.c
new file mode 100644 (file)
index 0000000..4ec1677
--- /dev/null
@@ -0,0 +1,393 @@
+/*  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.
+    */
+
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+
+#include "filter.h"
+
+#include "ld-decode.h"
+#include "ld-insn.h"
+
+#include "gen-model.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+static void
+model_c_or_h_data(insn_table *table,
+                 lf *file,
+                 table_entry *data)
+{
+  if (data->annex) {
+    table_entry_print_cpp_line_nr(file, data);
+    lf_print__c_code(file, data->annex);
+    lf_print__internal_reference(file);
+    lf_printf(file, "\n");
+  }
+}
+
+static void
+model_c_or_h_function(insn_table *entry,
+                     lf *file,
+                     table_entry *function,
+                     char *prefix)
+{
+  if (function->fields[function_type] == NULL
+      || function->fields[function_type][0] == '\0') {
+    error("Model function type not specified for %s", function->fields[function_name]);
+  }
+  lf_printf(file, "\n");
+  lf_print_function_type(file, function->fields[function_type], prefix, " ");
+  lf_printf(file, "%s\n(%s);\n",
+           function->fields[function_name],
+           function->fields[function_param]);
+  lf_printf(file, "\n");
+}
+
+void 
+gen_model_h(insn_table *table, lf *file)
+{
+  insn *insn_ptr;
+  model *model_ptr;
+  insn *macro;
+  char *name;
+  int model_create_p = 0;
+  int model_init_p = 0;
+  int model_halt_p = 0;
+  int model_mon_info_p = 0;
+  int model_mon_info_free_p = 0;
+
+  for(macro = model_macros; macro; macro = macro->next) {
+    model_c_or_h_data(table, file, macro->file_entry);
+  }
+
+  lf_printf(file, "typedef enum _model_enum {\n");
+  lf_printf(file, "  MODEL_NONE,\n");
+  for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+    lf_printf(file, "  MODEL_%s,\n", model_ptr->name);
+  }
+  lf_printf(file, "  nr_models\n");
+  lf_printf(file, "} model_enum;\n");
+  lf_printf(file, "\n");
+
+  lf_printf(file, "#define DEFAULT_MODEL MODEL_%s\n", (models) ? models->name : "NONE");
+  lf_printf(file, "\n");
+
+  lf_printf(file, "typedef struct _model_data model_data;\n");
+  lf_printf(file, "typedef struct _model_time model_time;\n");
+  lf_printf(file, "\n");
+
+  lf_printf(file, "extern model_enum current_model;\n");
+  lf_printf(file, "extern const char *model_name[ (int)nr_models ];\n");
+  lf_printf(file, "extern const char *const *const model_func_unit_name[ (int)nr_models ];\n");
+  lf_printf(file, "extern const model_time *const model_time_mapping[ (int)nr_models ];\n");
+  lf_printf(file, "\n");
+
+  for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
+    name = insn_ptr->file_entry->fields[function_name];
+    if (strcmp (name, "model_create") == 0)
+      model_create_p = 1;
+    else if (strcmp (name, "model_init") == 0)
+      model_init_p = 1;
+    else if (strcmp (name, "model_halt") == 0)
+      model_halt_p = 1;
+    else if (strcmp (name, "model_mon_info") == 0)
+      model_mon_info_p = 1;
+    else if (strcmp (name, "model_mon_info_free") == 0)
+      model_mon_info_free_p = 1;
+  }
+
+  if (!model_create_p) {
+    lf_print_function_type(file, "model_data *", "INLINE_MODEL", " ");
+    lf_printf(file, "model_create\n");
+    lf_printf(file, "(cpu *processor);\n");
+    lf_printf(file, "\n");
+  }
+
+  if (!model_init_p) {
+    lf_print_function_type(file, "void", "INLINE_MODEL", " ");
+    lf_printf(file, "model_init\n");
+    lf_printf(file, "(model_data *model_ptr);\n");
+    lf_printf(file, "\n");
+  }
+
+  if (!model_halt_p) {
+    lf_print_function_type(file, "void", "INLINE_MODEL", " ");
+    lf_printf(file, "model_halt\n");
+    lf_printf(file, "(model_data *model_ptr);\n");
+    lf_printf(file, "\n");
+  }
+
+  if (!model_mon_info_p) {
+    lf_print_function_type(file, "model_print *", "INLINE_MODEL", " ");
+    lf_printf(file, "model_mon_info\n");
+    lf_printf(file, "(model_data *model_ptr);\n");
+    lf_printf(file, "\n");
+  }
+
+  if (!model_mon_info_free_p) {
+    lf_print_function_type(file, "void", "INLINE_MODEL", " ");
+    lf_printf(file, "model_mon_info_free\n");
+    lf_printf(file, "(model_data *model_ptr,\n");
+    lf_printf(file, " model_print *info_ptr);\n");
+    lf_printf(file, "\n");
+  }
+
+  lf_print_function_type(file, "void", "INLINE_MODEL", " ");
+  lf_printf(file, "model_set\n");
+  lf_printf(file, "(const char *name);\n");
+}
+
+/****************************************************************/
+
+typedef struct _model_c_passed_data model_c_passed_data;
+struct _model_c_passed_data {
+  lf *file;
+  model *model_ptr;
+};
+
+static void
+model_c_insn(insn_table *entry,
+            lf *phony_file,
+            void *data,
+            insn *instruction,
+            int depth)
+{
+  model_c_passed_data *data_ptr = (model_c_passed_data *)data;
+  lf *file = data_ptr->file;
+  char *current_name = data_ptr->model_ptr->printable_name;
+  table_model_entry *model_ptr = instruction->file_entry->model_first;
+
+  while (model_ptr) {
+    if (model_ptr->fields[insn_model_name] == current_name) {
+      lf_printf(file, "  { %-*s },  /* %s */\n",
+               max_model_fields_len,
+               model_ptr->fields[insn_model_fields],
+               instruction->file_entry->fields[insn_name]);
+      return;
+    }
+
+    model_ptr = model_ptr->next;
+  }
+
+  lf_printf(file, "  { %-*s },  /* %s */\n",
+           max_model_fields_len,
+           data_ptr->model_ptr->insn_default,
+           instruction->file_entry->fields[insn_name]);
+}
+
+static void
+model_c_function(insn_table *table,
+                lf *file,
+                table_entry *function,
+                const char *prefix)
+{
+  if (function->fields[function_type] == NULL
+      || function->fields[function_type][0] == '\0') {
+    error("Model function return type not specified for %s", function->fields[function_name]);
+  }
+  else {
+    lf_printf(file, "\n");
+    lf_print_function_type(file, function->fields[function_type], prefix, "\n");
+    lf_printf(file, "%s(%s)\n",
+             function->fields[function_name],
+             function->fields[function_param]);
+  }
+  table_entry_print_cpp_line_nr(file, function);
+  lf_printf(file, "{\n");
+  if (function->annex) {
+    lf_indent(file, +2);
+    lf_print__c_code(file, function->annex);
+    lf_indent(file, -2);
+  }
+  lf_printf(file, "}\n");
+  lf_print__internal_reference(file);
+  lf_printf(file, "\n");
+}
+
+void 
+gen_model_c(insn_table *table, lf *file)
+{
+  insn *insn_ptr;
+  model *model_ptr;
+  char *name;
+  int model_create_p = 0;
+  int model_init_p = 0;
+  int model_halt_p = 0;
+  int model_mon_info_p = 0;
+  int model_mon_info_free_p = 0;
+
+  lf_printf(file, "\n");
+  lf_printf(file, "#include \"cpu.h\"\n");
+  lf_printf(file, "#include \"mon.h\"\n");
+  lf_printf(file, "\n");
+  lf_printf(file, "#ifdef HAVE_STDLIB_H\n");
+  lf_printf(file, "#include <stdlib.h>\n");
+  lf_printf(file, "#endif\n");
+  lf_printf(file, "\n");
+
+  for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_or_h_data(table, file, insn_ptr->file_entry);
+  }
+
+  for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_or_h_function(table, file, insn_ptr->file_entry, "/*h*/STATIC");
+  }
+
+  for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
+  }
+
+  for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_function(table, file, insn_ptr->file_entry, "/*c*/STATIC");
+  }
+
+  for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
+  }
+
+  for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
+    name = insn_ptr->file_entry->fields[function_name];
+    if (strcmp (name, "model_create") == 0)
+      model_create_p = 1;
+    else if (strcmp (name, "model_init") == 0)
+      model_init_p = 1;
+    else if (strcmp (name, "model_halt") == 0)
+      model_halt_p = 1;
+    else if (strcmp (name, "model_mon_info") == 0)
+      model_mon_info_p = 1;
+    else if (strcmp (name, "model_mon_info_free") == 0)
+      model_mon_info_free_p = 1;
+  }
+
+  if (!model_create_p) {
+    lf_print_function_type(file, "model_data *", "INLINE_MODEL", "\n");
+    lf_printf(file, "model_create(cpu *processor)\n");
+    lf_printf(file, "{\n");
+    lf_printf(file, "  return (model_data *)0;\n");
+    lf_printf(file, "}\n");
+    lf_printf(file, "\n");
+  }
+
+  if (!model_init_p) {
+    lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
+    lf_printf(file, "model_init(model_data *model_ptr)\n");
+    lf_printf(file, "{\n");
+    lf_printf(file, "}\n");
+    lf_printf(file, "\n");
+  }
+
+  if (!model_halt_p) {
+    lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
+    lf_printf(file, "model_halt(model_data *model_ptr)\n");
+    lf_printf(file, "{\n");
+    lf_printf(file, "}\n");
+    lf_printf(file, "\n");
+  }
+
+  if (!model_mon_info_p) {
+    lf_print_function_type(file, "model_print *", "INLINE_MODEL", "\n");
+    lf_printf(file, "model_mon_info(model_data *model_ptr)\n");
+    lf_printf(file, "{\n");
+    lf_printf(file, "  return (model_print *)0;\n");
+    lf_printf(file, "}\n");
+    lf_printf(file, "\n");
+  }
+
+  if (!model_mon_info_free_p) {
+    lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
+    lf_printf(file, "model_mon_info_free(model_data *model_ptr,\n");
+    lf_printf(file, "                    model_print *info_ptr)\n");
+    lf_printf(file, "{\n");
+    lf_printf(file, "}\n");
+    lf_printf(file, "\n");
+  }
+
+  lf_printf(file, "/* Insn functional unit info */\n");
+  for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+    model_c_passed_data data;
+
+    lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name);
+    data.file = file;
+    data.model_ptr = model_ptr;
+    insn_table_traverse_insn(table,
+                            NULL, (void *)&data,
+                            model_c_insn);
+
+    lf_printf(file, "};\n");
+    lf_printf(file, "\n");
+    lf_printf(file, "\f\n");
+  }
+
+  lf_printf(file, "#ifndef _INLINE_C_\n");
+  lf_printf(file, "const model_time *const model_time_mapping[ (int)nr_models ] = {\n");
+  lf_printf(file, "  (const model_time *const)0,\n");
+  for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+    lf_printf(file, "  model_time_%s,\n", model_ptr->name);
+  }
+  lf_printf(file, "};\n");
+  lf_printf(file, "#endif\n");
+  lf_printf(file, "\n");
+
+  lf_printf(file, "\f\n");
+  lf_printf(file, "/* map model enumeration into printable string */\n");
+  lf_printf(file, "#ifndef _INLINE_C_\n");
+  lf_printf(file, "const char *model_name[ (int)nr_models ] = {\n");
+  lf_printf(file, "  \"NONE\",\n");
+  for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+    lf_printf(file, "  \"%s\",\n", model_ptr->printable_name);
+  }
+  lf_printf(file, "};\n");
+  lf_printf(file, "#endif\n");
+  lf_printf(file, "\n");
+
+  lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
+  lf_printf(file, "model_set(const char *name)\n");
+  lf_printf(file, "{\n");
+  if (models) {
+    lf_printf(file, "  model_enum model;\n");
+    lf_printf(file, "  for(model = MODEL_%s; model < nr_models; model++) {\n", models->name);
+    lf_printf(file, "    if(strcmp(name, model_name[model]) == 0) {\n");
+    lf_printf(file, "      current_model = model;\n");
+    lf_printf(file, "      return;\n");
+    lf_printf(file, "    }\n");
+    lf_printf(file, "  }\n");
+    lf_printf(file, "\n");
+    lf_printf(file, "  error(\"Unknown model '%%s', Models which are known are:%%s\n\",\n");
+    lf_printf(file, "        name,\n");
+    lf_printf(file, "        \"");
+    for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+      lf_printf(file, "\\n\\t%s", model_ptr->printable_name);
+    }
+    lf_printf(file, "\");\n");
+  } else {
+    lf_printf(file, "  error(\"No models are currently known about\");\n");
+  }
+
+  lf_printf(file, "}\n");
+}
+
diff --git a/sim/igen/gen-model.h b/sim/igen/gen-model.h
new file mode 100644 (file)
index 0000000..b465a75
--- /dev/null
@@ -0,0 +1,30 @@
+/*  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.
+    */
+
+
+
+extern void gen_model_h
+(insn_table *table,
+ lf *file);
+
+
+extern void gen_model_c
+(insn_table *table,
+ lf *file);
diff --git a/sim/igen/gen-semantics.h b/sim/igen/gen-semantics.h
new file mode 100644 (file)
index 0000000..2c25715
--- /dev/null
@@ -0,0 +1,81 @@
+/*  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.
+    */
+
+
+/* Creates the files semantics.[hc].
+
+   The generated file semantics contains functions that implement the
+   operations required to model a single target processor instruction.
+
+   Several different variations on the semantics file can be created:
+
+       o       uncached
+
+               No instruction cache exists.  The semantic function
+               needs to generate any required values locally.
+
+       o       cached - separate cracker and semantic
+
+               Two independant functions are created.  Firstly the
+               function that cracks an instruction entering it into a
+               cache and secondly the semantic function propper that
+               uses the cache.
+
+       o       cached - semantic + cracking semantic
+
+               The function that cracks the instruction and enters
+               all values into the cache also contains a copy of the
+               semantic code (avoiding the need to call both the
+               cracker and the semantic function when there is a
+               cache miss).
+
+   For each of these general forms, several refinements can occure:
+
+       o       do/don't duplicate/expand semantic functions
+
+               As a consequence of decoding an instruction, the
+               decoder, as part of its table may have effectivly made
+               certain of the variable fields in an instruction
+               constant. Separate functions for each of the
+               alternative values for what would have been treated as
+               a variable part can be created.
+
+       o       use cache struct directly.
+
+               When a cracking cache is present, the semantic
+               functions can be generated to either hold intermediate
+               cache values in local variables or always refer to the
+               contents of the cache directly. */
+
+
+
+extern insn_handler print_semantic_declaration;
+extern insn_handler print_semantic_definition;
+
+extern void print_idecode_illegal
+(lf *file,
+ const char *result);
+
+extern void print_semantic_body
+(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ opcode_field *opcodes);
+
diff --git a/sim/igen/gen-support.h b/sim/igen/gen-support.h
new file mode 100644 (file)
index 0000000..70862d7
--- /dev/null
@@ -0,0 +1,29 @@
+/*  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.
+    */
+
+
+extern void gen_support_h
+(insn_table *table,
+ lf *file);
+
+extern void gen_support_c
+(insn_table *table,
+ lf *file);
+
diff --git a/sim/igen/ld-cache.c b/sim/igen/ld-cache.c
new file mode 100644 (file)
index 0000000..e7f119e
--- /dev/null
@@ -0,0 +1,115 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994,1995,1996, 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 "misc.h"
+#include "lf.h"
+#include "table.h"
+#include "ld-cache.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+enum {
+  ca_type,
+  ca_field_name,
+  ca_derived_name,
+  ca_type_def,
+  ca_expression,
+  nr_cache_rule_fields,
+};
+
+static const name_map cache_type_map[] = {
+  { "cache", cache_value },
+  { "compute", compute_value },
+  { "scratch", scratch_value },
+  { NULL, 0 },
+};
+
+
+cache_table *
+load_cache_table(char *file_name,
+                int hi_bit_nr)
+{
+  table *file = table_open(file_name, nr_cache_rule_fields, 0);
+  table_entry *entry;
+  cache_table *table = NULL;
+  cache_table **curr_rule = &table;
+  while ((entry = table_entry_read(file)) != NULL) {
+    cache_table *new_rule = ZALLOC(cache_table);
+    new_rule->type = name2i(entry->fields[ca_type], cache_type_map);
+    new_rule->field_name = entry->fields[ca_field_name];
+    new_rule->derived_name = entry->fields[ca_derived_name];
+    new_rule->type_def = (strlen(entry->fields[ca_type_def])
+                         ? entry->fields[ca_type_def]
+                         : NULL);
+    new_rule->expression = (strlen(entry->fields[ca_expression]) > 0
+                           ? entry->fields[ca_expression]
+                           : NULL);
+    new_rule->file_entry = entry;
+    *curr_rule = new_rule;
+    curr_rule = &new_rule->next;
+  }
+  return table;
+}
+
+
+
+#ifdef MAIN
+
+static void
+dump_cache_rule(cache_table* rule,
+               int indent)
+{
+  dumpf(indent, "((cache_table*)0x%x\n", rule);
+  dumpf(indent, " (type %s)\n", i2name(rule->type, cache_type_map));
+  dumpf(indent, " (field_name \"%s\")\n", rule->field_name);
+  dumpf(indent, " (derived_name \"%s\")\n", rule->derived_name);
+  dumpf(indent, " (type-def \"%s\")\n", rule->type_def);
+  dumpf(indent, " (expression \"%s\")\n", rule->expression);
+  dumpf(indent, " (next 0x%x)\n", rule->next);
+  dumpf(indent, " )\n");
+}
+
+
+static void
+dump_cache_rules(cache_table* rule,
+                int indent)
+{
+  while (rule) {
+    dump_cache_rule(rule, indent);
+    rule = rule->next;
+  }
+}
+
+
+int
+main(int argc, char **argv)
+{
+  cache_table *rules;
+  if (argc != 3)
+    error("Usage: cache <cache-file> <hi-bit-nr>\n");
+  rules = load_cache_table(argv[1], a2i(argv[2]));
+  dump_cache_rules(rules, 0);
+  return 0;
+}
+#endif
diff --git a/sim/igen/ld-cache.h b/sim/igen/ld-cache.h
new file mode 100644 (file)
index 0000000..fe9387b
--- /dev/null
@@ -0,0 +1,81 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994,1995,1996, 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.
+    */
+
+/* Instruction unpacking:
+
+   Once the instruction has been decoded, the register (and other)
+   fields within the instruction need to be extracted.
+
+   The table that follows determines how each field should be treated.
+   Importantly it considers the case where the extracted field is to
+   be used immediatly or stored in an instruction cache.
+
+   <type>
+
+   Indicates what to do with the cache entry.  If a cache is to be
+   used.  SCRATCH and CACHE values are defined when a cache entry is
+   being filled while CACHE and COMPUTE values are defined in the
+   semantic code.
+
+   Zero marks the end of the table.  More importantly 1. indicates
+   that the entry is valid and can be cached. 2. indicates that that
+   the entry is valid but can not be cached.
+
+   <field_name>
+
+   The field name as given in the instruction spec.
+
+   <derived_name>
+
+   A new name for <field_name> once it has been extracted from the
+   instruction (and possibly stored in the instruction cache).
+
+   <type>
+
+   String specifying the storage type for <new_name> (the extracted
+   field>.
+
+   <expression>
+
+   Specifies how to get <new_name> from <old_name>.  If null, old and
+   new name had better be the same. */
+
+
+typedef enum {
+  scratch_value,
+  cache_value,
+  compute_value,
+} cache_rule_type;
+
+typedef struct _cache_table cache_table;
+struct _cache_table {
+  cache_rule_type type;
+  char *field_name;
+  char *derived_name;
+  char *type_def;
+  char *expression;
+  table_entry *file_entry;
+  cache_table *next;
+};
+
+
+extern cache_table *load_cache_table
+(char *file_name,
+ int hi_bit_nr);
diff --git a/sim/igen/ld-decode.c b/sim/igen/ld-decode.c
new file mode 100644 (file)
index 0000000..e0be0c3
--- /dev/null
@@ -0,0 +1,155 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994,1995,1996, 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 the opcode stat structure */
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+#include "ld-decode.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+enum {
+  op_options,
+  op_first,
+  op_last,
+  op_force_first,
+  op_force_last,
+  op_force_expansion,
+  op_special_mask,
+  op_special_value,
+  op_special_constant,
+  nr_decode_fields,
+};
+
+static const name_map decode_type_map[] = {
+  { "normal", normal_decode_rule },
+  { "expand-forced", expand_forced_rule },
+  { "boolean", boolean_rule },
+  { NULL, normal_decode_rule },
+};
+
+static const name_map decode_gen_map[] = {
+  { "array", array_gen },
+  { "switch", switch_gen },
+  { "padded-switch", padded_switch_gen },
+  { "goto-switch", goto_switch_gen },
+  { NULL, -1 },
+};
+
+static const name_map decode_slash_map[] = {
+  { "variable-slash", 0 },
+  { "constant-slash", 1 },
+  { NULL },
+};
+
+
+static decode_gen_type overriding_gen_type = invalid_gen;
+
+void
+force_decode_gen_type(const char *type)
+{
+  overriding_gen_type = name2i(type, decode_gen_map);
+}
+
+
+decode_table *
+load_decode_table(char *file_name,
+                 int hi_bit_nr)
+{
+  table *file = table_open(file_name, nr_decode_fields, 0);
+  table_entry *entry;
+  decode_table *table = NULL;
+  decode_table **curr_rule = &table;
+  while ((entry = table_entry_read(file)) != NULL) {
+    decode_table *new_rule = ZALLOC(decode_table);
+    new_rule->type = name2i(entry->fields[op_options], decode_type_map);
+    new_rule->gen = (overriding_gen_type != invalid_gen
+                    ? overriding_gen_type
+                    : name2i(entry->fields[op_options], decode_gen_map));
+    new_rule->force_slash = name2i(entry->fields[op_options], decode_slash_map);
+    new_rule->first = target_a2i(hi_bit_nr, entry->fields[op_first]);
+    new_rule->last = target_a2i(hi_bit_nr, entry->fields[op_last]);
+    new_rule->force_first = (strlen(entry->fields[op_force_first])
+                            ? target_a2i(hi_bit_nr, entry->fields[op_force_first])
+                            : new_rule->last + 1);
+    new_rule->force_last = (strlen(entry->fields[op_force_last])
+                           ? target_a2i(hi_bit_nr, entry->fields[op_force_last])
+                           : new_rule->first - 1);
+    new_rule->force_expansion = entry->fields[op_force_expansion];
+    new_rule->special_mask = a2i(entry->fields[op_special_mask]);
+    new_rule->special_value = a2i(entry->fields[op_special_value]);
+    new_rule->special_constant = a2i(entry->fields[op_special_constant]);
+    *curr_rule = new_rule;
+    curr_rule = &new_rule->next;
+  }
+  return table;
+}
+
+  
+void
+dump_decode_rule(decode_table *rule,
+                int indent)
+{
+  dumpf(indent, "((decode_table*)%p\n", rule);
+  if (rule) {
+    dumpf(indent, " (type %s)\n", i2name(rule->type, decode_type_map));
+    dumpf(indent, " (gen %s)\n", i2name(rule->gen, decode_gen_map));
+    dumpf(indent, " (force_slash %d)\n", rule->force_slash);
+    dumpf(indent, " (first %d)\n", rule->first);
+    dumpf(indent, " (last %d)\n", rule->last);
+    dumpf(indent, " (force_first %d)\n", rule->force_first);
+    dumpf(indent, " (force_last %d)\n", rule->force_last);
+    dumpf(indent, " (force_expansion \"%s\")\n", rule->force_expansion);
+    dumpf(indent, " (special_mask 0x%x)\n", rule->special_mask);
+    dumpf(indent, " (special_value 0x%x)\n", rule->special_value);
+    dumpf(indent, " (special_constant 0x%x)\n", rule->special_constant);
+    dumpf(indent, " (next 0x%x)\n", rule->next);
+  }
+  dumpf(indent, " )\n");
+}
+
+
+#ifdef MAIN
+
+static void
+dump_decode_rules(decode_table *rule,
+                 int indent)
+{
+  while (rule) {
+    dump_decode_rule(rule, indent);
+    rule = rule->next;
+  }
+}
+
+int
+main(int argc, char **argv)
+{
+  decode_table *rules;
+  if (argc != 3)
+    error("Usage: decode <decode-file> <hi-bit-nr>\n");
+  rules = load_decode_table(argv[1], a2i(argv[2]));
+  dump_decode_rules(rules, 0);
+  return 0;
+}
+#endif
diff --git a/sim/igen/ld-decode.h b/sim/igen/ld-decode.h
new file mode 100644 (file)
index 0000000..de23181
--- /dev/null
@@ -0,0 +1,143 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994,1995,1996, 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.
+    */
+
+/* Instruction decode table:
+
+   <options>:<first>:<last>:<force-first>:<force-last>:<force-expand>:<special>...
+
+
+
+   Ignore the below:
+
+
+   The instruction decode table contains rules that dictate how igen
+   is going to firstly break down the opcode table and secondly
+
+   The table that follows is used by gen to construct a decision tree
+   that can identify each possible instruction.  Gen then outputs this
+   decision tree as (according to config) a table or switch statement
+   as the function idecode.
+
+   In parallel to this, as mentioned above, WITH_EXPANDED_SEMANTICS
+   determines of the semantic functions themselves should be expanded
+   in a similar way.
+
+   <first>
+   <last>
+
+   Range of bits (within the instruction) that should be searched for
+   an instruction field.  Within such ranges, gen looks for opcodes
+   (constants), registers (strings) and reserved bits (slash) and
+   according to the rules that follows includes or excludes them from
+   a possible instruction field.
+
+   <force_first>
+   <force_last>
+
+   If an instruction field was found, enlarge the field size so that
+   it is forced to at least include bits starting from <force_first>
+   (<force_last>).  To stop this occuring, use <force_first> = <last>
+   + 1 and <force_last> = <first> - 1.
+
+   <force_slash>
+
+   Treat `/' fields as a constant instead of variable when looking for
+   an instruction field.
+
+   <force_expansion>
+
+   Treat any contained register (string) fields as constant when
+   determining the instruction field.  For the instruction decode (and
+   controled by IDECODE_EXPAND_SEMANTICS) this forces the expansion of
+   what would otherwize be non constant bits of an instruction.
+
+   <use_switch>
+
+   Should this table be expanded using a switch statement (val 1) and
+   if so, should it be padded with entries so as to force the compiler
+   to generate a jump table (val 2). Or a branch table (val 3).
+
+   <special_mask>
+   <special_value>
+   <special_rule>
+   <special_constant>
+
+   Special rule to fine tune how specific (or groups) of instructions
+   are expanded.  The applicability of the rule is determined by
+
+     <special_mask> != 0 && (instruction> & <special_mask>) == <special_value>
+
+   Where <instruction> is obtained by looking only at constant fields
+   with in an instructions spec.  When determining an expansion, the
+   rule is only considered when a node contains a single instruction.
+   <special_rule> can be any of:
+
+        0: for this instruction, expand by earlier rules
+       1: expand bits <force_low> .. <force_hi> only
+       2: boolean expansion of only zero/non-zero cases
+       3: boolean expansion of equality of special constant
+
+       */
+
+
+typedef enum {
+  normal_decode_rule,
+  expand_forced_rule,
+  boolean_rule,
+  nr_decode_rules
+} decode_special_type;
+
+typedef enum {
+  invalid_gen,
+  array_gen,
+  switch_gen,
+  padded_switch_gen,
+  goto_switch_gen,
+  nr_decode_gen_types,
+} decode_gen_type;
+
+
+typedef struct _decode_table decode_table;
+struct _decode_table {
+  decode_special_type type;
+  decode_gen_type gen;
+  int first;
+  int last;
+  int force_first;
+  int force_last;
+  int force_slash;
+  char *force_expansion;
+  unsigned special_mask;
+  unsigned special_value;
+  unsigned special_constant;
+  decode_table *next;
+};
+
+
+extern void force_decode_gen_type
+(const char *type);
+
+extern decode_table *load_decode_table
+(char *file_name,
+ int hi_bit_nr);
+
+extern void dump_decode_rule
+(decode_table *rule,
+ int indent);
diff --git a/sim/igen/misc.c b/sim/igen/misc.c
new file mode 100644 (file)
index 0000000..660570c
--- /dev/null
@@ -0,0 +1,226 @@
+/*  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.
+    */
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include "config.h"
+#include "misc.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+void
+error (char *msg, ...)
+{
+  va_list ap;
+  va_start(ap, msg);
+  vprintf(msg, ap);
+  va_end(ap);
+  exit (1);
+}
+
+void *
+zalloc(long size)
+{
+  void *memory = malloc(size);
+  if (memory == NULL)
+    error("zalloc failed\n");
+  memset(memory, 0, size);
+  return memory;
+}
+
+void
+dumpf (int indent, char *msg, ...)
+{
+  va_list ap;
+  for (; indent > 0; indent--)
+    printf(" ");
+  va_start(ap, msg);
+  vprintf(msg, ap);
+  va_end(ap);
+}
+
+
+unsigned long long
+a2i(const char *a)
+{
+  int neg = 0;
+  int base = 10;
+  unsigned long long num = 0;
+  int looping;
+
+  while (isspace (*a))
+    a++;
+
+  if (*a == '-') {
+    neg = 1;
+    a++;
+  }
+
+  if (*a == '0') {
+    if (a[1] == 'x' || a[1] == 'X') {
+      a += 2;
+      base = 16;
+    } else if (a[1] == 'b' || a[1] == 'b') {
+      a += 2;
+      base = 2;
+    }
+    else
+      base = 8;
+  }
+
+  looping = 1;
+  while (looping) {
+    int ch = *a++;
+
+    switch (base) {
+    default:
+      looping = 0;
+      break;
+
+    case 2:
+      if (ch >= '0' && ch <= '1') {
+       num = (num * 2) + (ch - '0');
+      } else {
+       looping = 0;
+      }
+      break;
+
+    case 10:
+      if (ch >= '0' && ch <= '9') {
+       num = (num * 10) + (ch - '0');
+      } else {
+       looping = 0;
+      }
+      break;
+
+    case 8:
+      if (ch >= '0' && ch <= '7') {
+       num = (num * 8) + (ch - '0');
+      } else {
+       looping = 0;
+      }
+      break;
+
+    case 16:
+      if (ch >= '0' && ch <= '9') {
+       num = (num * 16) + (ch - '0');
+      } else if (ch >= 'a' && ch <= 'f') {
+       num = (num * 16) + (ch - 'a' + 10);
+      } else if (ch >= 'A' && ch <= 'F') {
+       num = (num * 16) + (ch - 'A' + 10);
+      } else {
+       looping = 0;
+      }
+      break;
+    }
+  }
+
+  if (neg)
+    num = - num;
+
+  return num;
+}
+
+unsigned
+target_a2i(int ms_bit_nr,
+          const char *a)
+{
+  if (ms_bit_nr)
+    return (ms_bit_nr - a2i(a));
+  else
+    return a2i(a);
+}
+
+unsigned
+i2target(int ms_bit_nr,
+        unsigned bit)
+{
+  if (ms_bit_nr)
+    return ms_bit_nr - bit;
+  else
+    return bit;
+}
+
+
+int
+name2i(const char *names,
+       const name_map *map)
+{
+  const name_map *curr;
+  const char *name = names;
+  while (*name != '\0') {
+    /* find our name */
+    char *end = strchr(name, ',');
+    char *next;
+    int len;
+    if (end == NULL) {
+      end = strchr(name, '\0');
+      next = end;
+    }
+    else {
+      next = end + 1;
+    }
+    len = end - name;
+    /* look it up */
+    curr = map;
+    while (curr->name != NULL) {
+      if (strncmp(curr->name, name, len) == 0
+         && strlen(curr->name) == len)
+       return curr->i;
+      curr++;
+    }
+    name = next;
+  }
+  /* nothing found, possibly return a default */
+  curr = map;
+  while (curr->name != NULL)
+    curr++;
+  if (curr->i >= 0)
+    return curr->i;
+  else
+    error("%s contains no valid names\n", names);
+  return 0;
+}
+
+const char *
+i2name(const int i,
+       const name_map *map)
+{
+  while (map->name != NULL) {
+    if (map->i == i)
+      return map->name;
+    map++;
+  }
+  error("map lookup failed for %d\n", i);
+  return NULL;
+}
diff --git a/sim/igen/misc.h b/sim/igen/misc.h
new file mode 100644 (file)
index 0000000..60351b4
--- /dev/null
@@ -0,0 +1,94 @@
+/*  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.
+    */
+
+
+/* Frustrating header junk */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#if !defined (__attribute__) && (!defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7))
+#define __attribute__(arg)
+#endif
+
+
+
+#include "filter_host.h"
+
+extern void error
+(char *msg, ...);
+
+#define ASSERT(EXPRESSION) \
+do { \
+  if (!(EXPRESSION)) { \
+    error("%s:%d: assertion failed - %s\n", \
+         filter_filename (__FILE__), __LINE__, #EXPRESSION); \
+  } \
+} while (0)
+
+#define ZALLOC(TYPE) (TYPE*)zalloc(sizeof(TYPE))
+
+extern void *zalloc
+(long size);
+
+extern void dumpf
+(int indent, char *msg, ...);
+
+extern unsigned target_a2i
+(int ms_bit_nr,
+ const char *a);
+
+extern unsigned i2target
+(int ms_bit_nr,
+ unsigned bit);
+
+extern unsigned long long a2i
+(const char *a);
+
+/* Try looking for name in the map table (returning the corresponding
+   integer value).  If that fails, try converting the name into an
+   integer */
+
+typedef struct _name_map {
+  const char *name;
+  int i;
+} name_map;
+
+extern int name2i
+(const char *name,
+ const name_map *map);
+
+extern const char *i2name
+(const int i,
+ const name_map *map);