and being made more generic.
--- /dev/null
+#
+# 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:
+#
--- /dev/null
+/* 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
--- /dev/null
+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])
--- /dev/null
+/* 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
--- /dev/null
+/* 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);
+
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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);
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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);
--- /dev/null
+/* 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);
--- /dev/null
+/* 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");
+}
+
--- /dev/null
+/* 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);
--- /dev/null
+/* 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);
+
--- /dev/null
+/* 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);
+
--- /dev/null
+/* 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
--- /dev/null
+/* 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);
--- /dev/null
+/* 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
--- /dev/null
+/* 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);
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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);