[rtems-tools commit] Add tools/5 patches
Sebastian Huber
sebh at rtems.org
Thu Nov 9 08:41:50 UTC 2017
Module: rtems-tools
Branch: master
Commit: 469e3623303aa97be6cbbc7e27058c1ae232f8aa
Changeset: http://git.rtems.org/rtems-tools/commit/?id=469e3623303aa97be6cbbc7e27058c1ae232f8aa
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Thu Nov 9 09:41:34 2017 +0100
Add tools/5 patches
Update #3220.
---
tools/5/gdb/gdb-7.11-erc32-common-run.diff | 472 ++
tools/5/gdb/gdb-7.11-erc32-endian-fix.diff | 13 +
tools/5/gdb/gdb-7.11-erc32-printf_filtered.diff | 1103 ++++
tools/5/gdb/gdb-7.11-sis-leon2-leon3.diff | 7496 +++++++++++++++++++++++
tools/5/gdb/patch-gdb-python-python-config.py | 11 +
5 files changed, 9095 insertions(+)
diff --git a/tools/5/gdb/gdb-7.11-erc32-common-run.diff b/tools/5/gdb/gdb-7.11-erc32-common-run.diff
new file mode 100644
index 0000000..e59cd78
--- /dev/null
+++ b/tools/5/gdb/gdb-7.11-erc32-common-run.diff
@@ -0,0 +1,472 @@
+diff -rNuw gdb-7.11.orig2/sim/erc32/Makefile.in gdb-7.11/sim/erc32/Makefile.in
+--- gdb-7.11.orig2/sim/erc32/Makefile.in 2016-03-16 14:20:34.556597040 +1100
++++ gdb-7.11/sim/erc32/Makefile.in 2016-03-16 14:21:45.736598841 +1100
+@@ -22,7 +22,7 @@
+ READLINE_LIB = @READLINE@
+
+ SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o
+-SIM_RUN_OBJS = sis.o
++SIM_RUN_OBJS = run.o
+ SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
+ SIM_EXTRA_ALL = sis
+ SIM_EXTRA_INSTALL = install-sis
+@@ -56,4 +56,3 @@
+ srcdir=. ; export srcdir ; \
+ else true ; fi ; \
+ (cd $${srcdir}; autoconf --localdir=../common)
+-
+diff -rNuw gdb-7.11.orig2/sim/erc32/run.c gdb-7.11/sim/erc32/run.c
+--- gdb-7.11.orig2/sim/erc32/run.c 1970-01-01 10:00:00.000000000 +1000
++++ gdb-7.11/sim/erc32/run.c 2016-03-16 14:21:21.556598229 +1100
+@@ -0,0 +1,354 @@
++/* run front end support for all the simulators.
++ Copyright (C) 1992-2015 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 3 of the License, or
++(at your option) any later version.
++
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with this program. If not, see <http://www.gnu.org/licenses/>. */
++
++/* Steve Chamberlain sac at cygnus.com,
++ and others at Cygnus. */
++
++#include "config.h"
++
++#include <signal.h>
++#include <stdio.h>
++#ifdef __STDC__
++#include <stdarg.h>
++#else
++#include <varargs.h>
++#endif
++
++#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
++
++#include "libiberty.h"
++#include "bfd.h"
++#include "gdb/callback.h"
++#include "gdb/remote-sim.h"
++#include "ansidecl.h"
++#include "run-sim.h"
++#include "version.h"
++
++static void usage (int help);
++static void print_version (void);
++extern int optind;
++extern char *optarg;
++
++extern host_callback default_callback;
++
++static char *myname;
++
++extern int getopt ();
++
++#ifdef NEED_UI_LOOP_HOOK
++/* Gdb foolery. This is only needed for gdb using a gui. */
++int (*deprecated_ui_loop_hook) (int signo);
++#endif
++
++static SIM_DESC sd;
++
++static RETSIGTYPE
++cntrl_c (int sig ATTRIBUTE_UNUSED)
++{
++ if (! sim_stop (sd))
++ {
++ fprintf (stderr, "Quit!\n");
++ exit (1);
++ }
++}
++
++int
++main (ac, av)
++ int ac;
++ char **av;
++{
++ RETSIGTYPE (*prev_sigint) ();
++ bfd *abfd;
++ int i;
++ int verbose = 0;
++ int trace = 0;
++#ifdef SIM_HAVE_ENVIRONMENT
++ int operating_p = 0;
++#endif
++ char *name;
++ static char *no_args[4];
++ char **sim_argv = &no_args[0];
++ char **prog_args;
++ enum sim_stop reason;
++ int sigrc;
++
++ myname = av[0] + strlen (av[0]);
++ while (myname > av[0] && myname[-1] != '/')
++ --myname;
++
++ /* The first element of sim_open's argv is the program name. */
++ no_args[0] = av[0];
++#ifdef SIM_HAVE_BIENDIAN
++ no_args[1] = "-E";
++ no_args[2] = "set-later";
++#endif
++
++ /* FIXME: This is currently being migrated into sim_open.
++ Simulators that use functions such as sim_size() still require
++ this. */
++ default_callback.init (&default_callback);
++ //sim_set_callbacks (&default_callback);
++
++#ifdef SIM_TARGET_SWITCHES
++ ac = sim_target_parse_command_line (ac, av);
++#endif
++
++ for (i = 1; av[i]; ++i)
++ {
++ if (strcmp (av[i], "--help") == 0)
++ {
++ usage (1);
++ }
++ else if (strcmp (av[i], "--version") == 0)
++ {
++ print_version ();
++ return 0;
++ }
++ }
++
++ /* FIXME: This is currently being rewritten to have each simulator
++ do all argv processing. */
++
++ while ((i = getopt (ac, av, "a:c:m:op:s:tv")) != EOF)
++ switch (i)
++ {
++ case 'a':
++ /* FIXME: Temporary hack. */
++ {
++ int len = strlen (av[0]) + strlen (optarg);
++ char *argbuf = (char *) alloca (len + 2 + 50);
++ sprintf (argbuf, "%s %s", av[0], optarg);
++#ifdef SIM_HAVE_BIENDIAN
++ /* The desired endianness must be passed to sim_open.
++ The value for "set-later" is set when we know what it is.
++ -E support isn't yet part of the published interface. */
++ strcat (argbuf, " -E set-later");
++#endif
++ sim_argv = buildargv (argbuf);
++ }
++ break;
++#ifdef SIM_HAVE_SIMCACHE
++ case 'c':
++ sim_set_simcache_size (atoi (optarg));
++ break;
++#endif
++ case 'm':
++ /* FIXME: Rename to sim_set_mem_size. */
++ //sim_size (atoi (optarg));
++ break;
++#ifdef SIM_HAVE_ENVIRONMENT
++ case 'o':
++ /* Operating enironment where any signals are delivered to the
++ target. */
++ operating_p = 1;
++ break;
++#endif
++#ifdef SIM_HAVE_PROFILE
++ case 'p':
++ sim_set_profile (atoi (optarg));
++ break;
++ case 's':
++ sim_set_profile_size (atoi (optarg));
++ break;
++#endif
++ case 't':
++ trace = 1;
++ break;
++ case 'v':
++ /* Things that are printed with -v are the kinds of things that
++ gcc -v prints. This is not meant to include detailed tracing
++ or debugging information, just summaries. */
++ verbose = 1;
++ /* sim_set_verbose (1); */
++ break;
++ /* FIXME: Quick hack, to be replaced by more general facility. */
++ default:
++ usage (0);
++ }
++
++ ac -= optind;
++ av += optind;
++ if (ac <= 0)
++ usage (0);
++
++ name = *av;
++ prog_args = av;
++
++ if (verbose)
++ {
++ printf ("%s %s\n", myname, name);
++ }
++
++ abfd = bfd_openr (name, 0);
++ if (!abfd)
++ {
++ fprintf (stderr, "%s: can't open %s: %s\n",
++ myname, name, bfd_errmsg (bfd_get_error ()));
++ exit (1);
++ }
++
++ if (!bfd_check_format (abfd, bfd_object))
++ {
++ fprintf (stderr, "%s: can't load %s: %s\n",
++ myname, name, bfd_errmsg (bfd_get_error ()));
++ exit (1);
++ }
++
++#ifdef SIM_HAVE_BIENDIAN
++ /* The endianness must be passed to sim_open because one may wish to
++ examine/set registers before calling sim_load [which is the other
++ place where one can determine endianness]. We previously passed the
++ endianness via global `target_byte_order' but that's not a clean
++ interface. */
++ for (i = 1; sim_argv[i + 1] != NULL; ++i)
++ continue;
++ if (bfd_big_endian (abfd))
++ sim_argv[i] = "big";
++ else
++ sim_argv[i] = "little";
++#endif
++
++ /* Ensure that any run-time initialisation that needs to be
++ performed by the simulator can occur. */
++ sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, abfd, sim_argv);
++ if (sd == 0)
++ exit (1);
++
++ if (sim_load (sd, name, abfd, 0) == SIM_RC_FAIL)
++ exit (1);
++
++ if (sim_create_inferior (sd, abfd, prog_args, NULL) == SIM_RC_FAIL)
++ exit (1);
++
++#ifdef SIM_HAVE_ENVIRONMENT
++ /* NOTE: An old simulator supporting the operating environment MUST
++ provide sim_set_trace() and not sim_trace(). That way
++ sim_stop_reason() can be used to determine any stop reason. */
++ if (trace)
++ sim_set_trace ();
++ sigrc = 0;
++ do
++ {
++ prev_sigint = signal (SIGINT, cntrl_c);
++ sim_resume (sd, 0, sigrc);
++ signal (SIGINT, prev_sigint);
++ sim_stop_reason (sd, &reason, &sigrc);
++ }
++ while (operating_p && reason == sim_stopped && sigrc != SIGINT);
++#else
++ if (trace)
++ {
++ int done = 0;
++ prev_sigint = signal (SIGINT, cntrl_c);
++ while (!done)
++ {
++ // done = sim_trace (sd);
++ }
++ signal (SIGINT, prev_sigint);
++ sim_stop_reason (sd, &reason, &sigrc);
++ }
++ else
++ {
++ prev_sigint = signal (SIGINT, cntrl_c);
++ sigrc = 0;
++ sim_resume (sd, 0, sigrc);
++ signal (SIGINT, prev_sigint);
++ sim_stop_reason (sd, &reason, &sigrc);
++ }
++#endif
++
++ if (verbose)
++ sim_info (sd, 0);
++ sim_close (sd, 0);
++
++ /* If reason is sim_exited, then sigrc holds the exit code which we want
++ to return. If reason is sim_stopped or sim_signalled, then sigrc holds
++ the signal that the simulator received; we want to return that to
++ indicate failure. */
++
++ /* Why did we stop? */
++ switch (reason)
++ {
++ case sim_signalled:
++ case sim_stopped:
++ if (sigrc != 0)
++ fprintf (stderr, "program stopped with signal %d.\n", sigrc);
++ break;
++
++ case sim_exited:
++ break;
++
++ case sim_running:
++ case sim_polling: /* These indicate a serious problem. */
++ abort ();
++ break;
++
++ }
++
++ return sigrc;
++}
++
++static void
++usage (int help)
++{
++ FILE *stream = help ? stdout : stderr;
++
++ fprintf (stream, "Usage: %s [options] program [program args]\n", myname);
++ fprintf (stream, "Options:\n");
++ fprintf (stream, "-a args Pass `args' to simulator.\n");
++#ifdef SIM_HAVE_SIMCACHE
++ fprintf (stream, "-c size Set simulator cache size to `size'.\n");
++#endif
++ fprintf (stream, "-m size Set memory size of simulator, in bytes.\n");
++#ifdef SIM_HAVE_ENVIRONMENT
++ fprintf (stream, "-o Select operating (kernel) environment.\n");
++#endif
++#ifdef SIM_HAVE_PROFILE
++ fprintf (stream, "-p freq Set profiling frequency.\n");
++ fprintf (stream, "-s size Set profiling size.\n");
++#endif
++ fprintf (stream, "-t Perform instruction tracing.\n");
++ fprintf (stream, " Note: Very few simulators support tracing.\n");
++ fprintf (stream, "-v Verbose output.\n");
++ fprintf (stream, "\n");
++ fprintf (stream, "program args Arguments to pass to simulated program.\n");
++ fprintf (stream, " Note: Very few simulators support this.\n");
++#ifdef SIM_TARGET_SWITCHES
++ fprintf (stream, "\nTarget specific options:\n");
++ sim_target_display_usage (help);
++#endif
++
++ if (help && REPORT_BUGS_TO[0])
++ printf ("Report bugs to %s\n", REPORT_BUGS_TO);
++
++ exit (help ? 0 : 1);
++}
++
++static void
++print_version ()
++{
++ printf ("GNU simulator %s%s\n", PKGVERSION, version);
++}
+diff -rNuw gdb-7.11.orig2/sim/erc32/run-sim.h gdb-7.11/sim/erc32/run-sim.h
+--- gdb-7.11.orig2/sim/erc32/run-sim.h 1970-01-01 10:00:00.000000000 +1000
++++ gdb-7.11/sim/erc32/run-sim.h 2016-03-16 14:22:00.512599215 +1100
+@@ -0,0 +1,93 @@
++/* This file defines the part of the interface between the standalone
++ simaulator program - run - and simulator library - libsim.a - that
++ is not used by GDB. The GDB part is described in include/remote-sim.h.
++
++ Copyright 2002-2015 Free Software Foundation, Inc.
++
++ This file is part of GDB.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>. */
++
++#ifndef RUN_SIM_H
++#define RUN_SIM_H
++
++#ifdef SIM_TARGET_SWITCHES
++ /* Parse the command line, extracting any target specific switches
++ before the generic simulator code gets a chance to complain
++ about them. Returns the adjusted value of argc. */
++int sim_target_parse_command_line (int, char **);
++
++ /* Display a list of target specific switches supported by this
++ target. */
++void sim_target_display_usage (int help);
++
++#endif
++
++/* Provide simulator with a default (global) host_callback_struct.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure does not take a SIM_DESC argument as it is
++ used before sim_open. */
++
++void sim_set_callbacks (struct host_callback_struct *);
++
++
++/* Set the size of the simulator memory array.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure does not take a SIM_DESC argument as it is
++ used before sim_open. */
++
++void sim_size (int i);
++
++
++/* Single-step simulator with tracing enabled.
++ THIS PROCEDURE IS DEPRECATED.
++ THIS PROCEDURE IS EVEN MORE DEPRECATED THAN SIM_SET_TRACE
++ GDB and NRUN do not use this interface.
++ This procedure returns: ``0'' indicating that the simulator should
++ be continued using sim_trace() calls; ``1'' indicating that the
++ simulation has finished. */
++
++int sim_trace (SIM_DESC sd);
++
++
++/* Enable tracing.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure returns: ``0'' indicating that the simulator should
++ be continued using sim_trace() calls; ``1'' indicating that the
++ simulation has finished. */
++
++void sim_set_trace (void);
++
++
++/* Configure the size of the profile buffer.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure does not take a SIM_DESC argument as it is
++ used before sim_open. */
++
++void sim_set_profile_size (int n);
++
++
++/* Kill the running program.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure will be replaced as part of the introduction of
++ multi-cpu simulators. */
++
++void sim_kill (SIM_DESC sd);
++
++#endif
diff --git a/tools/5/gdb/gdb-7.11-erc32-endian-fix.diff b/tools/5/gdb/gdb-7.11-erc32-endian-fix.diff
new file mode 100644
index 0000000..1021664
--- /dev/null
+++ b/tools/5/gdb/gdb-7.11-erc32-endian-fix.diff
@@ -0,0 +1,13 @@
+diff -ruw gdb-7.11.orig/sim/erc32/sis.h gdb-7.11/sim/erc32/sis.h
+--- gdb-7.11.orig/sim/erc32/sis.h 2016-03-15 10:24:35.934052479 +1100
++++ gdb-7.11/sim/erc32/sis.h 2016-03-16 13:52:51.988554970 +1100
+@@ -20,7 +20,7 @@
+ #include <sim-config.h>
+ #include <stdint.h>
+
+-#if HOST_BYTE_ORDER == BIG_ENDIAN
++#ifdef WORDS_BIGENDIAN
+ #define HOST_BIG_ENDIAN
+ #define EBT 0
+ #else
+Only in gdb-7.11/sim/erc32: sis.h~
diff --git a/tools/5/gdb/gdb-7.11-erc32-printf_filtered.diff b/tools/5/gdb/gdb-7.11-erc32-printf_filtered.diff
new file mode 100644
index 0000000..96403ff
--- /dev/null
+++ b/tools/5/gdb/gdb-7.11-erc32-printf_filtered.diff
@@ -0,0 +1,1103 @@
+diff -ruw gdb-7.11.orig1/sim/erc32/erc32.c gdb-7.11/sim/erc32/erc32.c
+--- gdb-7.11.orig1/sim/erc32/erc32.c 2016-03-16 14:00:04.632565918 +1100
++++ gdb-7.11/sim/erc32/erc32.c 2016-03-16 14:06:57.604576368 +1100
+@@ -19,6 +19,7 @@
+ /* The control space devices */
+
+ #include "config.h"
++#include <errno.h>
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -36,6 +37,7 @@
+ extern char uart_dev1[], uart_dev2[];
+
+ int dumbio = 0; /* normal, smart, terminal oriented IO by default */
++int tty_setup = 1; /* default setup if not a tty */
+
+ /* MEC registers */
+ #define MEC_START 0x01f80000
+@@ -293,12 +295,15 @@
+
+ extern int ext_irl;
+
++static host_callback *callback;
++
+
+ /* One-time init */
+
+ void
+ init_sim()
+ {
++ callback = sim_callback;
+ port_init();
+ }
+
+@@ -321,12 +326,12 @@
+ sys_reset();
+ mec_ersr = 0x8000;
+ if (sis_verbose)
+- printf("Error manager reset - IU in error mode\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Error manager reset - IU in error mode\n");
+ } else {
+ sys_halt();
+ mec_ersr |= 0x2000;
+ if (sis_verbose)
+- printf("Error manager halt - IU in error mode\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Error manager halt - IU in error mode\n");
+ }
+ } else
+ mec_irq(1);
+@@ -337,12 +342,12 @@
+ sys_reset();
+ mec_ersr = 0x8000;
+ if (sis_verbose)
+- printf("Error manager reset - IU comparison error\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Error manager reset - IU comparison error\n");
+ } else {
+ sys_halt();
+ mec_ersr |= 0x2000;
+ if (sis_verbose)
+- printf("Error manager halt - IU comparison error\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Error manager halt - IU comparison error\n");
+ }
+ } else
+ mec_irq(1);
+@@ -353,12 +358,12 @@
+ sys_reset();
+ mec_ersr = 0x8000;
+ if (sis_verbose)
+- printf("Error manager reset - MEC hardware error\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Error manager reset - MEC hardware error\n");
+ } else {
+ sys_halt();
+ mec_ersr |= 0x2000;
+ if (sis_verbose)
+- printf("Error manager halt - MEC hardware error\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Error manager halt - MEC hardware error\n");
+ }
+ } else
+ mec_irq(1);
+@@ -416,7 +421,7 @@
+ mem_rammask = RAM_MASK;
+ }
+ if (sis_verbose)
+- printf("RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n",
++ (*sim_callback->printf_filtered) (sim_callback, "RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n",
+ mem_ramstart, mem_ramsz >> 10, mem_romsz >> 10);
+ }
+
+@@ -432,7 +437,7 @@
+ }
+ mem_romw_ws = (mec_wcr >> 8) & 0x0f;
+ if (sis_verbose)
+- printf("Waitstates = RAM read: %d, RAM write: %d, ROM read: %d, ROM write: %d\n",
++ (*sim_callback->printf_filtered) (sim_callback, "Waitstates = RAM read: %d, RAM write: %d, ROM read: %d, ROM write: %d\n",
+ mem_ramr_ws, mem_ramw_ws, mem_romr_ws, mem_romw_ws);
+ }
+
+@@ -442,15 +447,15 @@
+ mem_accprot = (mec_wpr[0] | mec_wpr[1]);
+ mem_blockprot = (mec_mcr >> 3) & 1;
+ if (sis_verbose && mem_accprot)
+- printf("Memory block write protection enabled\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Memory block write protection enabled\n");
+ if (mec_mcr & 0x08000) {
+ mec_ersr |= 0x20;
+ decode_ersr();
+ }
+ if (sis_verbose && (mec_mcr & 2))
+- printf("Software reset enabled\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Software reset enabled\n");
+ if (sis_verbose && (mec_mcr & 1))
+- printf("Power-down mode enabled\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Power-down mode enabled\n");
+ }
+
+ /* Flush ports when simulator stops */
+@@ -553,7 +558,7 @@
+ int irq_test;
+
+ if (sis_verbose)
+- printf("interrupt %d acknowledged\n", level);
++ (*sim_callback->printf_filtered) (sim_callback, "interrupt %d acknowledged\n", level);
+ irq_test = mec_tcr & 0x80000;
+ if ((irq_test) && (mec_ifr & (1 << level)))
+ mec_ifr &= ~(1 << level);
+@@ -578,7 +583,7 @@
+ for (i = 15; i > 0; i--) {
+ if (((itmp >> i) & 1) != 0) {
+ if ((sis_verbose) && (i > old_irl))
+- printf("IU irl: %d\n", i);
++ (*sim_callback->printf_filtered) (sim_callback, "IU irl: %d\n", i);
+ ext_irl = i;
+ set_int(i, mec_intack, i);
+ break;
+@@ -753,7 +758,7 @@
+ uint32 data;
+ {
+ if (sis_verbose > 1)
+- printf("MEC write a: %08x, d: %08x\n",addr,data);
++ (*sim_callback->printf_filtered) (sim_callback, "MEC write a: %08x, d: %08x\n",addr,data);
+ switch (addr & 0x0ff) {
+
+ case MEC_MCR:
+@@ -767,7 +772,7 @@
+ sys_reset();
+ mec_ersr = 0x4000;
+ if (sis_verbose)
+- printf(" Software reset issued\n");
++ (*sim_callback->printf_filtered) (sim_callback, " Software reset issued\n");
+ }
+ break;
+
+@@ -782,7 +787,7 @@
+ mec_wpr[0] = (data >> 23) & 0x03;
+ mem_accprot = mec_wpr[0] || mec_wpr[1];
+ if (sis_verbose && mec_wpr[0])
+- printf("Segment 1 memory protection enabled (0x02%06x - 0x02%06x)\n",
++ (*sim_callback->printf_filtered) (sim_callback, "Segment 1 memory protection enabled (0x02%06x - 0x02%06x)\n",
+ mec_ssa[0] << 2, mec_sea[0] << 2);
+ break;
+ case MEC_SEA1: /* 0x24 */
+@@ -795,7 +800,7 @@
+ mec_wpr[1] = (data >> 23) & 0x03;
+ mem_accprot = mec_wpr[0] || mec_wpr[1];
+ if (sis_verbose && mec_wpr[1])
+- printf("Segment 2 memory protection enabled (0x02%06x - 0x02%06x)\n",
++ (*sim_callback->printf_filtered) (sim_callback, "Segment 2 memory protection enabled (0x02%06x - 0x02%06x)\n",
+ mec_ssa[1] << 2, mec_sea[1] << 2);
+ break;
+ case MEC_SEA2: /* 0x2c */
+@@ -909,7 +914,7 @@
+ if (wdog_status == init) {
+ wdog_status = disabled;
+ if (sis_verbose)
+- printf("Watchdog disabled\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Watchdog disabled\n");
+ }
+ break;
+
+@@ -936,10 +941,14 @@
+ {
+ if (dumbio)
+ return; /* do nothing */
+- if (!ifd1)
++ if (ifd1 == 0 && f1open) {
+ tcsetattr(0, TCSANOW, &ioc1);
+- if (!ifd2)
++ tcflush(ifd1, TCIFLUSH);
++ }
++ if (ifd2 == 0 && f1open) {
+ tcsetattr(0, TCSANOW, &ioc2);
++ tcflush(ifd2, TCIFLUSH);
++ }
+ }
+
+ void
+@@ -947,16 +956,18 @@
+ {
+ if (dumbio)
+ return; /* do nothing */
+- if (!ifd1)
++ if (ifd1 == 0 && f1open && tty_setup)
+ tcsetattr(0, TCSANOW, &iocold1);
+- if (!ifd2)
++ if (ifd2 == 0 && f2open && tty_setup)
+ tcsetattr(0, TCSANOW, &iocold2);
+ }
+
+ #define DO_STDIO_READ( _fd_, _buf_, _len_ ) \
+- ( dumbio \
++ ( dumbio || nouartrx \
+ ? (0) /* no bytes read, no delay */ \
+- : read( _fd_, _buf_, _len_ ) )
++ : (_fd_) == 1 && callback ? \
++ callback->read_stdin (callback, _buf_, _len_) : \
++ read( _fd_, _buf_, _len_ ) )
+
+
+ static void
+@@ -976,39 +987,44 @@
+ }
+ if (uart_dev1[0] != 0)
+ if ((fd1 = open(uart_dev1, O_RDWR | O_NONBLOCK)) < 0) {
+- printf("Warning, couldn't open output device %s\n", uart_dev1);
++ (*sim_callback->printf_filtered) (sim_callback, "Warning, couldn't open output device %s\n", uart_dev1);
+ } else {
+ if (sis_verbose)
+- printf("serial port A on %s\n", uart_dev1);
++ (*sim_callback->printf_filtered) (sim_callback, "serial port A on %s\n", uart_dev1);
+ f1in = f1out = fdopen(fd1, "r+");
+ setbuf(f1out, NULL);
+ f1open = 1;
+ }
+ if (f1in) ifd1 = fileno(f1in);
+ if (ifd1 == 0) {
++ if (callback && !callback->isatty(callback, ifd1)) {
++ tty_setup = 0;
++ }
+ if (sis_verbose)
+- printf("serial port A on stdin/stdout\n");
++ (*sim_callback->printf_filtered) (sim_callback, "serial port A on stdin/stdout\n");
+ if (!dumbio) {
+ tcgetattr(ifd1, &ioc1);
++ if (tty_setup) {
+ iocold1 = ioc1;
+ ioc1.c_lflag &= ~(ICANON | ECHO);
+ ioc1.c_cc[VMIN] = 0;
+ ioc1.c_cc[VTIME] = 0;
+ }
++ }
+ f1open = 1;
+ }
+
+ if (f1out) {
+ ofd1 = fileno(f1out);
+- if (!dumbio && ofd1 == 1) setbuf(f1out, NULL);
++ if (!dumbio && tty_setup && ofd1 == 1) setbuf(f1out, NULL);
+ }
+
+ if (uart_dev2[0] != 0)
+ if ((fd2 = open(uart_dev2, O_RDWR | O_NONBLOCK)) < 0) {
+- printf("Warning, couldn't open output device %s\n", uart_dev2);
++ (*sim_callback->printf_filtered) (sim_callback, "Warning, couldn't open output device %s\n", uart_dev2);
+ } else {
+ if (sis_verbose)
+- printf("serial port B on %s\n", uart_dev2);
++ (*sim_callback->printf_filtered) (sim_callback, "serial port B on %s\n", uart_dev2);
+ f2in = f2out = fdopen(fd2, "r+");
+ setbuf(f2out, NULL);
+ f2open = 1;
+@@ -1016,20 +1032,22 @@
+ if (f2in) ifd2 = fileno(f2in);
+ if (ifd2 == 0) {
+ if (sis_verbose)
+- printf("serial port B on stdin/stdout\n");
++ (*sim_callback->printf_filtered) (sim_callback, "serial port B on stdin/stdout\n");
+ if (!dumbio) {
+ tcgetattr(ifd2, &ioc2);
++ if (tty_setup) {
+ iocold2 = ioc2;
+ ioc2.c_lflag &= ~(ICANON | ECHO);
+ ioc2.c_cc[VMIN] = 0;
+ ioc2.c_cc[VTIME] = 0;
+ }
++ }
+ f2open = 1;
+ }
+
+ if (f2out) {
+ ofd2 = fileno(f2out);
+- if (!dumbio && ofd2 == 1) setbuf(f2out, NULL);
++ if (!dumbio && tty_setup && ofd2 == 1) setbuf(f2out, NULL);
+ }
+
+ wnuma = wnumb = 0;
+@@ -1058,6 +1076,9 @@
+ if (f1open) {
+ anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
+ }
++ else {
++ anum = 0;
++ }
+ if (anum > 0) {
+ aind = 0;
+ if ((aind + 1) < anum)
+@@ -1090,6 +1111,9 @@
+ if (f2open) {
+ bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
+ }
++ else {
++ bnum = 0;
++ }
+ if (bnum > 0) {
+ bind = 0;
+ if ((bind + 1) < bnum)
+@@ -1122,6 +1146,9 @@
+ if (f1open) {
+ anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
+ }
++ else {
++ anum = 0;
++ }
+ if (anum > 0) {
+ Ucontrol |= 0x00000001;
+ aind = 0;
+@@ -1134,6 +1161,9 @@
+ if (f2open) {
+ bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
+ }
++ else {
++ bnum = 0;
++ }
+ if (bnum > 0) {
+ Ucontrol |= 0x00010000;
+ bind = 0;
+@@ -1152,7 +1182,7 @@
+ break;
+ default:
+ if (sis_verbose)
+- printf("Read from unimplemented MEC register (%x)\n", addr);
++ (*sim_callback->printf_filtered) (sim_callback, "Read from unimplemented MEC register (%x)\n", addr);
+
+ }
+ return 0;
+@@ -1174,8 +1204,12 @@
+ if (wnuma < UARTBUF)
+ wbufa[wnuma++] = c;
+ else {
+- while (wnuma)
++ while (wnuma) {
++ if (ofd1 == 1 && callback)
++ wnuma -= callback->write_stdout(callback, wbufa, wnuma);
++ else
+ wnuma -= fwrite(wbufa, 1, wnuma, f1out);
++ }
+ wbufa[wnuma++] = c;
+ }
+ }
+@@ -1198,8 +1232,12 @@
+ if (wnumb < UARTBUF)
+ wbufb[wnumb++] = c;
+ else {
+- while (wnumb)
++ while (wnumb) {
++ if (ofd1 == 1 && callback)
++ wnumb -= callback->write_stdout(callback, wbufb, wnumb);
++ else
+ wnumb -= fwrite(wbufb, 1, wnumb, f2out);
++ }
+ wbufb[wnumb++] = c;
+ }
+ }
+@@ -1229,7 +1267,8 @@
+ break;
+ default:
+ if (sis_verbose)
+- printf("Write to unimplemented MEC register (%x)\n", addr);
++ (*sim_callback->printf_filtered) (sim_callback,
++ "Write to unimplemented MEC register (%x)\n", addr);
+
+ }
+ }
+@@ -1237,19 +1276,37 @@
+ static void
+ flush_uart()
+ {
+- while (wnuma && f1open)
++ while (wnuma && f1open) {
++ if (ofd1 == 1 && callback) {
++ wnuma -= callback->write_stdout(callback, wbufa, wnuma);
++ callback->flush_stdout(callback);
++ }
++ else
+ wnuma -= fwrite(wbufa, 1, wnuma, f1out);
+- while (wnumb && f2open)
++ }
++ while (wnumb && f2open) {
++ if (ofd2 == 1 && callback) {
++ wnuma -= callback->write_stdout(callback, wbufb, wnuma);
++ callback->flush_stdout(callback);
++ }
++ else
+ wnumb -= fwrite(wbufb, 1, wnumb, f2out);
+ }
++}
+
+
+
+ static void
+ uarta_tx()
+ {
+-
+- while (f1open && fwrite(&uarta_sreg, 1, 1, f1out) != 1);
++ while (f1open) {
++ if (ofd1 == 1 && callback) {
++ while (callback->write_stdout(callback, &uarta_sreg, 1) != 1);
++ }
++ else {
++ while (fwrite(&uarta_sreg, 1, 1, f1out) != 1);
++ }
++ }
+ if (uart_stat_reg & UARTA_HRE) {
+ uart_stat_reg |= UARTA_SRE;
+ } else {
+@@ -1263,7 +1320,14 @@
+ static void
+ uartb_tx()
+ {
+- while (f2open && fwrite(&uartb_sreg, 1, 1, f2out) != 1);
++ while (f2open) {
++ if (ofd2 == 1 && callback) {
++ while (callback->write_stdout(callback, &uarta_sreg, 1) != 1);
++ }
++ else {
++ while (fwrite(&uartb_sreg, 1, 1, f2out) != 1);
++ }
++ }
+ if (uart_stat_reg & UARTB_HRE) {
+ uart_stat_reg |= UARTB_SRE;
+ } else {
+@@ -1285,6 +1349,8 @@
+ rsize = 0;
+ if (f1open)
+ rsize = DO_STDIO_READ(ifd1, &rxd, 1);
++ else
++ rsize = 0;
+ if (rsize > 0) {
+ uarta_data = UART_DR | rxd;
+ if (uart_stat_reg & UARTA_HRE)
+@@ -1301,6 +1367,8 @@
+ rsize = 0;
+ if (f2open)
+ rsize = DO_STDIO_READ(ifd2, &rxd, 1);
++ else
++ rsize = 0;
+ if (rsize) {
+ uartb_data = UART_DR | rxd;
+ if (uart_stat_reg & UARTB_HRE)
+@@ -1354,7 +1422,7 @@
+ event(wdog_intr, 0, wdog_scaler + 1);
+ } else {
+ if (wdog_rston) {
+- printf("Watchdog reset!\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Watchdog reset!\n");
+ sys_reset();
+ mec_ersr = 0xC000;
+ } else {
+@@ -1372,7 +1440,8 @@
+ {
+ event(wdog_intr, 0, wdog_scaler + 1);
+ if (sis_verbose)
+- printf("Watchdog started, scaler = %d, counter = %d\n",
++ (*sim_callback->printf_filtered) (sim_callback,
++ "Watchdog started, scaler = %d, counter = %d\n",
+ wdog_scaler, wdog_counter);
+ }
+
+@@ -1399,7 +1468,8 @@
+ rtc_enabled = 1;
+ } else {
+ if (sis_verbose)
+- printf("RTC stopped\n\r");
++ (*sim_callback->printf_filtered) (sim_callback,
++ "RTC stopped\n\r");
+ rtc_enabled = 0;
+ }
+ }
+@@ -1408,7 +1478,8 @@
+ rtc_start()
+ {
+ if (sis_verbose)
+- printf("RTC started (period %d)\n\r", rtc_scaler + 1);
++ (*sim_callback->printf_filtered) (sim_callback,
++ "RTC started (period %d)\n\r", rtc_scaler + 1);
+ event(rtc_intr, 0, rtc_scaler + 1);
+ rtc_scaler_start = now();
+ rtc_enabled = 1;
+@@ -1452,7 +1523,7 @@
+ gpt_enabled = 1;
+ } else {
+ if (sis_verbose)
+- printf("GPT stopped\n\r");
++ (*sim_callback->printf_filtered) (sim_callback, "GPT stopped\n\r");
+ gpt_enabled = 0;
+ }
+ }
+@@ -1461,7 +1532,8 @@
+ gpt_start()
+ {
+ if (sis_verbose)
+- printf("GPT started (period %d)\n\r", gpt_scaler + 1);
++ (*sim_callback->printf_filtered) (sim_callback,
++ "GPT started (period %d)\n\r", gpt_scaler + 1);
+ event(gpt_intr, 0, gpt_scaler + 1);
+ gpt_scaler_start = now();
+ gpt_enabled = 1;
+@@ -1566,7 +1638,8 @@
+ }
+
+ if (sis_verbose)
+- printf ("Memory exception at %x (illegal address)\n", addr);
++ (*sim_callback->printf_filtered) (sim_callback,
++ "Memory exception at %x (illegal address)\n", addr);
+ if (sregs.psr & 0x080)
+ asi = 9;
+ else
+@@ -1589,7 +1662,7 @@
+ #ifdef ERRINJ
+ if (errmec) {
+ if (sis_verbose)
+- printf("Inserted MEC error %d\n",errmec);
++ (*sim_callback->printf_filtered) (sim_callback, "Inserted MEC error %d\n",errmec);
+ set_sfsr(errmec, addr, asi, 1);
+ if (errmec == 5) mecparerror();
+ if (errmec == 6) iucomperr();
+@@ -1641,7 +1714,8 @@
+ }
+
+ if (sis_verbose)
+- printf ("Memory exception at %x (illegal address)\n", addr);
++ (*sim_callback->printf_filtered) (sim_callback,
++ "Memory exception at %x (illegal address)\n", addr);
+ set_sfsr(UIMP_ACC, addr, asi, 1);
+ *ws = MEM_EX_WS;
+ return 1;
+@@ -1666,7 +1740,8 @@
+ #ifdef ERRINJ
+ if (errmec) {
+ if (sis_verbose)
+- printf("Inserted MEC error %d\n",errmec);
++ (*sim_callback->printf_filtered) (sim_callback,
++ "Inserted MEC error %d\n",errmec);
+ set_sfsr(errmec, addr, asi, 0);
+ if (errmec == 5) mecparerror();
+ if (errmec == 6) iucomperr();
+@@ -1690,7 +1765,8 @@
+ !((mec_wpr[0] && wphit[0]) || (mec_wpr[1] && wphit[1]))
+ )) {
+ if (sis_verbose)
+- printf("Memory access protection error at 0x%08x\n", addr);
++ (*sim_callback->printf_filtered) (sim_callback,
++ "Memory access protection error at 0x%08x\n", addr);
+ set_sfsr(PROT_EXC, addr, asi, 0);
+ *ws = MEM_EX_WS;
+ return 1;
+diff -ruw gdb-7.11.orig1/sim/erc32/exec.c gdb-7.11/sim/erc32/exec.c
+--- gdb-7.11.orig1/sim/erc32/exec.c 2016-03-16 14:00:04.632565918 +1100
++++ gdb-7.11/sim/erc32/exec.c 2016-03-16 14:08:17.484578389 +1100
+@@ -1903,7 +1903,8 @@
+ if (errftt) {
+ sregs->fsr = (sregs->fsr & ~FSR_TT) | (errftt << 14);
+ sregs->fpstate = FP_EXC_PE;
+- if (sis_verbose) printf("Inserted fpu error %X\n",errftt);
++ if (sis_verbose) (*sim_callback->printf_filtered) (sim_callback,
++ "Inserted fpu error %X\n",errftt);
+ errftt = 0;
+ }
+ #endif
+@@ -2023,7 +2024,8 @@
+ #ifdef ERRINJ
+ if (errtt) {
+ sregs->trap = errtt;
+- if (sis_verbose) printf("Inserted error trap 0x%02X\n",errtt);
++ if (sis_verbose) (*sim_callback->printf_filtered) (sim_callback,
++ "Inserted error trap 0x%02X\n",errtt);
+ errtt = 0;
+ }
+ #endif
+diff -ruw gdb-7.11.orig1/sim/erc32/func.c gdb-7.11/sim/erc32/func.c
+--- gdb-7.11.orig1/sim/erc32/func.c 2016-03-16 14:00:04.628565918 +1100
++++ gdb-7.11/sim/erc32/func.c 2016-03-16 14:17:33.328592454 +1100
+@@ -47,6 +47,8 @@
+ char uart_dev2[128] = "";
+ extern int ext_irl;
+ uint32 last_load_addr = 0;
++int nouartrx = 0;
++host_callback *sim_callback;
+
+ #ifdef ERRINJ
+ uint32 errcnt = 0;
+@@ -80,14 +82,15 @@
+ size_t slen;
+
+ if ((fp = fopen(fname, "r")) == NULL) {
+- fprintf(stderr, "couldn't open batch file %s\n", fname);
++ (*sim_callback->printf_filtered) (sim_callback,
++ "couldn't open batch file %s\n", fname);
+ return 0;
+ }
+ while (getline(&lbuf, &len, fp) > -1) {
+ slen = strlen(lbuf);
+ if (slen && (lbuf[slen - 1] == '\n')) {
+ lbuf[slen - 1] = 0;
+- printf("sis> %s\n", lbuf);
++ (*sim_callback->printf_filtered) (sim_callback, "sis> %s\n", lbuf);
+ exec_cmd(sregs, lbuf);
+ }
+ }
+@@ -279,13 +282,13 @@
+ err = 1;
+ switch (err) {
+ case 0:
+- printf("%s = %d (0x%08x)\n", reg, rval, rval);
++ (*sim_callback->printf_filtered) (sim_callback, "%s = %d (0x%08x)\n", reg, rval, rval);
+ break;
+ case 1:
+- printf("no such regiser: %s\n", reg);
++ (*sim_callback->printf_filtered) (sim_callback, "no such regiser: %s\n", reg);
+ break;
+ case 2:
+- printf("cannot set g0\n");
++ (*sim_callback->printf_filtered) (sim_callback, "cannot set g0\n");
+ break;
+ default:
+ break;
+@@ -358,7 +361,7 @@
+ if ((flim > ebase.simtime) && (flim < 4294967296.0)) {
+ lim = (uint32) flim;
+ } else {
+- printf("error in expression\n");
++ (*sim_callback->printf_filtered) (sim_callback, "error in expression\n");
+ lim = -1;
+ }
+ }
+@@ -381,12 +384,12 @@
+ clen = strlen(cmd1);
+ if (strncmp(cmd1, "bp", clen) == 0) {
+ for (i = 0; i < sregs->bptnum; i++) {
+- printf(" %d : 0x%08x\n", i + 1, sregs->bpts[i]);
++ (*sim_callback->printf_filtered) (sim_callback, " %d : 0x%08x\n", i + 1, sregs->bpts[i]);
+ }
+ } else if (strncmp(cmd1, "+bp", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+ sregs->bpts[sregs->bptnum] = VAL(cmd1) & ~0x3;
+- printf("added breakpoint %d at 0x%08x\n",
++ (*sim_callback->printf_filtered) (sim_callback, "added breakpoint %d at 0x%08x\n",
+ sregs->bptnum + 1, sregs->bpts[sregs->bptnum]);
+ sregs->bptnum += 1;
+ }
+@@ -394,7 +397,7 @@
+ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+ i = VAL(cmd1) - 1;
+ if ((i >= 0) && (i < sregs->bptnum)) {
+- printf("deleted breakpoint %d at 0x%08x\n", i + 1,
++ (*sim_callback->printf_filtered) (sim_callback, "deleted breakpoint %d at 0x%08x\n", i + 1,
+ sregs->bpts[i]);
+ for (; i < sregs->bptnum - 1; i++) {
+ sregs->bpts[i] = sregs->bpts[i + 1];
+@@ -404,7 +407,7 @@
+ }
+ } else if (strncmp(cmd1, "batch", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
+- printf("no file specified\n");
++ (*sim_callback->printf_filtered) (sim_callback, "no file specified\n");
+ } else {
+ batch(sregs, cmd1);
+ }
+@@ -420,7 +423,7 @@
+ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+ sis_verbose = VAL(cmd1);
+ }
+- printf("Debug level = %d\n",sis_verbose);
++ (*sim_callback->printf_filtered) (sim_callback, "Debug level = %d\n",sis_verbose);
+ } else if (strncmp(cmd1, "dis", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+ daddr = VAL(cmd1);
+@@ -429,13 +432,13 @@
+ len = VAL(cmd2);
+ } else
+ len = 16;
+- printf("\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n");
+ dis_mem(daddr, len, &dinfo);
+- printf("\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n");
+ daddr += len * 4;
+ } else if (strncmp(cmd1, "echo", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+- printf("%s\n", (&cmdsave[clen+1]));
++ (*sim_callback->printf_filtered) (sim_callback, "%s\n", (&cmdsave[clen+1]));
+ }
+ #ifdef ERRINJ
+ } else if (strncmp(cmd1, "error", clen) == 0) {
+@@ -443,9 +446,9 @@
+ errper = VAL(cmd1);
+ if (errper) {
+ event(errinj, 0, (len = (random()%errper)));
+- printf("Error injection started with period %d\n",len);
++ (*sim_callback->printf_filtered) (sim_callback, "Error injection started with period %d\n",len);
+ }
+- } else printf("Injected errors: %d\n",errcnt);
++ } else (*sim_callback->printf_filtered) (sim_callback, "Injected errors: %d\n",errcnt);
+ #endif
+ } else if (strncmp(cmd1, "float", clen) == 0) {
+ stat = disp_fpu(sregs);
+@@ -459,7 +462,7 @@
+ sregs->npc = sregs->pc + 4;
+ if ((sregs->pc != 0) && (ebase.simtime == 0))
+ boot_init();
+- printf("resuming at 0x%08x\n",sregs->pc);
++ (*sim_callback->printf_filtered) (sim_callback, "resuming at 0x%08x\n",sregs->pc);
+ if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
+ stat = run_sim(sregs, VAL(cmd2), 0);
+ } else {
+@@ -475,7 +478,7 @@
+ if (sregs->histbuf != NULL)
+ free(sregs->histbuf);
+ sregs->histbuf = (struct histype *) calloc(sregs->histlen, sizeof(struct histype));
+- printf("trace history length = %d\n\r", sregs->histlen);
++ (*sim_callback->printf_filtered) (sim_callback, "trace history length = %d\n\r", sregs->histlen);
+ sregs->histind = 0;
+
+ } else {
+@@ -483,7 +486,7 @@
+ for (i = 0; i < sregs->histlen; i++) {
+ if (j >= sregs->histlen)
+ j = 0;
+- printf(" %8d ", sregs->histbuf[j].time);
++ (*sim_callback->printf_filtered) (sim_callback, " %8d ", sregs->histbuf[j].time);
+ dis_mem(sregs->histbuf[j].addr, 1, &dinfo);
+ j++;
+ }
+@@ -495,7 +498,7 @@
+ while ((cmd1 = strtok(NULL, " \t\n\r")) != NULL)
+ last_load_addr = bfd_load(cmd1);
+ } else {
+- printf("load: no file specified\n");
++ (*sim_callback->printf_filtered) (sim_callback, "load: no file specified\n");
+ }
+ } else if (strncmp(cmd1, "mem", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL)
+@@ -565,14 +568,14 @@
+ }
+ sregs->pc = len & ~3;
+ sregs->npc = sregs->pc + 4;
+- printf("resuming at 0x%08x\n",sregs->pc);
++ (*sim_callback->printf_filtered) (sim_callback, "resuming at 0x%08x\n",sregs->pc);
+ stat = run_sim(sregs, UINT64_MAX, 0);
+ daddr = sregs->pc;
+ sim_halt();
+ } else if (strncmp(cmd1, "tlimit", clen) == 0) {
+ sregs->tlimit = limcalc(sregs->freq);
+ if (sregs->tlimit != (uint32) -1)
+- printf("simulation limit = %u (%.3f ms)\n",(uint32) sregs->tlimit,
++ (*sim_callback->printf_filtered) (sim_callback, "simulation limit = %u (%.3f ms)\n",(uint32) sregs->tlimit,
+ sregs->tlimit / sregs->freq / 1000);
+ } else if (strncmp(cmd1, "tra", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
+@@ -580,7 +583,7 @@
+ } else {
+ stat = run_sim(sregs, VAL(cmd1), 1);
+ }
+- printf("\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n");
+ daddr = sregs->pc;
+ sim_halt();
+ } else if (strncmp(cmd1, "trun", clen) == 0) {
+@@ -592,7 +595,7 @@
+ daddr = sregs->pc;
+ sim_halt();
+ } else
+- printf("syntax error\n");
++ (*sim_callback->printf_filtered) (sim_callback, "syntax error\n");
+ }
+ if (cmdsave2 != NULL)
+ free(cmdsave2);
+@@ -636,42 +639,42 @@
+ sregs->nbranch;
+ #endif
+
+- printf("\n Cycles : %9" PRIu64 "\n\r", ebase.simtime - sregs->simstart);
+- printf(" Instructions : %9" PRIu64 "\n", sregs->ninst);
++ (*sim_callback->printf_filtered) (sim_callback, "\n Cycles : %9" PRIu64 "\n\r", ebase.simtime - sregs->simstart);
++ (*sim_callback->printf_filtered) (sim_callback, " Instructions : %9" PRIu64 "\n", sregs->ninst);
+
+ #ifdef STAT
+- printf(" integer : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst);
+- printf(" load : %9.2f %%\n",
++ (*sim_callback->printf_filtered) (sim_callback, " integer : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst);
++ (*sim_callback->printf_filtered) (sim_callback, " load : %9.2f %%\n",
+ 100.0 * (float) sregs->nload / (float) sregs->ninst);
+- printf(" store : %9.2f %%\n",
++ (*sim_callback->printf_filtered) (sim_callback, " store : %9.2f %%\n",
+ 100.0 * (float) sregs->nstore / (float) sregs->ninst);
+- printf(" branch : %9.2f %%\n",
++ (*sim_callback->printf_filtered) (sim_callback, " branch : %9.2f %%\n",
+ 100.0 * (float) sregs->nbranch / (float) sregs->ninst);
+- printf(" float : %9.2f %%\n",
++ (*sim_callback->printf_filtered) (sim_callback, " float : %9.2f %%\n",
+ 100.0 * (float) sregs->finst / (float) sregs->ninst);
+- printf(" Integer CPI : %9.2f\n",
++ (*sim_callback->printf_filtered) (sim_callback, " Integer CPI : %9.2f\n",
+ ((float) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst))
+ /
+ (float) (sregs->ninst - sregs->finst));
+- printf(" Float CPI : %9.2f\n",
++ (*sim_callback->printf_filtered) (sim_callback, " Float CPI : %9.2f\n",
+ ((float) sregs->fholdt / (float) sregs->finst) + 1.0);
+ #endif
+- printf(" Overall CPI : %9.2f\n",
++ (*sim_callback->printf_filtered) (sim_callback, " Overall CPI : %9.2f\n",
+ (float) (stime - sregs->pwdtime) / (float) sregs->ninst);
+- printf("\n ERC32 performance (%4.1f MHz): %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n",
++ (*sim_callback->printf_filtered) (sim_callback, "\n ERC32 performance (%4.1f MHz): %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n",
+ sregs->freq, sregs->freq * (float) sregs->ninst / (float) (stime - sregs->pwdtime),
+ sregs->freq * (float) (sregs->ninst - sregs->finst) /
+ (float) (stime - sregs->pwdtime),
+ sregs->freq * (float) sregs->finst / (float) (stime - sregs->pwdtime));
+- printf(" Simulated ERC32 time : %.2f s\n",
++ (*sim_callback->printf_filtered) (sim_callback, " Simulated ERC32 time : %.2f s\n",
+ (float) (ebase.simtime - sregs->simstart) / 1000000.0 / sregs->freq);
+- printf(" Processor utilisation : %.2f %%\n",
++ (*sim_callback->printf_filtered) (sim_callback, " Processor utilisation : %.2f %%\n",
+ 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime)));
+- printf(" Real-time performance : %.2f %%\n",
++ (*sim_callback->printf_filtered) (sim_callback, " Real-time performance : %.2f %%\n",
+ 100.0 / (sregs->tottime / ((double) (stime) / (sregs->freq * 1.0E6))));
+- printf(" Simulator performance : %.2f MIPS\n",
++ (*sim_callback->printf_filtered) (sim_callback, " Simulator performance : %.2f MIPS\n",
+ (double)(sregs->ninst) / sregs->tottime / 1E6);
+- printf(" Used time (sys + user) : %.2f s\n\n", sregs->tottime);
++ (*sim_callback->printf_filtered) (sim_callback, " Used time (sys + user) : %.2f s\n\n", sregs->tottime);
+ }
+
+
+@@ -692,7 +695,7 @@
+ int32 sig;
+ {
+ if (sig != 2)
+- printf("\n\n Signal handler error (%d)\n\n", sig);
++ (*sim_callback->printf_filtered) (sim_callback, "\n\n Signal handler error (%d)\n\n", sig);
+ ctrl_c = 1;
+ }
+
+@@ -721,7 +724,7 @@
+ int i;
+ float t;
+
+- printf("\n fsr: %08X\n\n", sregs->fsr);
++ (*sim_callback->printf_filtered) (sim_callback, "\n fsr: %08X\n\n", sregs->fsr);
+
+ #ifdef HOST_LITTLE_ENDIAN
+ for (i = 0; i < 32; i++)
+@@ -730,13 +733,13 @@
+
+ for (i = 0; i < 32; i++) {
+ t = sregs->fs[i];
+- printf(" f%02d %08x %14e ", i, sregs->fsi[i], sregs->fs[i]);
++ (*sim_callback->printf_filtered) (sim_callback, " f%02d %08x %14e ", i, sregs->fsi[i], sregs->fs[i]);
+ if (!(i & 1))
+- printf("%14e\n", sregs->fd[i >> 1]);
++ (*sim_callback->printf_filtered) (sim_callback, "%14e\n", sregs->fd[i >> 1]);
+ else
+- printf("\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n");
+ }
+- printf("\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n");
+ return OK;
+ }
+
+@@ -749,9 +752,9 @@
+ int i;
+
+ cwp = ((cwp & 0x7) << 4);
+- printf("\n\t INS LOCALS OUTS GLOBALS\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n\t INS LOCALS OUTS GLOBALS\n");
+ for (i = 0; i < 8; i++) {
+- printf(" %d: %08X %08X %08X %08X\n", i,
++ (*sim_callback->printf_filtered) (sim_callback, " %d: %08X %08X %08X %08X\n", i,
+ sregs->r[(cwp + i + 24) & 0x7f],
+ sregs->r[(cwp + i + 16) & 0x7f], sregs->r[(cwp + i + 8) & 0x7f],
+ sregs->g[i]);
+@@ -776,7 +779,7 @@
+
+ uint32 i;
+
+- printf("\n psr: %08X wim: %08X tbr: %08X y: %08X\n",
++ (*sim_callback->printf_filtered) (sim_callback, "\n psr: %08X wim: %08X tbr: %08X y: %08X\n",
+ sregs->psr, sregs->wim, sregs->tbr, sregs->y);
+ sis_memory_read (sregs->pc, (char *) &i, 4);
+ printf ("\n pc: %08X = %08X ", sregs->pc, i);
+@@ -785,8 +788,8 @@
+ printf ("\n npc: %08X = %08X ", sregs->npc, i);
+ print_insn_sparc_sis(sregs->npc, &dinfo);
+ if (sregs->err_mode)
+- printf("\n IU in error mode");
+- printf("\n\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n IU in error mode");
++ (*sim_callback->printf_filtered) (sim_callback, "\n\n");
+ }
+
+ static void
+@@ -804,13 +807,13 @@
+ char *p;
+
+ for (i = addr & ~3; i < ((addr + len) & ~3); i += 16) {
+- printf("\n %8X ", i);
++ (*sim_callback->printf_filtered) (sim_callback, "\n %8X ", i);
+ for (j = 0; j < 4; j++) {
+ sis_memory_read ((i + (j * 4)), data.u8, 4);
+ printf ("%08x ", data.u32);
+ mem[j] = data.u32;
+ }
+- printf(" ");
++ (*sim_callback->printf_filtered) (sim_callback, " ");
+ p = (char *) mem;
+ for (j = 0; j < 16; j++) {
+ if (isprint (p[j ^ EBT]))
+@@ -819,7 +822,7 @@
+ putchar('.');
+ }
+ }
+- printf("\n\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n\n");
+ }
+
+ void
+@@ -839,7 +842,7 @@
+ printf (" %08x %08x ", i, data.u32);
+ print_insn_sparc_sis(i, info);
+ if (i >= 0xfffffffc) break;
+- printf("\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n");
+ }
+ }
+
+@@ -854,7 +857,7 @@
+ struct evcell *ev1, *evins;
+
+ if (ebase.freeq == NULL) {
+- printf("Error, too many events in event queue\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Error, too many events in event queue\n");
+ return;
+ }
+ ev1 = &ebase.eq;
+@@ -959,7 +962,7 @@
+ uint64 endtime;
+
+ if (ebase.eq.nxt == NULL)
+- printf("Warning: event queue empty - power-down mode not entered\n");
++ (*sim_callback->printf_filtered) (sim_callback, "Warning: event queue empty - power-down mode not entered\n");
+ endtime = ebase.simtime;
+ while (!ext_irl && (ebase.eq.nxt != NULL)) {
+ ebase.simtime = ebase.eq.nxt->time;
+@@ -971,7 +974,7 @@
+ ebase.freeq = evrem;
+ cfunc(arg);
+ if (ctrl_c) {
+- printf("\bwarning: power-down mode interrupted\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\bwarning: power-down mode interrupted\n");
+ break;
+ }
+ }
+@@ -1039,17 +1042,17 @@
+ pbfd = bfd_openr(fname, 0);
+
+ if (pbfd == NULL) {
+- printf("open of %s failed\n", fname);
++ (*sim_callback->printf_filtered) (sim_callback, "open of %s failed\n", fname);
+ return -1;
+ }
+ if (!bfd_check_format(pbfd, bfd_object)) {
+- printf("file %s doesn't seem to be an object file\n", fname);
++ (*sim_callback->printf_filtered) (sim_callback, "file %s doesn't seem to be an object file\n", fname);
+ return -1;
+ }
+
+ arch = bfd_get_arch_info (pbfd);
+ if (sis_verbose)
+- printf("loading %s:", fname);
++ (*sim_callback->printf_filtered) (sim_callback, "loading %s:", fname);
+ for (section = pbfd->sections; section; section = section->next) {
+ if (bfd_get_section_flags(pbfd, section) & SEC_ALLOC) {
+ bfd_vma section_address;
+@@ -1087,7 +1090,7 @@
+ section_size = bfd_section_size(pbfd, section);
+
+ if (sis_verbose)
+- printf("\nsection %s at 0x%08lx (0x%lx bytes)",
++ (*sim_callback->printf_filtered) (sim_callback, "\nsection %s at 0x%08lx (0x%lx bytes)",
+ section_name, section_address, section_size);
+
+ /* Text, data or lit */
+@@ -1113,11 +1116,11 @@
+ }
+ } else /* BSS */
+ if (sis_verbose)
+- printf("(not loaded)");
++ (*sim_callback->printf_filtered) (sim_callback, "(not loaded)");
+ }
+ }
+ if (sis_verbose)
+- printf("\n");
++ (*sim_callback->printf_filtered) (sim_callback, "\n");
+
+ return bfd_get_start_address (pbfd);
+ }
+diff -ruw gdb-7.11.orig1/sim/erc32/interf.c gdb-7.11/sim/erc32/interf.c
+--- gdb-7.11.orig1/sim/erc32/interf.c 2016-03-16 14:00:04.628565918 +1100
++++ gdb-7.11/sim/erc32/interf.c 2016-03-16 14:09:55.832580878 +1100
+@@ -57,8 +57,6 @@
+
+ int sis_gdb_break = 1;
+
+-host_callback *sim_callback;
+-
+ int
+ run_sim(sregs, icount, dis)
+ struct pstate *sregs;
+@@ -89,12 +87,12 @@
+ #if 0 /* DELETE ME! for debugging purposes only */
+ if (sis_verbose > 1)
+ if (sregs->pc == 0 || sregs->npc == 0)
+- printf ("bogus pc or npc\n");
++ (*sim_callback->printf_filtered) (sim_callback, "bogus pc or npc\n");
+ #endif
+ mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
+ #if 0 /* DELETE ME! for debugging purposes only */
+ if (sis_verbose > 2)
+- printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
++ (*sim_callback->printf_filtered) (sim_callback, "pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
+ sregs->pc, sregs->npc,
+ sregs->r[(((sregs->psr & 7) << 4) + 14) & 0x7f],
+ sregs->r[(((sregs->psr & 7) << 4) + 30) & 0x7f],
+@@ -192,6 +190,9 @@
+ if (strcmp(argv[stat], "-dumbio") == 0) {
+ dumbio = 1;
+ } else
++ if (strcmp(argv[stat], "-nouartrx") == 0) {
++ nouartrx = 1;
++ } else
+ if (strcmp(argv[stat], "-wrp") == 0) {
+ wrp = 1;
+ } else
+@@ -430,7 +431,7 @@
+ #if 1
+ if (sis_verbose > 2) {
+ uint32 fp = sregs.r[(win * 16 + 30) & 0x7f];
+- printf("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
++ (*sim_callback->printf_filtered) (sim_callback, "flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
+ }
+ #endif
+
+diff -ruw gdb-7.11.orig1/sim/erc32/sis.c gdb-7.11/sim/erc32/sis.c
+--- gdb-7.11.orig1/sim/erc32/sis.c 2016-03-16 14:00:04.632565918 +1100
++++ gdb-7.11/sim/erc32/sis.c 2016-03-16 14:01:13.052567649 +1100
+@@ -199,6 +199,8 @@
+ #endif
+ } else if (strcmp(argv[stat], "-dumbio") == 0) {
+ dumbio = 1;
++ } else if (strcmp(argv[stat], "-nouartrx") == 0) {
++ nouartrx = 1;
+ } else {
+ printf("unknown option %s\n", argv[stat]);
+ usage();
+@@ -293,4 +295,3 @@
+ }
+ return 0;
+ }
+-
+diff -ruw gdb-7.11.orig1/sim/erc32/sis.h gdb-7.11/sim/erc32/sis.h
+--- gdb-7.11.orig1/sim/erc32/sis.h 2016-03-16 14:00:04.632565918 +1100
++++ gdb-7.11/sim/erc32/sis.h 2016-03-16 14:00:44.488566926 +1100
+@@ -158,7 +158,7 @@
+ /* Prototypes */
+
+ /* erc32.c */
+-extern void init_sim (void);
++extern void init_sim ();
+ extern void reset (void);
+ extern void error_mode (uint32 pc);
+ extern void sim_halt (void);
+@@ -200,6 +200,8 @@
+ extern void sys_halt (void);
+ extern int bfd_load (const char *fname);
+ extern double get_time (void);
++extern int nouartrx;
++extern host_callback *sim_callback;
+
+ /* exec.c */
+ extern int dispatch_instruction (struct pstate *sregs);
diff --git a/tools/5/gdb/gdb-7.11-sis-leon2-leon3.diff b/tools/5/gdb/gdb-7.11-sis-leon2-leon3.diff
new file mode 100644
index 0000000..78b5302
--- /dev/null
+++ b/tools/5/gdb/gdb-7.11-sis-leon2-leon3.diff
@@ -0,0 +1,7496 @@
+From c374a40ba70ae8b74410de2ef9293a56e1efe10b Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri at gaisler.se>
+Date: Wed, 23 Dec 2015 16:17:10 -0500
+Subject: [PATCH 1/9] sim/erc32: Use gdb callback for UART I/O when linked with
+ gdb.
+
+ * erc32.c (<errno.h>): new include.
+ (init_stdio, restore_stdio): don't set tty attributes if ttys not open.
+ (DO_STDIO_READ, port_init, read_uart, write_uart, flush_uart, uarta_tx,
+ uartb_tx, uart_rx): Use gdb callbacks for console I/O, fix whitespace.
+
+ * func.c (dumbio, tty_setup): new variables.
+ (nouartrx): new variable, set to 1 if UART receiver should be disabled.
+ (sim_callback): new variable, pointer to gdb host callback structure.
+
+ * interf.c (dumbio): remove duplicate extern declaration.
+ (sim_callback): moved to func.c.
+ (sim_open): add -nouartrx switch to disable UART input.
+
+ * sis.c (main): Add -nouartrx switch to disable UART input.
+
+ * sis.h (nouartrx, sim_callback, dumbio, tty_setup): add external declare.
+---
+ sim/erc32/erc32.c | 161 +++++++++++++++++++++++++++++++++++------------------
+ sim/erc32/func.c | 8 +++
+ sim/erc32/interf.c | 6 +-
+ sim/erc32/sis.c | 2 +
+ sim/erc32/sis.h | 5 ++
+ 5 files changed, 124 insertions(+), 58 deletions(-)
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index c24b652..2a68926 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -19,6 +19,7 @@
+ /* The control space devices */
+
+ #include "config.h"
++#include <errno.h>
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -35,8 +36,6 @@ extern int32 sparclite, sparclite_board;
+ extern int rom8,wrp,uben;
+ extern char uart_dev1[], uart_dev2[];
+
+-int dumbio = 0; /* normal, smart, terminal oriented IO by default */
+-
+ /* MEC registers */
+ #define MEC_START 0x01f80000
+ #define MEC_END 0x01f80100
+@@ -293,7 +292,6 @@ static void store_bytes (unsigned char *mem, uint32 waddr,
+
+ extern int ext_irl;
+
+-
+ /* One-time init */
+
+ void
+@@ -935,44 +933,49 @@ void
+ init_stdio()
+ {
+ if (dumbio)
+- return; /* do nothing */
+- if (!ifd1)
++ return; /* do nothing */
++ if (ifd1 == 0 && f1open) {
+ tcsetattr(0, TCSANOW, &ioc1);
+- if (!ifd2)
++ tcflush (ifd1, TCIFLUSH);
++ }
++ if (ifd2 == 0 && f1open) {
+ tcsetattr(0, TCSANOW, &ioc2);
++ tcflush (ifd2, TCIFLUSH);
++ }
+ }
+
+ void
+ restore_stdio()
+ {
+ if (dumbio)
+- return; /* do nothing */
+- if (!ifd1)
++ return; /* do nothing */
++ if (ifd1 == 0 && f1open && tty_setup)
+ tcsetattr(0, TCSANOW, &iocold1);
+- if (!ifd2)
++ if (ifd2 == 0 && f2open && tty_setup)
+ tcsetattr(0, TCSANOW, &iocold2);
+ }
+
+ #define DO_STDIO_READ( _fd_, _buf_, _len_ ) \
+- ( dumbio \
+- ? (0) /* no bytes read, no delay */ \
+- : read( _fd_, _buf_, _len_ ) )
+-
++ ( dumbio || nouartrx \
++ ? (0) /* no bytes read, no delay */ \
++ : (_fd_) == 1 && sim_callback ? \
++ sim_callback->read_stdin (sim_callback, _buf_, _len_) : \
++ read( _fd_, _buf_, _len_ ) )
+
+ static void
+ port_init()
+ {
+
+ if (uben) {
+- f2in = stdin;
+- f1in = NULL;
+- f2out = stdout;
+- f1out = NULL;
++ f2in = stdin;
++ f1in = NULL;
++ f2out = stdout;
++ f1out = NULL;
+ } else {
+- f1in = stdin;
+- f2in = NULL;
+- f1out = stdout;
+- f2out = NULL;
++ f1in = stdin;
++ f2in = NULL;
++ f1out = stdout;
++ f2out = NULL;
+ }
+ if (uart_dev1[0] != 0)
+ if ((fd1 = open(uart_dev1, O_RDWR | O_NONBLOCK)) < 0) {
+@@ -984,23 +987,29 @@ port_init()
+ setbuf(f1out, NULL);
+ f1open = 1;
+ }
+- if (f1in) ifd1 = fileno(f1in);
++ if (f1in)
++ ifd1 = fileno(f1in);
+ if (ifd1 == 0) {
++ if (sim_callback && !sim_callback->isatty (sim_callback, ifd1))
++ tty_setup = 0;
+ if (sis_verbose)
+ printf("serial port A on stdin/stdout\n");
+ if (!dumbio) {
+- tcgetattr(ifd1, &ioc1);
+- iocold1 = ioc1;
+- ioc1.c_lflag &= ~(ICANON | ECHO);
+- ioc1.c_cc[VMIN] = 0;
+- ioc1.c_cc[VTIME] = 0;
++ tcgetattr (ifd1, &ioc1);
++ if (tty_setup) {
++ iocold1 = ioc1;
++ ioc1.c_lflag &= ~(ICANON | ECHO);
++ ioc1.c_cc[VMIN] = 0;
++ ioc1.c_cc[VTIME] = 0;
++ }
+ }
+ f1open = 1;
+ }
+
+ if (f1out) {
+ ofd1 = fileno(f1out);
+- if (!dumbio && ofd1 == 1) setbuf(f1out, NULL);
++ if (!dumbio && tty_setup && ofd1 == 1)
++ setbuf (f1out, NULL);
+ }
+
+ if (uart_dev2[0] != 0)
+@@ -1019,17 +1028,20 @@ port_init()
+ printf("serial port B on stdin/stdout\n");
+ if (!dumbio) {
+ tcgetattr(ifd2, &ioc2);
+- iocold2 = ioc2;
+- ioc2.c_lflag &= ~(ICANON | ECHO);
+- ioc2.c_cc[VMIN] = 0;
+- ioc2.c_cc[VTIME] = 0;
++ if (tty_setup) {
++ iocold2 = ioc2;
++ ioc2.c_lflag &= ~(ICANON | ECHO);
++ ioc2.c_cc[VMIN] = 0;
++ ioc2.c_cc[VTIME] = 0;
++ }
+ }
+ f2open = 1;
+ }
+
+ if (f2out) {
+ ofd2 = fileno(f2out);
+- if (!dumbio && ofd2 == 1) setbuf(f2out, NULL);
++ if (!dumbio && tty_setup && ofd2 == 1)
++ setbuf (f2out, NULL);
+ }
+
+ wnuma = wnumb = 0;
+@@ -1055,9 +1067,10 @@ read_uart(addr)
+ mec_irq(4);
+ return (0x700 | (uint32) aq[aind++]);
+ } else {
+- if (f1open) {
+- anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
+- }
++ if (f1open)
++ anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
++ else
++ anum = 0;
+ if (anum > 0) {
+ aind = 0;
+ if ((aind + 1) < anum)
+@@ -1087,9 +1100,10 @@ read_uart(addr)
+ mec_irq(5);
+ return (0x700 | (uint32) bq[bind++]);
+ } else {
+- if (f2open) {
++ if (f2open)
+ bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
+- }
++ else
++ bnum = 0;
+ if (bnum > 0) {
+ bind = 0;
+ if ((bind + 1) < bnum)
+@@ -1119,9 +1133,10 @@ read_uart(addr)
+ if (aind < anum) {
+ Ucontrol |= 0x00000001;
+ } else {
+- if (f1open) {
+- anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
+- }
++ if (f1open)
++ anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
++ else
++ anum = 0;
+ if (anum > 0) {
+ Ucontrol |= 0x00000001;
+ aind = 0;
+@@ -1131,9 +1146,10 @@ read_uart(addr)
+ if (bind < bnum) {
+ Ucontrol |= 0x00010000;
+ } else {
+- if (f2open) {
++ if (f2open)
+ bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
+- }
++ else
++ bnum = 0;
+ if (bnum > 0) {
+ Ucontrol |= 0x00010000;
+ bind = 0;
+@@ -1174,9 +1190,13 @@ write_uart(addr, data)
+ if (wnuma < UARTBUF)
+ wbufa[wnuma++] = c;
+ else {
+- while (wnuma)
+- wnuma -= fwrite(wbufa, 1, wnuma, f1out);
+- wbufa[wnuma++] = c;
++ while (wnuma) {
++ if (ofd1 == 1 && sim_callback)
++ wnuma -= sim_callback->write_stdout (sim_callback, wbufa, wnuma);
++ else
++ wnuma -= fwrite (wbufa, 1, wnuma, f1out);
++ }
++ wbufa[wnuma++] = c;
+ }
+ }
+ mec_irq(4);
+@@ -1198,8 +1218,12 @@ write_uart(addr, data)
+ if (wnumb < UARTBUF)
+ wbufb[wnumb++] = c;
+ else {
+- while (wnumb)
+- wnumb -= fwrite(wbufb, 1, wnumb, f2out);
++ while (wnumb) {
++ if (ofd1 == 1 && sim_callback)
++ wnumb -= sim_callback->write_stdout (sim_callback, wbufb, wnumb);
++ else
++ wnumb -= fwrite (wbufb, 1, wnumb, f2out);
++ }
+ wbufb[wnumb++] = c;
+ }
+ }
+@@ -1237,10 +1261,20 @@ write_uart(addr, data)
+ static void
+ flush_uart()
+ {
+- while (wnuma && f1open)
+- wnuma -= fwrite(wbufa, 1, wnuma, f1out);
+- while (wnumb && f2open)
+- wnumb -= fwrite(wbufb, 1, wnumb, f2out);
++ while (wnuma && f1open) {
++ if (ofd1 == 1 && sim_callback) {
++ wnuma -= sim_callback->write_stdout (sim_callback, wbufa, wnuma);
++ sim_callback->flush_stdout (sim_callback);
++ } else
++ wnuma -= fwrite (wbufa, 1, wnuma, f1out);
++ }
++ while (wnumb && f2open) {
++ if (ofd2 == 1 && sim_callback) {
++ wnuma -= sim_callback->write_stdout (sim_callback, wbufb, wnuma);
++ sim_callback->flush_stdout (sim_callback);
++ } else
++ wnumb -= fwrite (wbufb, 1, wnumb, f2out);
++ }
+ }
+
+
+@@ -1248,8 +1282,14 @@ flush_uart()
+ static void
+ uarta_tx()
+ {
+-
+- while (f1open && fwrite(&uarta_sreg, 1, 1, f1out) != 1);
++ while (f1open) {
++ if (ofd1 == 1 && sim_callback)
++ while (sim_callback->write_stdout (sim_callback, &uarta_sreg, 1) != 1)
++ continue;
++ else
++ while (fwrite (&uarta_sreg, 1, 1, f1out) != 1)
++ continue;
++ }
+ if (uart_stat_reg & UARTA_HRE) {
+ uart_stat_reg |= UARTA_SRE;
+ } else {
+@@ -1263,7 +1303,14 @@ uarta_tx()
+ static void
+ uartb_tx()
+ {
+- while (f2open && fwrite(&uartb_sreg, 1, 1, f2out) != 1);
++ while (f2open) {
++ if (ofd2 == 1 && sim_callback)
++ while (sim_callback->write_stdout (sim_callback, &uarta_sreg, 1) != 1)
++ continue;
++ else
++ while (fwrite(&uartb_sreg, 1, 1, f2out) != 1)
++ continue;
++ }
+ if (uart_stat_reg & UARTB_HRE) {
+ uart_stat_reg |= UARTB_SRE;
+ } else {
+@@ -1285,6 +1332,8 @@ uart_rx(arg)
+ rsize = 0;
+ if (f1open)
+ rsize = DO_STDIO_READ(ifd1, &rxd, 1);
++ else
++ rsize = 0;
+ if (rsize > 0) {
+ uarta_data = UART_DR | rxd;
+ if (uart_stat_reg & UARTA_HRE)
+@@ -1301,6 +1350,8 @@ uart_rx(arg)
+ rsize = 0;
+ if (f2open)
+ rsize = DO_STDIO_READ(ifd2, &rxd, 1);
++ else
++ rsize = 0;
+ if (rsize) {
+ uartb_data = UART_DR | rxd;
+ if (uart_stat_reg & UARTB_HRE)
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index aa5871c..47f403d 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -29,6 +29,12 @@
+
+ #define VAL(x) strtoul(x,(char **)NULL,0)
+
++/* set if UART device cannot handle attributes, terminal oriented IO by default */
++int dumbio = 0;
++
++/* set if UARTs are connected to a tty, enable by default */
++int tty_setup = 1;
++
+ struct disassemble_info dinfo;
+ struct pstate sregs;
+ extern struct estate ebase;
+@@ -47,6 +53,8 @@ char uart_dev1[128] = "";
+ char uart_dev2[128] = "";
+ extern int ext_irl;
+ uint32 last_load_addr = 0;
++int nouartrx = 0;
++host_callback *sim_callback;
+
+ #ifdef ERRINJ
+ uint32 errcnt = 0;
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 826a85a..23a6ea9 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -50,15 +50,12 @@ extern struct evcell evbuf[];
+ extern struct irqcell irqarr[];
+ extern int irqpend, ext_irl;
+ extern int sparclite;
+-extern int dumbio;
+ extern int sparclite_board;
+ extern int termsave;
+ extern char uart_dev1[], uart_dev2[];
+
+ int sis_gdb_break = 1;
+
+-host_callback *sim_callback;
+-
+ int
+ run_sim(sregs, icount, dis)
+ struct pstate *sregs;
+@@ -192,6 +189,9 @@ sim_open (kind, callback, abfd, argv)
+ if (strcmp(argv[stat], "-dumbio") == 0) {
+ dumbio = 1;
+ } else
++ if (strcmp(argv[stat], "-nouartrx") == 0) {
++ nouartrx = 1;
++ } else
+ if (strcmp(argv[stat], "-wrp") == 0) {
+ wrp = 1;
+ } else
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index 7334c20..19f80fa 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -199,6 +199,8 @@ main(argc, argv)
+ #endif
+ } else if (strcmp(argv[stat], "-dumbio") == 0) {
+ dumbio = 1;
++ } else if (strcmp(argv[stat], "-nouartrx") == 0) {
++ nouartrx = 1;
+ } else {
+ printf("unknown option %s\n", argv[stat]);
+ usage();
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index 5a909f5..3e29a40 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -200,6 +200,11 @@ extern void sys_reset (void);
+ extern void sys_halt (void);
+ extern int bfd_load (const char *fname);
+ extern double get_time (void);
++extern int nouartrx;
++extern host_callback *sim_callback;
++extern int dumbio;
++extern int tty_setup;
++
+
+ /* exec.c */
+ extern int dispatch_instruction (struct pstate *sregs);
+--
+2.7.4
+
+From c14cfd7c752600f375806e89dcf578d38fb4d27d Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri at gaisler.se>
+Date: Wed, 23 Dec 2015 16:21:52 -0500
+Subject: [PATCH 2/9] sim/erc32: Access memory subsystem through struct memsys.
+
+ Introduce an common API to access emulated memory. This allows
+ to emulate different types of SPARC-based CPUs.
+
+ * erc32.c (reset, error_mode, sim_halt, close_port, exit_sim, init_stdio,
+ restore_stdio, memory_iread, memory_read, memory_write, sis_memory_write,
+ sis_memory_read): Mark static.
+ (sim_stop): Move to interf.c.
+ (erc32sys): New variable, exporting memory operations through struct memsys.
+ * exec.c (dispatch_instruction): Access memory through common API.
+ * func.c (ms): New global, pointing to active memory sub-system.
+ (exec_cmd, print_insn_sparc_sis, dis_mem, reset_all, bfd_load): Access memory
+ through common API.
+ * interf.c (sregs, ctrl_c, sis_verbose): move extern declaration to sis.h.
+ (run_sim, sim_close, sim_write, sim_read, flush_windows): Access memory through
+ common API.
+ (sim_stop): Add.
+ * sis.c (sregs, ctrl_c, sis_verbose): move extern declaration to sis.h.
+ (run_sim, main): Access memory through common API.
+ * sis.h (memsys): Define struct memsys as common memory API. Remove declaration
+ of functions marked as static.
+---
+ sim/erc32/erc32.c | 46 +++++++++++++++++++++++++++-------------------
+ sim/erc32/exec.c | 42 +++++++++++++++++++++---------------------
+ sim/erc32/func.c | 32 ++++++++++++++++----------------
+ sim/erc32/interf.c | 34 +++++++++++++++++++---------------
+ sim/erc32/sis.c | 15 ++++++---------
+ sim/erc32/sis.h | 42 +++++++++++++++++++++++++-----------------
+ 6 files changed, 114 insertions(+), 97 deletions(-)
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index 2a68926..2e1ed03 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -294,7 +294,7 @@ extern int ext_irl;
+
+ /* One-time init */
+
+-void
++static void
+ init_sim()
+ {
+ port_init();
+@@ -302,7 +302,7 @@ init_sim()
+
+ /* Power-on reset init */
+
+-void
++static void
+ reset()
+ {
+ mec_reset();
+@@ -382,7 +382,7 @@ mecparerror()
+
+ /* IU error mode manager */
+
+-void
++static void
+ error_mode(pc)
+ uint32 pc;
+ {
+@@ -453,7 +453,7 @@ decode_mcr()
+
+ /* Flush ports when simulator stops */
+
+-void
++static void
+ sim_halt()
+ {
+ #ifdef FAST_UART
+@@ -461,13 +461,6 @@ sim_halt()
+ #endif
+ }
+
+-int
+-sim_stop(SIM_DESC sd)
+-{
+- ctrl_c = 1;
+- return 1;
+-}
+-
+ static void
+ close_port()
+ {
+@@ -477,7 +470,7 @@ close_port()
+ fclose(f2in);
+ }
+
+-void
++static void
+ exit_sim()
+ {
+ close_port();
+@@ -929,7 +922,7 @@ mec_write(addr, data)
+
+ static int ifd1 = -1, ifd2 = -1, ofd1 = -1, ofd2 = -1;
+
+-void
++static void
+ init_stdio()
+ {
+ if (dumbio)
+@@ -944,7 +937,7 @@ init_stdio()
+ }
+ }
+
+-void
++static void
+ restore_stdio()
+ {
+ if (dumbio)
+@@ -1602,7 +1595,7 @@ store_bytes (unsigned char *mem, uint32 waddr, uint32 *data, int32 sz,
+
+ /* Memory emulation */
+
+-int
++static int
+ memory_iread (uint32 addr, uint32 *data, int32 *ws)
+ {
+ uint32 asi;
+@@ -1627,7 +1620,7 @@ memory_iread (uint32 addr, uint32 *data, int32 *ws)
+ return 1;
+ }
+
+-int
++static int
+ memory_read(asi, addr, data, sz, ws)
+ int32 asi;
+ uint32 addr;
+@@ -1698,7 +1691,7 @@ memory_read(asi, addr, data, sz, ws)
+ return 1;
+ }
+
+-int
++static int
+ memory_write(asi, addr, data, sz, ws)
+ int32 asi;
+ uint32 addr;
+@@ -1832,7 +1825,7 @@ get_mem_ptr(addr, size)
+ return (char *) -1;
+ }
+
+-int
++static int
+ sis_memory_write(addr, data, length)
+ uint32 addr;
+ const unsigned char *data;
+@@ -1847,7 +1840,7 @@ sis_memory_write(addr, data, length)
+ return length;
+ }
+
+-int
++static int
+ sis_memory_read(addr, data, length)
+ uint32 addr;
+ char *data;
+@@ -1877,3 +1870,18 @@ boot_init (void)
+ sregs.r[14] = sregs.r[30] - 96 * 4;
+ mec_mcr |= 1; /* power-down enabled */
+ }
++
++const struct memsys erc32sys = {
++ init_sim,
++ reset,
++ error_mode,
++ sim_halt,
++ exit_sim,
++ init_stdio,
++ restore_stdio,
++ memory_iread,
++ memory_read,
++ memory_write,
++ sis_memory_write,
++ sis_memory_read
++};
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index a0ab0f9..99220d4 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -1241,9 +1241,9 @@ dispatch_instruction(sregs)
+ else
+ rdd = &(sregs->g[rd]);
+ }
+- mexc = memory_read (asi, address, ddata, 2, &ws);
++ mexc = ms->memory_read (asi, address, ddata, 2, &ws);
+ sregs->hold += ws;
+- mexc |= memory_read (asi, address+4, &ddata[1], 2, &ws);
++ mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_LDD;
+ if (mexc) {
+@@ -1264,7 +1264,7 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = memory_read(asi, address, &data, 2, &ws);
++ mexc = ms->memory_read (asi, address, &data, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1275,7 +1275,7 @@ dispatch_instruction(sregs)
+ case LDSTUBA:
+ if (!chk_asi(sregs, &asi, op3)) break;
+ case LDSTUB:
+- mexc = memory_read(asi, address, &data, 0, &ws);
++ mexc = ms->memory_read (asi, address, &data, 0, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_LDST;
+ if (mexc) {
+@@ -1285,7 +1285,7 @@ dispatch_instruction(sregs)
+ data = extract_byte (data, address);
+ *rdd = data;
+ data = 0x0ff;
+- mexc = memory_write(asi, address, &data, 0, &ws);
++ mexc = ms->memory_write (asi, address, &data, 0, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1299,7 +1299,7 @@ dispatch_instruction(sregs)
+ if (!chk_asi(sregs, &asi, op3)) break;
+ case LDSB:
+ case LDUB:
+- mexc = memory_read(asi, address, &data, 0, &ws);
++ mexc = ms->memory_read (asi, address, &data, 0, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1320,7 +1320,7 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = memory_read(asi, address, &data, 1, &ws);
++ mexc = ms->memory_read (asi, address, &data, 1, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1346,7 +1346,7 @@ dispatch_instruction(sregs)
+ (sregs->frs2 == rd))
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = memory_read(asi, address, &data, 2, &ws);
++ mexc = ms->memory_read (asi, address, &data, 2, &ws);
+ sregs->hold += ws;
+ sregs->flrd = rd;
+ sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
+@@ -1372,9 +1372,9 @@ dispatch_instruction(sregs)
+ ((sregs->frs2 >> 1) == (rd >> 1)))
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = memory_read (asi, address, ddata, 2, &ws);
++ mexc = ms->memory_read (asi, address, ddata, 2, &ws);
+ sregs->hold += ws;
+- mexc |= memory_read (asi, address+4, &ddata[1], 2, &ws);
++ mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_LDD;
+ if (mexc) {
+@@ -1403,7 +1403,7 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = memory_read(asi, address, &data, 2, &ws);
++ mexc = ms->memory_read (asi, address, &data, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1425,7 +1425,7 @@ dispatch_instruction(sregs)
+ if (ebase.simtime < sregs->ftime) {
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);
++ mexc = ms->memory_write (asi, address, &sregs->fsr, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1439,7 +1439,7 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = memory_write(asi, address, rdd, 2, &ws);
++ mexc = ms->memory_write (asi, address, rdd, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1448,7 +1448,7 @@ dispatch_instruction(sregs)
+ case STBA:
+ if (!chk_asi(sregs, &asi, op3)) break;
+ case STB:
+- mexc = memory_write(asi, address, rdd, 0, &ws);
++ mexc = ms->memory_write (asi, address, rdd, 0, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1468,7 +1468,7 @@ dispatch_instruction(sregs)
+ else
+ rdd = &(sregs->g[rd]);
+ }
+- mexc = memory_write(asi, address, rdd, 3, &ws);
++ mexc = ms->memory_write (asi, address, rdd, 3, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_STD;
+ #ifdef STAT
+@@ -1497,7 +1497,7 @@ dispatch_instruction(sregs)
+ break;
+ }
+ rdd = &(sregs->fpq[0]);
+- mexc = memory_write(asi, address, rdd, 3, &ws);
++ mexc = ms->memory_write (asi, address, rdd, 3, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_STD;
+ #ifdef STAT
+@@ -1518,7 +1518,7 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = memory_write(asi, address, rdd, 1, &ws);
++ mexc = ms->memory_write (asi, address, rdd, 1, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1537,7 +1537,7 @@ dispatch_instruction(sregs)
+ if (sregs->frd == rd)
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = memory_write(asi, address, &sregs->fsi[rd], 2, &ws);
++ mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1557,7 +1557,7 @@ dispatch_instruction(sregs)
+ if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = memory_write(asi, address, &sregs->fsi[rd], 3, &ws);
++ mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 3, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_STD;
+ #ifdef STAT
+@@ -1574,13 +1574,13 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = memory_read(asi, address, &data, 2, &ws);
++ mexc = ms->memory_read (asi, address, &data, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+ break;
+ }
+- mexc = memory_write(asi, address, rdd, 2, &ws);
++ mexc = ms->memory_write (asi, address, rdd, 2, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_LDST;
+ if (mexc) {
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index 47f403d..94750e4 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -55,6 +55,7 @@ extern int ext_irl;
+ uint32 last_load_addr = 0;
+ int nouartrx = 0;
+ host_callback *sim_callback;
++const struct memsys *ms = &erc32sys;
+
+ #ifdef ERRINJ
+ uint32 errcnt = 0;
+@@ -423,7 +424,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ stat = run_sim(sregs, VAL(cmd1), 0);
+ }
+ daddr = sregs->pc;
+- sim_halt();
++ ms->sim_halt ();
+ } else if (strncmp(cmd1, "debug", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+ sis_verbose = VAL(cmd1);
+@@ -474,7 +475,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ stat = run_sim(sregs, UINT64_MAX, 0);
+ }
+ daddr = sregs->pc;
+- sim_halt();
++ ms->sim_halt ();
+ } else if (strncmp(cmd1, "help", clen) == 0) {
+ gen_help();
+ } else if (strncmp(cmd1, "history", clen) == 0) {
+@@ -548,7 +549,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ stat = run_sim(sregs, VAL(cmd1), 0);
+ }
+ daddr = sregs->pc;
+- sim_halt();
++ ms->sim_halt ();
+ } else if (strncmp(cmd1, "shell", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+ if (system(&cmdsave[clen])) {
+@@ -558,12 +559,12 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ } else if (strncmp(cmd1, "step", clen) == 0) {
+ stat = run_sim(sregs, 1, 1);
+ daddr = sregs->pc;
+- sim_halt();
++ ms->sim_halt ();
+ } else if (strncmp(cmd1, "tcont", clen) == 0) {
+ sregs->tlimit = limcalc(sregs->freq);
+ stat = run_sim(sregs, UINT64_MAX, 0);
+ daddr = sregs->pc;
+- sim_halt();
++ ms->sim_halt ();
+ } else if (strncmp(cmd1, "tgo", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
+ len = last_load_addr;
+@@ -576,7 +577,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ printf("resuming at 0x%08x\n",sregs->pc);
+ stat = run_sim(sregs, UINT64_MAX, 0);
+ daddr = sregs->pc;
+- sim_halt();
++ ms->sim_halt ();
+ } else if (strncmp(cmd1, "tlimit", clen) == 0) {
+ sregs->tlimit = limcalc(sregs->freq);
+ if (sregs->tlimit != (uint32) -1)
+@@ -590,7 +591,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ }
+ printf("\n");
+ daddr = sregs->pc;
+- sim_halt();
++ ms->sim_halt ();
+ } else if (strncmp(cmd1, "trun", clen) == 0) {
+ ebase.simtime = 0;
+ reset_all();
+@@ -598,7 +599,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ sregs->tlimit = limcalc(sregs->freq);
+ stat = run_sim(sregs, UINT64_MAX, 0);
+ daddr = sregs->pc;
+- sim_halt();
++ ms->sim_halt ();
+ } else
+ printf("syntax error\n");
+ }
+@@ -770,7 +771,7 @@ static void print_insn_sparc_sis(uint32 addr, struct disassemble_info *info)
+ {
+ unsigned char i[4];
+
+- sis_memory_read(addr, i, 4);
++ ms->sis_memory_read (addr, i, 4);
+ dinfo.buffer_vma = addr;
+ dinfo.buffer_length = 4;
+ dinfo.buffer = i;
+@@ -786,10 +787,10 @@ disp_ctrl(sregs)
+
+ printf("\n psr: %08X wim: %08X tbr: %08X y: %08X\n",
+ sregs->psr, sregs->wim, sregs->tbr, sregs->y);
+- sis_memory_read (sregs->pc, (char *) &i, 4);
++ ms->sis_memory_read (sregs->pc, (char *) &i, 4);
+ printf ("\n pc: %08X = %08X ", sregs->pc, i);
+ print_insn_sparc_sis(sregs->pc, &dinfo);
+- sis_memory_read (sregs->npc, (char *) &i, 4);
++ ms->sis_memory_read (sregs->npc, (char *) &i, 4);
+ printf ("\n npc: %08X = %08X ", sregs->npc, i);
+ print_insn_sparc_sis(sregs->npc, &dinfo);
+ if (sregs->err_mode)
+@@ -814,7 +815,7 @@ disp_mem(addr, len)
+ for (i = addr & ~3; i < ((addr + len) & ~3); i += 16) {
+ printf("\n %8X ", i);
+ for (j = 0; j < 4; j++) {
+- sis_memory_read ((i + (j * 4)), data.u8, 4);
++ ms->sis_memory_read ((i + (j * 4)), data.u8, 4);
+ printf ("%08x ", data.u32);
+ mem[j] = data.u32;
+ }
+@@ -843,7 +844,7 @@ dis_mem(addr, len, info)
+ } data;
+
+ for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) {
+- sis_memory_read (i, data.u8, 4);
++ ms->sis_memory_read (i, data.u8, 4);
+ printf (" %08x %08x ", i, data.u32);
+ print_insn_sparc_sis(i, info);
+ if (i >= 0xfffffffc) break;
+@@ -1007,7 +1008,7 @@ reset_all()
+ {
+ init_event(); /* Clear event queue */
+ init_regs(&sregs);
+- reset();
++ ms->reset ();
+ #ifdef ERRINJ
+ errinjstart();
+ #endif
+@@ -1113,8 +1114,7 @@ bfd_load (const char *fname)
+ bfd_get_section_contents(pbfd, section, buffer, fptr, count);
+
+ for (i = 0; i < count; i++)
+- sis_memory_write ((section_address + i) ^ EBT, &buffer[i], 1);
+-
++ ms->sis_memory_write ((section_address + i) ^ EBT, &buffer[i], 1);
+ section_address += count;
+ fptr += count;
+ section_size -= count;
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 23a6ea9..20577de 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -34,16 +34,13 @@
+ #define PSR_CWP 0x7
+
+ extern struct disassemble_info dinfo;
+-extern struct pstate sregs;
+ extern struct estate ebase;
+
+-extern int ctrl_c;
+ extern int nfp;
+ extern int ift;
+ extern int rom8;
+ extern int wrp;
+ extern int uben;
+-extern int sis_verbose;
+ extern char *sis_version;
+ extern struct estate ebase;
+ extern struct evcell evbuf[];
+@@ -67,7 +64,7 @@ run_sim(sregs, icount, dis)
+ if (sis_verbose)
+ (*sim_callback->printf_filtered) (sim_callback, "resuming at %x\n",
+ sregs->pc);
+- init_stdio();
++ ms->init_stdio ();
+ sregs->starttime = get_time();
+ irq = 0;
+ if ((sregs->pc != 0) && (ebase.simtime == 0))
+@@ -88,7 +85,7 @@ run_sim(sregs, icount, dis)
+ if (sregs->pc == 0 || sregs->npc == 0)
+ printf ("bogus pc or npc\n");
+ #endif
+- mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
++ mexc = ms->memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
+ #if 0 /* DELETE ME! for debugging purposes only */
+ if (sis_verbose > 2)
+ printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
+@@ -114,8 +111,8 @@ run_sim(sregs, icount, dis)
+ if (sis_verbose)
+ (*sim_callback->printf_filtered) (sim_callback,
+ "SW BP hit at %x\n", sregs->pc);
+- sim_halt();
+- restore_stdio();
++ ms->sim_halt ();
++ ms->restore_stdio ();
+ clearerr(stdin);
+ return BPT_HIT;
+ } else
+@@ -133,12 +130,12 @@ run_sim(sregs, icount, dis)
+ icount = 0;
+ }
+ }
+- sim_halt();
++ ms->sim_halt ();
+ sregs->tottime += get_time() - sregs->starttime;
+- restore_stdio();
++ ms->restore_stdio ();
+ clearerr(stdin);
+ if (sregs->err_mode)
+- error_mode(sregs->pc);
++ ms->error_mode (sregs->pc);
+ if (sregs->err_mode)
+ return ERROR;
+ if (sregs->bphit) {
+@@ -254,7 +251,7 @@ sim_open (kind, callback, abfd, argv)
+ #endif
+ reset_all();
+ ebase.simtime = 0;
+- init_sim();
++ ms->init_sim ();
+ init_bpt(&sregs);
+ reset_stat(&sregs);
+
+@@ -268,7 +265,7 @@ sim_close(sd, quitting)
+ int quitting;
+ {
+
+- exit_sim();
++ ms->exit_sim ();
+ fcntl(0, F_SETFL, termsave);
+
+ };
+@@ -336,7 +333,7 @@ sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length)
+ int i, len;
+
+ for (i = 0; i < length; i++) {
+- sis_memory_write ((mem + i) ^ EBT, &buf[i], 1);
++ ms->sis_memory_write ((mem + i) ^ EBT, &buf[i], 1);
+ }
+ return length;
+ }
+@@ -347,7 +344,7 @@ sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
+ int i, len;
+
+ for (i = 0; i < length; i++) {
+- sis_memory_read ((mem + i) ^ EBT, &buf[i], 1);
++ ms->sis_memory_read ((mem + i) ^ EBT, &buf[i], 1);
+ }
+ return length;
+ }
+@@ -435,7 +432,7 @@ flush_windows ()
+ #endif
+
+ for (i = 0; i < 16; i++)
+- memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
++ ms->memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
+ &ws);
+
+ if (win == cwp)
+@@ -465,6 +462,13 @@ sim_complete_command (SIM_DESC sd, const char *text, const char *word)
+ return NULL;
+ }
+
++int
++sim_stop (SIM_DESC sd)
++{
++ ctrl_c = 1;
++ return 1;
++}
++
+ #if 0 /* FIXME: These shouldn't exist. */
+
+ int
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index 19f80fa..a5c557b 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -40,16 +40,13 @@
+ #define HIST_LEN 64
+
+ extern struct disassemble_info dinfo;
+-extern struct pstate sregs;
+ extern struct estate ebase;
+
+-extern int ctrl_c;
+ extern int nfp;
+ extern int ift;
+ extern int wrp;
+ extern int rom8;
+ extern int uben;
+-extern int sis_verbose;
+ extern char *sis_version;
+ extern struct estate ebase;
+ extern struct evcell evbuf[];
+@@ -75,13 +72,13 @@ run_sim(sregs, icount, dis)
+ int irq, mexc, deb;
+
+ sregs->starttime = get_time();
+- init_stdio();
++ ms->init_stdio ();
+ if (sregs->err_mode) icount = 0;
+ deb = dis || sregs->histlen || sregs->bptnum;
+ irq = 0;
+ while (icount > 0) {
+
+- mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
++ mexc = ms->memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
+ sregs->icnt = 1;
+ if (sregs->annul) {
+ sregs->annul = 0;
+@@ -96,7 +93,7 @@ run_sim(sregs, icount, dis)
+ } else {
+ if (deb) {
+ if ((sregs->bphit = check_bpt(sregs)) != 0) {
+- restore_stdio();
++ ms->restore_stdio ();
+ return BPT_HIT;
+ }
+ if (sregs->histlen) {
+@@ -119,7 +116,7 @@ run_sim(sregs, icount, dis)
+ irq = 0;
+ sregs->err_mode = execute_trap(sregs);
+ if (sregs->err_mode) {
+- error_mode(sregs->pc);
++ ms->error_mode (sregs->pc);
+ icount = 0;
+ }
+ }
+@@ -131,7 +128,7 @@ run_sim(sregs, icount, dis)
+ }
+ }
+ sregs->tottime += get_time() - sregs->starttime;
+- restore_stdio();
++ ms->restore_stdio ();
+ if (sregs->err_mode)
+ return ERROR;
+ if (ctrl_c) {
+@@ -232,7 +229,7 @@ main(argc, argv)
+ ebase.simtime = 0;
+ reset_all();
+ init_bpt(&sregs);
+- init_sim();
++ ms->init_sim ();
+ if (lfile)
+ last_load_addr = bfd_load(argv[lfile]);
+ #ifdef STAT
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index 3e29a40..ec6bc28 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -158,25 +158,12 @@ struct irqcell {
+ /* Prototypes */
+
+ /* erc32.c */
+-extern void init_sim (void);
+-extern void reset (void);
+-extern void error_mode (uint32 pc);
+-extern void sim_halt (void);
+-extern void exit_sim (void);
+-extern void init_stdio (void);
+-extern void restore_stdio (void);
+-extern int memory_iread (uint32 addr, uint32 *data, int32 *ws);
+-extern int memory_read (int32 asi, uint32 addr, uint32 *data,
+- int32 sz, int32 *ws);
+-extern int memory_write (int32 asi, uint32 addr, uint32 *data,
+- int32 sz, int32 *ws);
+-extern int sis_memory_write (uint32 addr,
+- const unsigned char *data, uint32 length);
+-extern int sis_memory_read (uint32 addr, char *data,
+- uint32 length);
++extern const struct memsys erc32sys;
+
+ /* func.c */
+-extern struct pstate sregs;
++extern struct pstate sregs;
++extern int ctrl_c;
++extern int sis_verbose;
+ extern void set_regi (struct pstate *sregs, int32 reg,
+ uint32 rval);
+ extern void get_regi (struct pstate *sregs, int32 reg, char *buf);
+@@ -224,3 +211,24 @@ extern void set_fsr (uint32 fsr);
+ /* help.c */
+ extern void usage (void);
+ extern void gen_help (void);
++
++struct memsys {
++ void (*init_sim) (void);
++ void (*reset) (void);
++ void (*error_mode) (uint32 pc);
++ void (*sim_halt) (void);
++ void (*exit_sim) (void);
++ void (*init_stdio) (void);
++ void (*restore_stdio) (void);
++ int (*memory_iread) (uint32 addr, uint32 *data, int32 *ws);
++ int (*memory_read) (int32 asi, uint32 addr, uint32 *data,
++ int32 sz, int32 *ws);
++ int (*memory_write) (int32 asi, uint32 addr, uint32 *data,
++ int32 sz, int32 *ws);
++ int (*sis_memory_write) (uint32 addr,
++ const unsigned char *data, uint32 length);
++ int (*sis_memory_read) (uint32 addr, char *data,
++ uint32 length);
++};
++
++extern const struct memsys *ms;
+--
+2.7.4
+
+From 9fa14f370fedc21a38493ae6d8fd7a7fc331e63a Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri at gaisler.se>
+Date: Thu, 24 Dec 2015 09:41:50 -0500
+Subject: [PATCH 3/9] sim/erc32: Move local extern declarations into sis.h.
+
+ * erc32.c (ctrl_c, sis_verbose, sparclite, sparclite_board, rom8,
+ wrp, uben, uart_dev[], ext_irl, sregs): Remove extern declarations
+ * exec.c (sis_verbose, sparclite, ebase, nfp, ift, irqarr): As above.
+ * func.c (ebase, dinfo, ext_irl): As above.
+ (ebase, evbuf, irqarr, dinfo): Move declaration to top of file
+ * interf.c (dinfo, ebase, nfp, ift, rom8, wrp, uben, sis_version,
+ evbuf, irqarr, irqpend, ext_irl, sparclite, sparclite_board,
+ termsave, uart_dev): Remove extern declarations
+ * sis.c (dinfo, ebase, nfp, ift, rom8, wrp, uben, sis_version,
+ evbuf, irqarr, irqpend, ext_irl, sparclite, sparclite_board,
+ termsave, uart_dev, last_load_addr): Remove extern declarations
+ * sis.h (dinfo, ebase, nfp, ift, rom8, wrp, uben, sis_version,
+ evbuf, irqarr, irqpend, ext_irl, sparclite, sparclite_board,
+ termsave, uart_dev, last_load_addr): Add extern declarations
+---
+ sim/erc32/erc32.c | 10 ----------
+ sim/erc32/exec.c | 7 -------
+ sim/erc32/func.c | 12 ++++--------
+ sim/erc32/interf.c | 18 ------------------
+ sim/erc32/sis.c | 20 --------------------
+ sim/erc32/sis.h | 20 +++++++++++++++++++-
+ 6 files changed, 23 insertions(+), 64 deletions(-)
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index 2e1ed03..5c9755c 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -30,12 +30,6 @@
+ #include "sis.h"
+ #include "sim-config.h"
+
+-extern int ctrl_c;
+-extern int32 sis_verbose;
+-extern int32 sparclite, sparclite_board;
+-extern int rom8,wrp,uben;
+-extern char uart_dev1[], uart_dev2[];
+-
+ /* MEC registers */
+ #define MEC_START 0x01f80000
+ #define MEC_END 0x01f80100
+@@ -290,8 +284,6 @@ static unsigned char *
+ static void store_bytes (unsigned char *mem, uint32 waddr,
+ uint32 *data, int sz, int32 *ws);
+
+-extern int ext_irl;
+-
+ /* One-time init */
+
+ static void
+@@ -1855,8 +1847,6 @@ sis_memory_read(addr, data, length)
+ return length;
+ }
+
+-extern struct pstate sregs;
+-
+ void
+ boot_init (void)
+ {
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index 99220d4..3c08123 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -21,7 +21,6 @@
+ #include <math.h>
+ #include <stdio.h>
+
+-extern int32 sis_verbose, sparclite;
+ int ext_irl = 0;
+
+ /* Load/store interlock delay */
+@@ -225,10 +224,6 @@ static int fpexec (uint32 op3, uint32 rd, uint32 rs1, uint32 rs2,
+ struct pstate *sregs);
+ static int chk_asi (struct pstate *sregs, uint32 *asi, uint32 op3);
+
+-
+-extern struct estate ebase;
+-extern int32 nfp,ift;
+-
+ #ifdef ERRINJ
+ extern uint32 errtt, errftt;
+ #endif
+@@ -2014,8 +2009,6 @@ execute_trap(sregs)
+
+ }
+
+-extern struct irqcell irqarr[16];
+-
+ int
+ check_interrupts(sregs)
+ struct pstate *sregs;
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index 94750e4..af61e24 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -37,7 +37,10 @@ int tty_setup = 1;
+
+ struct disassemble_info dinfo;
+ struct pstate sregs;
+-extern struct estate ebase;
++struct estate ebase;
++struct evcell evbuf[EVENT_MAX];
++struct irqcell irqarr[16];
++
+ int ctrl_c = 0;
+ int sis_verbose = 0;
+ char *sis_version = "2.7.5";
+@@ -51,7 +54,6 @@ int sparclite = 0; /* emulating SPARClite instructions? */
+ int sparclite_board = 0; /* emulating SPARClite board RAM? */
+ char uart_dev1[128] = "";
+ char uart_dev2[128] = "";
+-extern int ext_irl;
+ uint32 last_load_addr = 0;
+ int nouartrx = 0;
+ host_callback *sim_callback;
+@@ -716,12 +718,6 @@ init_signals()
+ }
+
+
+-extern struct disassemble_info dinfo;
+-
+-struct estate ebase;
+-struct evcell evbuf[EVENT_MAX];
+-struct irqcell irqarr[16];
+-
+ static int
+ disp_fpu(sregs)
+ struct pstate *sregs;
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 20577de..a7cc107 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -33,24 +33,6 @@
+
+ #define PSR_CWP 0x7
+
+-extern struct disassemble_info dinfo;
+-extern struct estate ebase;
+-
+-extern int nfp;
+-extern int ift;
+-extern int rom8;
+-extern int wrp;
+-extern int uben;
+-extern char *sis_version;
+-extern struct estate ebase;
+-extern struct evcell evbuf[];
+-extern struct irqcell irqarr[];
+-extern int irqpend, ext_irl;
+-extern int sparclite;
+-extern int sparclite_board;
+-extern int termsave;
+-extern char uart_dev1[], uart_dev2[];
+-
+ int sis_gdb_break = 1;
+
+ int
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index a5c557b..58478ef 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -39,26 +39,6 @@
+ /* Command history buffer length - MUST be binary */
+ #define HIST_LEN 64
+
+-extern struct disassemble_info dinfo;
+-extern struct estate ebase;
+-
+-extern int nfp;
+-extern int ift;
+-extern int wrp;
+-extern int rom8;
+-extern int uben;
+-extern char *sis_version;
+-extern struct estate ebase;
+-extern struct evcell evbuf[];
+-extern struct irqcell irqarr[];
+-extern int irqpend, ext_irl;
+-extern int termsave;
+-extern int sparclite;
+-extern int dumbio;
+-extern char uart_dev1[];
+-extern char uart_dev2[];
+-extern uint32 last_load_addr;
+-
+ #ifdef ERA
+ extern int era;
+ #endif
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index ec6bc28..7cf8feb 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -20,7 +20,7 @@
+ #include <sim-config.h>
+ #include <stdint.h>
+
+-#if HOST_BYTE_ORDER == BIG_ENDIAN
++#ifdef WORDS_BIGENDIAN
+ #define HOST_BIG_ENDIAN
+ #define EBT 0
+ #else
+@@ -162,8 +162,25 @@ extern const struct memsys erc32sys;
+
+ /* func.c */
+ extern struct pstate sregs;
++extern struct estate ebase;
++extern struct evcell evbuf[];
++extern struct irqcell irqarr[];
++extern int nfp;
++extern int ift;
+ extern int ctrl_c;
+ extern int sis_verbose;
++extern char *sis_version;
++extern int sparclite;
++extern int sparclite_board;
++extern uint32 last_load_addr;
++extern int wrp;
++extern int rom8;
++extern int uben;
++extern int irqpend;
++extern int ext_irl;
++extern int termsave;
++extern char uart_dev1[];
++extern char uart_dev2[];
+ extern void set_regi (struct pstate *sregs, int32 reg,
+ uint32 rval);
+ extern void get_regi (struct pstate *sregs, int32 reg, char *buf);
+@@ -174,6 +191,7 @@ extern void init_bpt (struct pstate *sregs);
+ extern void init_signals (void);
+
+ struct disassemble_info;
++extern struct disassemble_info dinfo;
+ extern void dis_mem (uint32 addr, uint32 len,
+ struct disassemble_info *info);
+ extern void event (void (*cfunc) (), int32 arg, uint64 delta);
+--
+2.7.4
+
+From 2ad488950209768810c41f753e56af85e04d79c5 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri at gaisler.se>
+Date: Sun, 27 Dec 2015 19:46:23 -0500
+Subject: [PATCH 4/9] Add support for LEON3 processor emulation.
+
+ Added memory and I/O sub-system to emulate a LEON3 processor.
+ The cache and MMU are not emulated but enough functionallity
+ is provided to run any RTEMS and BCC compiled application.
+ The code is based on erc32.c and modified to emulate the
+ LEON3 address space and peripheral operations.
+
+ * Makefile.in: Added new object files
+ * README.leon3: New file, documentation for leon3 emulation
+ * README.sis: Updated documentation for simulator commands
+ * grlib.c: New file, emulates leon3/grlib peripheral devices
+ * grlib.h: New file, definition of grlib plug&play values
+ * leon3.c: New file, emulation of leon3 memory and interrupt controller
+ * erc32.c (memory_read, memory_write): Remove asi from parameters,
+ compute locally.
+ (memory_read_asi, memory_write_asi): New memory function with asi
+ parameter.
+ (get_mem_ptr): Allow reading of I/O registers if access has exactly
+ 4 byte size.
+ (boot_init): Mark as static. Add new struct members.
+ * exec.c (dispatch_instruction): Emulate leon3 V8 mul/div and asr17.
+ Emulate LDA/LDDA/LDUBA/LDUHA/LDSTA/SWAPA/STA/STBA/SHA/STDA instructions
+ separately.
+ (fpexec): Use integer operations for FMOV to avoid FPU traps on x86.
+ (execute_trap): Support single vector trapping for leon3
+ (init_regs): Add leon3 vendor/device ID to %psr.
+ * func.c (sis_version): Set version to 2.8 to indicate support of leon3.
+ (exec_cmd): Call boot_init through memsys structure. Set PC to start
+ address of last loaded binary, and initialize registers if not 0.
+ (show_stat): Use 64-bit floats when calculating simulator statistics.
+ * interf.c (run_sim): Call boot_init through memsys struct. Add -leon3
+ option.
+ (sim_open): Set leon3 default frequency to 50 MHz. Print out current
+ emulation mode (erc32/leon3).
+ (flush_windows): Skip asi when flushing windows.
+ * sis.c (main): Update maintainer email. Add -leon3 switch. Set default
+ leon3 frequency to 50 MHz. Print out current emulation mode.
+ * sis.h: Add memsys struct for leon3.
+---
+ sim/erc32/Makefile.in | 8 +-
+ sim/erc32/README.leon3 | 53 +++
+ sim/erc32/README.sis | 83 ++--
+ sim/erc32/erc32.c | 50 ++-
+ sim/erc32/exec.c | 226 ++++++++--
+ sim/erc32/func.c | 58 +--
+ sim/erc32/grlib.c | 106 +++++
+ sim/erc32/grlib.h | 60 +++
+ sim/erc32/interf.c | 26 +-
+ sim/erc32/leon3.c | 1067 ++++++++++++++++++++++++++++++++++++++++++++++++
+ sim/erc32/sis.c | 22 +-
+ sim/erc32/sis.h | 14 +-
+ 12 files changed, 1643 insertions(+), 130 deletions(-)
+ create mode 100644 sim/erc32/README.leon3
+ create mode 100644 sim/erc32/grlib.c
+ create mode 100644 sim/erc32/grlib.h
+ create mode 100644 sim/erc32/leon3.c
+
+diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
+index 8f140b4..f1d6589 100644
+--- a/sim/erc32/Makefile.in
++++ b/sim/erc32/Makefile.in
+@@ -21,7 +21,10 @@
+ TERMCAP_LIB = @TERMCAP@
+ READLINE_LIB = @READLINE@
+
+-SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o
++# `sis' doesn't need interf.o.
++SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o
++
++SIM_OBJS = $(SIS_OFILES) interf.o
+ SIM_RUN_OBJS = sis.o
+ SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
+ SIM_EXTRA_ALL = sis
+@@ -35,9 +38,6 @@ SIM_EXTRA_CFLAGS = -DFAST_UART -I$(srcroot)
+
+ ## COMMON_POST_CONFIG_FRAG
+
+-# `sis' doesn't need interf.o.
+-SIS_OFILES = exec.o erc32.o func.o help.o float.o
+-
+ sis: sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) -o sis \
+ sis.o $(SIS_OFILES) $(COMMON_OBJS) $(EXTRA_LIBS)
+diff --git a/sim/erc32/README.leon3 b/sim/erc32/README.leon3
+new file mode 100644
+index 0000000..e6d5f5e
+--- /dev/null
++++ b/sim/erc32/README.leon3
+@@ -0,0 +1,53 @@
++
++1. LEON3 emulation
++
++The file 'leon3.c' contains a model of simple LEON3 sub-system. It
++contains 16 Mbyte ROM and 16 Mbyte RAM. Standard peripherals
++such as interrupt controller, UART and timer are provided.
++The model can execute leon3 binaries that do not require an
++MMU.
++
++To start sis in Leon3 mode, add the -leon3 switch. In gdb,
++use 'target sim -leon3' .
++
++1.1 UART
++
++The UART emulates an APBUART and is located at address 0x80000100.
++The following registers are implemented:
++
++- UART RX and TX register (0x80000100)
++- UART status register (0x80000104)
++
++The UART generates interrupt 3.
++
++1.2 Timer unit (GPTIMER)
++
++The GPTIMER programmable counter is emulated and located at
++address 0x80000300. It is configured with two timers and separate
++interrupts (8 and 9).
++
++1.3 Interrupt controller
++
++The IRQMP interrupt controller is implemented as described in the
++GRLIB IP manual, with the exception of the interrupt level register.
++Extended interrupts are not supported. The registers are located
++at address 0x80000200.
++
++1.5 Memory interface
++
++The following memory areas are valid for the Leon3 simulator:
++
++0x00000000 - 0x01000000 ROM (16 Mbyte, loaded at start-up)
++0x40000000 - 0x41000000 RAM (16 Mbyte, loaded at start-up)
++0x80000000 - 0x81000000 APB bus, including plug&play
++0xFFFFF000 - 0xFFFFFFFF AHB plug&play area
++
++Access to non-existing memory will result in a memory exception trap.
++
++1.8 Power-down mode
++
++The Leon3 power-down feature (%asr19) is supported. When power-down is
++entered, time is skipped forward until the next event in the event queue.
++However, if the simulator event queue is empty, power-down mode is not
++entered since no interrupt would be generated to exit from the mode. A
++Ctrl-C in the simulator window will exit the power-down mode.
+diff --git a/sim/erc32/README.sis b/sim/erc32/README.sis
+index b119f03..db6b4cc 100644
+--- a/sim/erc32/README.sis
++++ b/sim/erc32/README.sis
+@@ -1,10 +1,10 @@
+
+-SIS - Sparc Instruction Simulator README file (v2.0, 05-02-1996)
++SIS - Sparc Instruction Simulator README file (v2.8, 10-11-2014)
+ -------------------------------------------------------------------
+
+ 1. Introduction
+
+-The SIS is a SPARC V7 architecture simulator. It consist of two parts,
++The SIS is a SPARC V7/V8 architecture simulator. It consist of two parts,
+ the simulator core and a user defined memory module. The simulator
+ core executes the instructions while the memory module emulates memory
+ and peripherals.
+@@ -13,28 +13,28 @@ and peripherals.
+
+ The simulator is started as follows:
+
+-sis [-uart1 uart_device1] [-uart2 uart_device2]
++sis [-leon3] [-uart1 uart_device1] [-uart2 uart_device2]
+ [-nfp] [-freq frequency] [-c batch_file] [files]
+
+-The default uart devices for SIS are /dev/ptypc and /dev/ptypd. The
+--uart[1,2] switch can be used to connect the uarts to other devices.
+-Use 'tip /dev/ttypc' to connect a terminal emulator to the uarts.
++By default, SIS emulates an ERC32 system. The -leon3 switch
++enables emulation of a LEON3 SOC system.
++
++The emulated console uart is connected to stdin/stdout. The -uart[1,2]
++switch can be used to connect the uarts to other devices.
++
+ The '-nfp' will disable the simulated FPU, so each FPU instruction will
+ generate a FPU disabled trap. The '-freq' switch can be used to define
+ which "frequency" the simulator runs at. This is used by the 'perf'
+ command to calculated the MIPS figure for a particular configuration.
+-The give frequency must be an integer indicating the frequency in MHz.
++The frequency must be an integer indicating the frequency in MHz.
+
+ The -c option indicates that sis commands should be read from 'batch_file'
+ at startup.
+
+-Files to be loaded must be in one of the supported formats (see INSTALLATION),
+-and will be loaded into the simulated memory. The file formats are
+-automatically recognised.
++Files to be loaded must be in one of the supported formats (elf, a.out, srec),
++and will be loaded into the simulated memory.
+
+-The script 'startsim' will start the simulator in one xterm window and
+-open a terminal emulator (tip) connected to the UART A in a second
+-xterm window. Below is description of commands that are recognized by
++Below is description of commands that are recognized by
+ the simulator. The command-line is parsed using GNU readline. A command
+ history of 64 commands is maintained. Use the up/down arrows to recall
+ previous commands. For more details, see the readline documentation.
+@@ -77,8 +77,8 @@ Prints the FPU registers
+ go <address> [inst_count]
+
+ The go command will set pc to <address> and npc to <address> + 4, and start
+-execution. No other initialisation will be done. If inst_count is given,
+-execution will stop after the specified number of instructions.
++execution. If inst_count is given, execution will stop after the specified
++number of instructions.
+
+ help
+
+@@ -112,7 +112,7 @@ command also resets the statistic information.
+
+ reg [reg_name] [value]
+
+-Prints and sets the IU regiters. 'reg' without parameters prints the IU
++Prints and sets the IU registers. 'reg' without parameters prints the IU
+ registers. 'reg [reg_name] [value]' sets the corresponding register to
+ [value]. Valid register names are psr, tbr, wim, y, g1-g7, o0-o7 and
+ l0-l7.
+@@ -146,14 +146,20 @@ interpreted as 'cont'.
+
+ 3. Simulator core
+
+-The SIS emulates the behavior of the 90C601E and 90C602E sparc IU and
+-FPU from Matra MHS. These are roughly equivalent to the Cypress C601
+-and C602. The simulator is cycle true, i.e a simulator time is
+-maintained and inremented according the IU and FPU instruction timing.
++In ERC32 mode, SIS emulates the behavior of the 90C601E and 90C602E
++sparc IU and FPU from Matra MHS. These are roughly equivalent to the
++Cypress C601 and C602. The simulator is cycle accurate, i.e a simulator
++time is maintained and incremented according the IU and FPU instruction timing.
+ The parallel execution between the IU and FPU is modelled, as well as
+-stalls due to operand dependencies (FPU). The core interacts with the
+-user-defined memory modules through a number of functions. The memory
+-module must provide the following functions:
++stalls due to operand dependencies (FPU).
++
++In Leon3 mode, the core emulates the Leon3 SPARC V8 core from
++Gaisler Research. All SPARC V8 instructions are supported but
++emulation is not fully cycle-true as the cache is not emulated.
++
++The core interacts with the user-defined memory modules through
++a number of functions. The memory module must provide the following
++functions:
+
+ int memory_read(asi,addr,data,ws)
+ int asi;
+@@ -272,7 +278,7 @@ See 'erc32.c' for examples on how to use events and interrupts.
+
+ 5. Memory module
+
+-The supplied memory module (erc32.c) emulates the functions of memory and
++The ERC32 memory module (erc32.c) emulates the functions of memory and
+ the MEC asic developed for the 90C601/2. It includes the following functions:
+
+ * UART A & B
+@@ -284,28 +290,27 @@ the MEC asic developed for the 90C601/2. It includes the following functions:
+ * 512 Kbyte ROM
+ * 4 Mbyte RAM
+
+-See README.erc32 on how the MEC functions are emulated. For a detailed MEC
+-specification, look at the ERC32 home page at URL:
++See README.erc32 on how the MEC functions are emulated.
+
+-http://www.estec.esa.nl/wsmwww/erc32
++The Leon3 memory module (leon3.c) emulates on-chip peripherals and
++external memory for a simple Leon3 system. The modules includes the
++following functions:
+
+-6. Compile and linking programs
++* AHB and APB buses with plug&play
++* UART (APBUART)
++* Interrupt controller (IRQMP)
++* Timer unit with two timers (GPTIMER)
++* PROM/SRAM memory controller (SRCTRL)
++* 16 Mbyte PROM, 16 Mbyte SRAM
+
+-The directory 'examples' contain some code fragments for SIS.
+-The script gccx indicates how the native sunos gcc and linker can be used
+-to produce executables for the simulator. To compile and link the provided
+-'hello.c', type 'gccx hello.c'. This will build the executable 'hello'.
+-Start the simulator by running 'startsim hello', and issue the command 'run.
+-After the program is terminated, the IU will be force to error mode through
+-a software trap and halt.
++See README.leon3 for further details on Leon3 emulation.
+
+-The programs are linked with a start-up file, srt0.S. This file includes
+-the traptable and window underflow/overflow trap routines.
++6. Compile and linking programs
+
+ 7. IU and FPU instruction timing.
+
+-The simulator provides cycle true simulation. The following table shows
+-the emulated instruction timing for 90C601E & 90C602E:
++The simulator provides cycle true simulation for ERC32. The following table
++shows the emulated instruction timing for 90C601E & 90C602E:
+
+ Instructions Cycles
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index 5c9755c..439abf1 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -1613,19 +1613,16 @@ memory_iread (uint32 addr, uint32 *data, int32 *ws)
+ }
+
+ static int
+-memory_read(asi, addr, data, sz, ws)
+- int32 asi;
+- uint32 addr;
+- uint32 *data;
+- int32 sz;
+- int32 *ws;
++memory_read (uint32 addr, uint32 *data, int32 sz, int32 *ws)
+ {
+ int32 mexc;
++ int32 asi;
+
+ #ifdef ERRINJ
+ if (errmec) {
+ if (sis_verbose)
+ printf("Inserted MEC error %d\n",errmec);
++ asi = (sregs.psr & 0x080) ? 11 : 10;
+ set_sfsr(errmec, addr, asi, 1);
+ if (errmec == 5) mecparerror();
+ if (errmec == 6) iucomperr();
+@@ -1639,6 +1636,7 @@ memory_read(asi, addr, data, sz, ws)
+ *ws = mem_ramr_ws;
+ return 0;
+ } else if ((addr >= MEC_START) && (addr < MEC_END)) {
++ asi = (sregs.psr & 0x080) ? 11 : 10;
+ mexc = mec_read(addr, asi, data);
+ if (mexc) {
+ set_sfsr(MEC_ACC, addr, asi, 1);
+@@ -1678,18 +1676,20 @@ memory_read(asi, addr, data, sz, ws)
+
+ if (sis_verbose)
+ printf ("Memory exception at %x (illegal address)\n", addr);
++ asi = (sregs.psr & 0x080) ? 11 : 10;
+ set_sfsr(UIMP_ACC, addr, asi, 1);
+ *ws = MEM_EX_WS;
+ return 1;
+ }
+
+ static int
+-memory_write(asi, addr, data, sz, ws)
+- int32 asi;
+- uint32 addr;
+- uint32 *data;
+- int32 sz;
+- int32 *ws;
++memory_read_asi (int32 asi, uint32 addr, uint32 *data, int32 sz, int32 *ws)
++{
++ return memory_read (addr, data, sz, ws);
++}
++
++static int
++memory_write (uint32 addr, uint32 *data, int32 sz, int32 *ws)
+ {
+ uint32 byte_addr;
+ uint32 byte_mask;
+@@ -1698,11 +1698,13 @@ memory_write(asi, addr, data, sz, ws)
+ int32 mexc;
+ int i;
+ int wphit[2];
++ int asi;
+
+ #ifdef ERRINJ
+ if (errmec) {
+ if (sis_verbose)
+ printf("Inserted MEC error %d\n",errmec);
++ asi = (sregs.psr & 0x080) ? 11 : 10;
+ set_sfsr(errmec, addr, asi, 0);
+ if (errmec == 5) mecparerror();
+ if (errmec == 6) iucomperr();
+@@ -1715,6 +1717,7 @@ memory_write(asi, addr, data, sz, ws)
+ if (mem_accprot) {
+
+ waddr = (addr & 0x7fffff) >> 2;
++ asi = (sregs.psr & 0x080) ? 11 : 10;
+ for (i = 0; i < 2; i++)
+ wphit[i] =
+ (((asi == 0xa) && (mec_wpr[i] & 1)) ||
+@@ -1736,6 +1739,7 @@ memory_write(asi, addr, data, sz, ws)
+ store_bytes (ramb, waddr, data, sz, ws);
+ return 0;
+ } else if ((addr >= MEC_START) && (addr < MEC_END)) {
++ asi = (sregs.psr & 0x080) ? 11 : 10;
+ if ((sz != 2) || (asi != 0xb)) {
+ set_sfsr(MEC_ACC, addr, asi, 0);
+ *ws = MEM_EX_WS;
+@@ -1792,10 +1796,17 @@ memory_write(asi, addr, data, sz, ws)
+ }
+
+ *ws = MEM_EX_WS;
++ asi = (sregs.psr & 0x080) ? 11 : 10;
+ set_sfsr(UIMP_ACC, addr, asi, 0);
+ return 1;
+ }
+
++static int
++memory_write_asi (int32 asi, uint32 addr, uint32 *data, int32 sz, int32 *ws)
++{
++ return memory_write (addr, data, sz, ws);
++}
++
+ static unsigned char *
+ get_mem_ptr(addr, size)
+ uint32 addr;
+@@ -1839,6 +1850,14 @@ sis_memory_read(addr, data, length)
+ uint32 length;
+ {
+ char *mem;
++ int ws;
++ int w4;
++
++ if (length == 4) {
++ memory_read (addr, &w4, length, &ws);
++ memcpy(data, &w4, length);
++ return 4;
++ }
+
+ if ((mem = get_mem_ptr(addr, length)) == ((char *) -1))
+ return 0;
+@@ -1847,7 +1866,7 @@ sis_memory_read(addr, data, length)
+ return length;
+ }
+
+-void
++static void
+ boot_init (void)
+ {
+ mec_write(MEC_WCR, 0); /* zero waitstates */
+@@ -1871,7 +1890,10 @@ const struct memsys erc32sys = {
+ restore_stdio,
+ memory_iread,
+ memory_read,
++ memory_read_asi,
+ memory_write,
++ memory_write_asi,
+ sis_memory_write,
+- sis_memory_read
++ sis_memory_read,
++ boot_init
+ };
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index 3c08123..4f15320 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -1062,17 +1062,14 @@ dispatch_instruction(sregs)
+ *rdd = sregs->psr;
+ break;
+ case RDY:
+- if (!sparclite)
++ if ((!sparclite) && (cputype != CPU_LEON3))
+ *rdd = sregs->y;
+ else {
+ int rs1_is_asr = (sregs->inst >> 14) & 0x1f;
+ if ( 0 == rs1_is_asr )
+ *rdd = sregs->y;
+- else if ( 17 == rs1_is_asr )
++ else if ( 17 == rs1_is_asr ) {
+ *rdd = sregs->asr17;
+- else {
+- sregs->trap = TRAP_UNIMP;
+- break;
+ }
+ }
+ break;
+@@ -1118,16 +1115,18 @@ dispatch_instruction(sregs)
+ ((rs1 ^ operand2) & 0xfffff000);
+ break;
+ case WRY:
+- if (!sparclite)
++ if ((!sparclite) && (cputype != CPU_LEON3))
+ sregs->y = (rs1 ^ operand2);
+ else {
+ if ( 0 == rd )
+ sregs->y = (rs1 ^ operand2);
+- else if ( 17 == rd )
+- sregs->asr17 = (rs1 ^ operand2);
+- else {
+- sregs->trap = TRAP_UNIMP;
+- break;
++ else if ( 17 == rd ) {
++ if (sparclite)
++ sregs->asr17 = (rs1 ^ operand2);
++ }
++ else if ( 19 == rd ) {
++ if (cputype == CPU_LEON3)
++ wait_for_irq();
+ }
+ }
+ break;
+@@ -1224,6 +1223,32 @@ dispatch_instruction(sregs)
+ switch (op3) {
+ case LDDA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ if (address & 0x7) {
++ sregs->trap = TRAP_UNALI;
++ break;
++ }
++ if (rd & 1) {
++ rd &= 0x1e;
++ if (rd > 7)
++ rdd = &(sregs->r[(cwp + rd) & 0x7f]);
++ else
++ rdd = &(sregs->g[rd]);
++ }
++ mexc = ms->memory_read_asi (asi, address, ddata, 2, &ws);
++ sregs->hold += ws;
++ mexc |= ms->memory_read_asi (asi, address+4, &ddata[1], 2, &ws);
++ sregs->hold += ws;
++ sregs->icnt = T_LDD;
++ if (mexc)
++ sregs->trap = TRAP_DEXC;
++ else {
++ rdd[0] = ddata[0];
++ rdd[1] = ddata[1];
++#ifdef STAT
++ sregs->nload++; /* Double load counts twice */
++#endif
++ }
++ break;
+ case LDD:
+ if (address & 0x7) {
+ sregs->trap = TRAP_UNALI;
+@@ -1236,9 +1261,9 @@ dispatch_instruction(sregs)
+ else
+ rdd = &(sregs->g[rd]);
+ }
+- mexc = ms->memory_read (asi, address, ddata, 2, &ws);
++ mexc = ms->memory_read (address, ddata, 2, &ws);
+ sregs->hold += ws;
+- mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws);
++ mexc |= ms->memory_read (address+4, &ddata[1], 2, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_LDD;
+ if (mexc) {
+@@ -1254,12 +1279,23 @@ dispatch_instruction(sregs)
+
+ case LDA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ if (address & 0x3) {
++ sregs->trap = TRAP_UNALI;
++ break;
++ }
++ mexc = ms->memory_read_asi (asi, address, &data, 2, &ws);
++ sregs->hold += ws;
++ if (mexc)
++ sregs->trap = TRAP_DEXC;
++ else
++ *rdd = data;
++ break;
+ case LD:
+ if (address & 0x3) {
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = ms->memory_read (asi, address, &data, 2, &ws);
++ mexc = ms->memory_read (address, &data, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1269,8 +1305,26 @@ dispatch_instruction(sregs)
+ break;
+ case LDSTUBA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ mexc = ms->memory_read_asi (asi, address, &data, 0, &ws);
++ sregs->hold += ws;
++ sregs->icnt = T_LDST;
++ if (mexc) {
++ sregs->trap = TRAP_DEXC;
++ break;
++ }
++ data = extract_byte (data, address);
++ *rdd = data;
++ data = 0x0ff;
++ mexc = ms->memory_write_asi (asi, address, &data, 0, &ws);
++ sregs->hold += ws;
++ if (mexc)
++ sregs->trap = TRAP_DEXC;
++#ifdef STAT
++ sregs->nload++;
++#endif
++ break;
+ case LDSTUB:
+- mexc = ms->memory_read (asi, address, &data, 0, &ws);
++ mexc = ms->memory_read (address, &data, 0, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_LDST;
+ if (mexc) {
+@@ -1280,7 +1334,7 @@ dispatch_instruction(sregs)
+ data = extract_byte (data, address);
+ *rdd = data;
+ data = 0x0ff;
+- mexc = ms->memory_write (asi, address, &data, 0, &ws);
++ mexc = ms->memory_write (address, &data, 0, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1292,9 +1346,21 @@ dispatch_instruction(sregs)
+ case LDSBA:
+ case LDUBA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ mexc = ms->memory_read_asi (asi, address, &data, 0, &ws);
++ sregs->hold += ws;
++ if (mexc) {
++ sregs->trap = TRAP_DEXC;
++ break;
++ }
++ if (op3 == LDSB)
++ data = extract_byte_signed (data, address);
++ else
++ data = extract_byte (data, address);
++ *rdd = data;
++ break;
+ case LDSB:
+ case LDUB:
+- mexc = ms->memory_read (asi, address, &data, 0, &ws);
++ mexc = ms->memory_read (address, &data, 0, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1309,13 +1375,29 @@ dispatch_instruction(sregs)
+ case LDSHA:
+ case LDUHA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ if (address & 0x1) {
++ sregs->trap = TRAP_UNALI;
++ break;
++ }
++ mexc = ms->memory_read_asi (asi, address, &data, 1, &ws);
++ sregs->hold += ws;
++ if (mexc) {
++ sregs->trap = TRAP_DEXC;
++ break;
++ }
++ if (op3 == LDSH)
++ data = extract_short_signed (data, address);
++ else
++ data = extract_short (data, address);
++ *rdd = data;
++ break;
+ case LDSH:
+ case LDUH:
+ if (address & 0x1) {
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = ms->memory_read (asi, address, &data, 1, &ws);
++ mexc = ms->memory_read (address, &data, 1, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1341,7 +1423,7 @@ dispatch_instruction(sregs)
+ (sregs->frs2 == rd))
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = ms->memory_read (asi, address, &data, 2, &ws);
++ mexc = ms->memory_read (address, &data, 2, &ws);
+ sregs->hold += ws;
+ sregs->flrd = rd;
+ sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
+@@ -1367,9 +1449,9 @@ dispatch_instruction(sregs)
+ ((sregs->frs2 >> 1) == (rd >> 1)))
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = ms->memory_read (asi, address, ddata, 2, &ws);
++ mexc = ms->memory_read (address, ddata, 2, &ws);
+ sregs->hold += ws;
+- mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws);
++ mexc |= ms->memory_read (address+4, &ddata[1], 2, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_LDD;
+ if (mexc) {
+@@ -1398,7 +1480,7 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = ms->memory_read (asi, address, &data, 2, &ws);
++ mexc = ms->memory_read (address, &data, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1420,7 +1502,7 @@ dispatch_instruction(sregs)
+ if (ebase.simtime < sregs->ftime) {
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = ms->memory_write (asi, address, &sregs->fsr, 2, &ws);
++ mexc = ms->memory_write (address, &sregs->fsr, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1429,12 +1511,21 @@ dispatch_instruction(sregs)
+
+ case STA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ if (address & 0x3) {
++ sregs->trap = TRAP_UNALI;
++ break;
++ }
++ mexc = ms->memory_write_asi (asi, address, rdd, 2, &ws);
++ sregs->hold += ws;
++ if (mexc)
++ sregs->trap = TRAP_DEXC;
++ break;
+ case ST:
+ if (address & 0x3) {
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = ms->memory_write (asi, address, rdd, 2, &ws);
++ mexc = ms->memory_write (address, rdd, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1442,8 +1533,13 @@ dispatch_instruction(sregs)
+ break;
+ case STBA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ mexc = ms->memory_write_asi (asi, address, rdd, 0, &ws);
++ sregs->hold += ws;
++ if (mexc)
++ sregs->trap = TRAP_DEXC;
++ break;
+ case STB:
+- mexc = ms->memory_write (asi, address, rdd, 0, &ws);
++ mexc = ms->memory_write (address, rdd, 0, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1451,6 +1547,28 @@ dispatch_instruction(sregs)
+ break;
+ case STDA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ if (address & 0x7) {
++ sregs->trap = TRAP_UNALI;
++ break;
++ }
++ if (rd & 1) {
++ rd &= 0x1e;
++ if (rd > 7)
++ rdd = &(sregs->r[(cwp + rd) & 0x7f]);
++ else
++ rdd = &(sregs->g[rd]);
++ }
++ mexc = ms->memory_write_asi (asi, address, rdd, 3, &ws);
++ sregs->hold += ws;
++ sregs->icnt = T_STD;
++#ifdef STAT
++ sregs->nstore++; /* Double store counts twice */
++#endif
++ if (mexc) {
++ sregs->trap = TRAP_DEXC;
++ break;
++ }
++ break;
+ case STD:
+ if (address & 0x7) {
+ sregs->trap = TRAP_UNALI;
+@@ -1463,7 +1581,7 @@ dispatch_instruction(sregs)
+ else
+ rdd = &(sregs->g[rd]);
+ }
+- mexc = ms->memory_write (asi, address, rdd, 3, &ws);
++ mexc = ms->memory_write (address, rdd, 3, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_STD;
+ #ifdef STAT
+@@ -1492,7 +1610,7 @@ dispatch_instruction(sregs)
+ break;
+ }
+ rdd = &(sregs->fpq[0]);
+- mexc = ms->memory_write (asi, address, rdd, 3, &ws);
++ mexc = ms->memory_write (address, rdd, 3, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_STD;
+ #ifdef STAT
+@@ -1508,12 +1626,21 @@ dispatch_instruction(sregs)
+ break;
+ case STHA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ if (address & 0x1) {
++ sregs->trap = TRAP_UNALI;
++ break;
++ }
++ mexc = ms->memory_write_asi (asi, address, rdd, 1, &ws);
++ sregs->hold += ws;
++ if (mexc)
++ sregs->trap = TRAP_DEXC;
++ break;
+ case STH:
+ if (address & 0x1) {
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = ms->memory_write (asi, address, rdd, 1, &ws);
++ mexc = ms->memory_write (address, rdd, 1, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1532,7 +1659,7 @@ dispatch_instruction(sregs)
+ if (sregs->frd == rd)
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 2, &ws);
++ mexc = ms->memory_write (address, &sregs->fsi[rd], 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1552,7 +1679,7 @@ dispatch_instruction(sregs)
+ if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 3, &ws);
++ mexc = ms->memory_write (address, &sregs->fsi[rd], 3, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_STD;
+ #ifdef STAT
+@@ -1564,18 +1691,40 @@ dispatch_instruction(sregs)
+ break;
+ case SWAPA:
+ if (!chk_asi(sregs, &asi, op3)) break;
++ if (address & 0x3) {
++ sregs->trap = TRAP_UNALI;
++ break;
++ }
++ mexc = ms->memory_read_asi (asi, address, &data, 2, &ws);
++ sregs->hold += ws;
++ if (mexc) {
++ sregs->trap = TRAP_DEXC;
++ break;
++ }
++ mexc = ms->memory_write_asi (asi, address, rdd, 2, &ws);
++ sregs->hold += ws;
++ sregs->icnt = T_LDST;
++ if (mexc) {
++ sregs->trap = TRAP_DEXC;
++ break;
++ } else
++ *rdd = data;
++#ifdef STAT
++ sregs->nload++;
++#endif
++ break;
+ case SWAP:
+ if (address & 0x3) {
+ sregs->trap = TRAP_UNALI;
+ break;
+ }
+- mexc = ms->memory_read (asi, address, &data, 2, &ws);
++ mexc = ms->memory_read (address, &data, 2, &ws);
+ sregs->hold += ws;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+ break;
+ }
+- mexc = ms->memory_write (asi, address, rdd, 2, &ws);
++ mexc = ms->memory_write (address, rdd, 2, &ws);
+ sregs->hold += ws;
+ sregs->icnt = T_LDST;
+ if (mexc) {
+@@ -1811,7 +1960,7 @@ fpexec(op3, rd, rs1, rs2, sregs)
+ sregs->ftime += T_FDIVd;
+ break;
+ case FMOVs:
+- sregs->fs[rd] = sregs->fs[rs2];
++ sregs->fsi[rd] = sregs->fsi[rs2];
+ sregs->ftime += T_FMOVs;
+ sregs->frs1 = 32; /* rs1 ignored */
+ break;
+@@ -1993,7 +2142,7 @@ execute_trap(sregs)
+ sregs->pc = sregs->tbr;
+ sregs->npc = sregs->tbr + 4;
+
+- if ( 0 != (1 & sregs->asr17) ) {
++ if ( 0 != (1 & (sregs->asr17 >> 13)) ) {
+ /* single vector trapping! */
+ sregs->pc = sregs->tbr & 0xfffff000;
+ sregs->npc = sregs->pc + 4;
+@@ -2040,7 +2189,10 @@ init_regs(sregs)
+ sregs->npc = 4;
+ sregs->trap = 0;
+ sregs->psr &= 0x00f03fdf;
+- sregs->psr |= 0x11000080; /* Set supervisor bit */
++ if (cputype == CPU_LEON3)
++ sregs->psr |= 0xF3000080; /* Set supervisor bit */
++ else
++ sregs->psr |= 0x11000080; /* Set supervisor bit */
+ sregs->breakpoint = 0;
+ sregs->annul = 0;
+ sregs->fpstate = FP_EXE_MODE;
+@@ -2069,4 +2221,8 @@ init_regs(sregs)
+
+ sregs->rett_err = 0;
+ sregs->jmpltime = 0;
++ if (cputype == CPU_LEON3) {
++ sregs->asr17 = 0x107;
++ if (!nfp) sregs->asr17 |= (3 << 10); /* Meiko FPU */
++ }
+ }
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index af61e24..29fb667 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -26,6 +26,7 @@
+ #include <dis-asm.h>
+ #include "sim-config.h"
+ #include <inttypes.h>
++#include <sys/time.h>
+
+ #define VAL(x) strtoul(x,(char **)NULL,0)
+
+@@ -43,7 +44,7 @@ struct irqcell irqarr[16];
+
+ int ctrl_c = 0;
+ int sis_verbose = 0;
+-char *sis_version = "2.7.5";
++char *sis_version = "2.8";
+ int nfp = 0;
+ int ift = 0;
+ int wrp = 0;
+@@ -58,6 +59,7 @@ uint32 last_load_addr = 0;
+ int nouartrx = 0;
+ host_callback *sim_callback;
+ const struct memsys *ms = &erc32sys;
++int cputype = 0; /* 0 = erc32, 3 = leon3 */
+
+ #ifdef ERRINJ
+ uint32 errcnt = 0;
+@@ -469,7 +471,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ sregs->pc = len & ~3;
+ sregs->npc = sregs->pc + 4;
+ if ((sregs->pc != 0) && (ebase.simtime == 0))
+- boot_init();
++ ms->boot_init ();
+ printf("resuming at 0x%08x\n",sregs->pc);
+ if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
+ stat = run_sim(sregs, VAL(cmd2), 0);
+@@ -545,6 +547,11 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ ebase.simtime = 0;
+ reset_all();
+ reset_stat(sregs);
++ if (last_load_addr != 0) {
++ sregs->pc = last_load_addr & ~3;
++ sregs->npc = sregs->pc + 4;
++ }
++ if ((sregs->pc != 0) && (ebase.simtime == 0)) ms->boot_init ();
+ if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
+ stat = run_sim(sregs, UINT64_MAX, 0);
+ } else {
+@@ -598,6 +605,11 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ ebase.simtime = 0;
+ reset_all();
+ reset_stat(sregs);
++ if (last_load_addr != 0) {
++ sregs->pc = last_load_addr & ~3;
++ sregs->npc = sregs->pc + 4;
++ }
++ if ((sregs->pc != 0) && (ebase.simtime == 0)) ms->boot_init ();
+ sregs->tlimit = limcalc(sregs->freq);
+ stat = run_sim(sregs, UINT64_MAX, 0);
+ daddr = sregs->pc;
+@@ -635,8 +647,8 @@ void
+ show_stat(sregs)
+ struct pstate *sregs;
+ {
+- uint32 iinst;
+- uint32 stime;
++ uint64 iinst;
++ uint64 stime;
+
+ if (sregs->tottime == 0.0)
+ sregs->tottime += 1E-6;
+@@ -651,37 +663,37 @@ show_stat(sregs)
+ printf(" Instructions : %9" PRIu64 "\n", sregs->ninst);
+
+ #ifdef STAT
+- printf(" integer : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst);
++ printf (" integer : %9.2f %%\n", 100.0 * (double) iinst / (double) sregs->ninst);
+ printf(" load : %9.2f %%\n",
+- 100.0 * (float) sregs->nload / (float) sregs->ninst);
++ 100.0 * (double) sregs->nload / (double) sregs->ninst);
+ printf(" store : %9.2f %%\n",
+- 100.0 * (float) sregs->nstore / (float) sregs->ninst);
++ 100.0 * (double) sregs->nstore / (double) sregs->ninst);
+ printf(" branch : %9.2f %%\n",
+- 100.0 * (float) sregs->nbranch / (float) sregs->ninst);
++ 100.0 * (double) sregs->nbranch / (double) sregs->ninst);
+ printf(" float : %9.2f %%\n",
+- 100.0 * (float) sregs->finst / (float) sregs->ninst);
++ 100.0 * (double) sregs->finst / (double) sregs->ninst);
+ printf(" Integer CPI : %9.2f\n",
+- ((float) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst))
++ ((double) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst))
+ /
+- (float) (sregs->ninst - sregs->finst));
++ (double) (sregs->ninst - sregs->finst));
+ printf(" Float CPI : %9.2f\n",
+- ((float) sregs->fholdt / (float) sregs->finst) + 1.0);
++ ((double) sregs->fholdt / (double) sregs->finst) + 1.0);
+ #endif
+ printf(" Overall CPI : %9.2f\n",
+- (float) (stime - sregs->pwdtime) / (float) sregs->ninst);
+- printf("\n ERC32 performance (%4.1f MHz): %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n",
+- sregs->freq, sregs->freq * (float) sregs->ninst / (float) (stime - sregs->pwdtime),
+- sregs->freq * (float) (sregs->ninst - sregs->finst) /
+- (float) (stime - sregs->pwdtime),
+- sregs->freq * (float) sregs->finst / (float) (stime - sregs->pwdtime));
+- printf(" Simulated ERC32 time : %.2f s\n",
+- (float) (ebase.simtime - sregs->simstart) / 1000000.0 / sregs->freq);
++ (double) (stime - sregs->pwdtime) / (double) sregs->ninst);
++ printf ("\n CPU performance (%4.1f MHz) : %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n",
++ sregs->freq, sregs->freq * (double) sregs->ninst / (double) (stime - sregs->pwdtime),
++ sregs->freq * (double) (sregs->ninst - sregs->finst) /
++ (double) (stime - sregs->pwdtime),
++ sregs->freq * (double) sregs->finst / (double) (stime - sregs->pwdtime));
++ printf (" Simulated CPU time : %.2f s\n",
++ (double) (ebase.simtime - sregs->simstart) / 1000000.0 / sregs->freq);
+ printf(" Processor utilisation : %.2f %%\n",
+- 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime)));
++ 100.0 * (1.0 - ((double) sregs->pwdtime / (double) stime)));
+ printf(" Real-time performance : %.2f %%\n",
+- 100.0 / (sregs->tottime / ((double) (stime) / (sregs->freq * 1.0E6))));
++ 100.0 / (sregs->tottime / ((double) (stime) / (sregs->freq * 1.0E6))));
+ printf(" Simulator performance : %.2f MIPS\n",
+- (double)(sregs->ninst) / sregs->tottime / 1E6);
++ (double)(sregs->ninst) / sregs->tottime / 1E6);
+ printf(" Used time (sys + user) : %.2f s\n\n", sregs->tottime);
+ }
+
+diff --git a/sim/erc32/grlib.c b/sim/erc32/grlib.c
+new file mode 100644
+index 0000000..9932360
+--- /dev/null
++++ b/sim/erc32/grlib.c
+@@ -0,0 +1,106 @@
++/*
++ * This file is part of SIS.
++ *
++ * SIS, SPARC instruction simulator. Copyright (C) 2014 Jiri Gaisler
++ *
++ * This program is free software; you can redistribute it and/or modify it under
++ * the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 3 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, see <http://www.gnu.org/licenses/>.
++ *
++ */
++
++
++#include "sis.h"
++#include "grlib.h"
++
++
++/* APB PNP */
++
++static uint32 apbppmem[32 * 2]; /* 32-entry APB PP AREA */
++static int apbppindex;
++
++int
++grlib_apbpp_add (uint32 id, uint32 addr)
++{
++ apbppmem[apbppindex++] = id;
++ apbppmem[apbppindex++] = addr;
++ if (apbppindex >= (32 * 2))
++ apbppindex = 0; /* prevent overflow of area */
++ return apbppindex;
++}
++
++uint32
++grlib_apbpnp_read (uint32 addr)
++{
++ uint32 read_data;
++ addr &= 0xff;
++ read_data = apbppmem[addr >> 2];
++
++ return read_data;
++}
++
++/* AHB PNP */
++
++static uint32 ahbppmem[128 * 8]; /* 128-entry AHB PP AREA */
++static int ahbmppindex;
++static int ahbsppindex = 64 * 8;
++
++int
++grlib_ahbmpp_add (uint32 id)
++{
++ ahbppmem[ahbmppindex] = id;
++ ahbmppindex += 8;
++ if (ahbmppindex >= (64 * 8))
++ ahbmppindex = 0; /* prevent overflow of area */
++ return ahbmppindex;
++}
++
++int
++grlib_ahbspp_add (uint32 id, uint32 addr1, uint32 addr2,
++ uint32 addr3, uint32 addr4)
++{
++ ahbppmem[ahbsppindex] = id;
++ ahbsppindex += 4;
++ ahbppmem[ahbsppindex++] = addr1;
++ ahbppmem[ahbsppindex++] = addr2;
++ ahbppmem[ahbsppindex++] = addr3;
++ ahbppmem[ahbsppindex++] = addr4;
++ if (ahbsppindex >= (128 * 8))
++ ahbsppindex = 64 * 8; /* prevent overflow of area */
++ return ahbsppindex;
++}
++
++uint32
++grlib_ahbpnp_read (uint32 addr)
++{
++ uint32 read_data;
++
++ addr &= 0xfff;
++ read_data = ahbppmem[addr >> 2];
++ return read_data;
++
++}
++
++void
++grlib_init ()
++{
++ /* Add PP records for Leon3, APB bridge and interrupt controller
++ as this is not done elsewhere */
++
++ grlib_ahbmpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_LEON3, 0, 0));
++ grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_APBMST, 0, 0),
++ GRLIB_PP_AHBADDR (0x80000000, 0xFFF, 0, 0, 2), 0, 0, 0);
++
++ grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_IRQMP, 2, 0),
++ GRLIB_PP_APBADDR (0x80000200, 0xFFF));
++
++}
+diff --git a/sim/erc32/grlib.h b/sim/erc32/grlib.h
+new file mode 100644
+index 0000000..cf38dee
+--- /dev/null
++++ b/sim/erc32/grlib.h
+@@ -0,0 +1,60 @@
++/*
++ * This file is part of SIS.
++ *
++ * SIS, SPARC instruction simulator. Copyright (C) 2014 Jiri Gaisler
++ *
++ * This program is free software; you can redistribute it and/or modify it under
++ * the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 3 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, see <http://www.gnu.org/licenses/>.
++ *
++ */
++
++
++/* Definitions for AMBA PNP in Gaisler Research GRLIB SOC */
++
++/* Vendors */
++
++#define VENDOR_GAISLER 1
++#define VENDOR_PENDER 2
++#define VENDOR_ESA 4
++#define VENDOR_DLR 10
++
++/* Devices */
++
++#define GAISLER_LEON3 0x003
++#define GAISLER_APBMST 0x006
++#define GAISLER_SRCTRL 0x008
++#define GAISLER_APBUART 0x00C
++#define GAISLER_IRQMP 0x00D
++#define GAISLER_GPTIMER 0x011
++#define ESA_MCTRL 0x00F
++
++/* How to build entries in the plug&play area */
++
++#define GRLIB_PP_ID(v, d, x, i) ((v & 0xff) << 24) | ((d & 0x3ff) << 12) |\
++ ((x & 0x1f) << 5) | (i & 0x1f)
++#define GRLIB_PP_AHBADDR(a, m, p, c, t) (a & 0xfff00000) | ((m & 0xfff) << 4) |\
++ ((p & 1) << 17) | ((c & 1) << 16) | (t & 0x3)
++#define GRLIB_PP_APBADDR(a, m) ((a & 0xfff00)<< 12) | ((m & 0xfff) << 4) | 1
++
++#define AHBPP_START 0xFFFFF000
++#define AHBPP_END 0xFFFFFFFF
++#define APBPP_START 0x800FF000
++#define APBPP_END 0x800FFFFF
++
++extern int grlib_apbpp_add (uint32 id, uint32 addr);
++extern int grlib_ahbmpp_add (uint32 id);
++extern int grlib_ahbspp_add (uint32 id, uint32 addr1, uint32 addr2,
++ uint32 addr3, uint32 addr4);
++extern uint32 grlib_ahbpnp_read (uint32 addr);
++extern uint32 grlib_apbpnp_read (uint32 addr);
++extern void grlib_init ();
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index a7cc107..1a088c1 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -50,7 +50,7 @@ run_sim(sregs, icount, dis)
+ sregs->starttime = get_time();
+ irq = 0;
+ if ((sregs->pc != 0) && (ebase.simtime == 0))
+- boot_init();
++ ms->boot_init ();
+ while (!sregs->err_mode & (icount > 0)) {
+
+ sregs->fhold = 0;
+@@ -171,6 +171,10 @@ sim_open (kind, callback, abfd, argv)
+ if (strcmp(argv[stat], "-nouartrx") == 0) {
+ nouartrx = 1;
+ } else
++ if (strcmp (argv[stat], "-leon3") == 0) {
++ ms = &leon3;
++ cputype = CPU_LEON3;
++ } else
+ if (strcmp(argv[stat], "-wrp") == 0) {
+ wrp = 1;
+ } else
+@@ -208,9 +212,21 @@ sim_open (kind, callback, abfd, argv)
+ stat++;
+ }
+
++ if (cputype == CPU_LEON3)
++ sregs.freq = freq ? freq : 50;
++ else
++ sregs.freq = freq ? freq : 14;
++
+ if (sis_verbose) {
+ (*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
+- (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais at wd.estec.esa.nl)\n");
++ (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jiri at gaisler.se)\n\n");
++ switch (cputype) {
++ case CPU_LEON3:
++ (*sim_callback->printf_filtered) (sim_callback, "LEON3 emulation enabled\n");
++ break;
++ default:
++ (*sim_callback->printf_filtered) (sim_callback, "ERC32 emulation enabled\n");
++ }
+ if (nfp)
+ (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
+ if (sparclite)
+@@ -219,11 +235,9 @@ sim_open (kind, callback, abfd, argv)
+ (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
+ if (sis_gdb_break == 0)
+ (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
+- if (freq)
+- (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
++ (*sim_callback->printf_filtered) (sim_callback, "CPU freq %3.1f MHz\n", sregs.freq);
+ }
+
+- sregs.freq = freq ? freq : 15;
+ termsave = fcntl(0, F_GETFL, 0);
+ INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
+ #ifdef HOST_LITTLE_ENDIAN
+@@ -414,7 +428,7 @@ flush_windows ()
+ #endif
+
+ for (i = 0; i < 16; i++)
+- ms->memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
++ ms->memory_write (sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
+ &ws);
+
+ if (win == cwp)
+diff --git a/sim/erc32/leon3.c b/sim/erc32/leon3.c
+new file mode 100644
+index 0000000..4f35386
+--- /dev/null
++++ b/sim/erc32/leon3.c
+@@ -0,0 +1,1067 @@
++/*
++ * This file is part of SIS.
++ *
++ * SIS, SPARC instruction simulator V2.5 Copyright (C) 1995 Jiri Gaisler,
++ * European Space Agency
++ *
++ * This program is free software; you can redistribute it and/or modify it under
++ * the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 3 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, see <http://www.gnu.org/licenses/>.
++ *
++ * Leon3 emulation, loosely based on erc32.c.
++ */
++
++/* The control space devices. */
++
++#include "config.h"
++#include <errno.h>
++#include <sys/types.h>
++#include <stdio.h>
++#include <string.h>
++#include <termios.h>
++#include <sys/fcntl.h>
++#include <sys/file.h>
++#include <unistd.h>
++#include "sis.h"
++#include "grlib.h"
++#include "sim-config.h"
++
++/* APB registers */
++#define APBSTART 0x80000000
++#define APBEND 0x80100000
++
++/* Memory exception waitstates. */
++#define MEM_EX_WS 1
++
++#define MOK 0
++
++/* LEON3 APB register addresses. */
++
++#define IRQMP_IPR 0x204
++#define IRQMP_IMR 0x240
++#define IRQMP_ICR 0x20C
++#define IRQMP_IFR 0x208
++#define GPTIMER_SCALER 0x300
++#define GPTIMER_SCLOAD 0x304
++#define GPTIMER_CONFIG 0x308
++#define GPTIMER_TIMER1 0x310
++#define GPTIMER_RELOAD1 0x314
++#define GPTIMER_CTRL1 0x318
++#define GPTIMER_TIMER2 0x320
++#define GPTIMER_RELOAD2 0x324
++#define GPTIMER_CTRL2 0x328
++
++#define APBUART_RXTX 0x100
++#define APBUART_STATUS 0x104
++
++/* Size of UART buffers (bytes). */
++#define UARTBUF 1024
++
++/* Number of simulator ticks between flushing the UARTS. */
++/* For good performance, keep above 1000. */
++#define UART_FLUSH_TIME 3000
++
++/* New uart defines. */
++#define UART_TX_TIME 1000
++#define UART_RX_TIME 1000
++#define UARTA_DR 0x1
++#define UARTA_SRE 0x2
++#define UARTA_HRE 0x4
++#define UARTA_OR 0x10
++
++/* IRQMP registers. */
++
++static uint32 irqmp_ipr;
++static uint32 irqmp_imr;
++static uint32 irqmp_ifr;
++
++/* GPTIMER registers. */
++
++#define NGPTIMERS 2
++#define GPTIMER_IRQ 8
++
++static uint32 gpt_scaler;
++static uint32 gpt_scaler_start;
++static uint32 gpt_counter[NGPTIMERS];
++static uint32 gpt_reload[NGPTIMERS];
++static uint32 gpt_ctrl[NGPTIMERS];
++
++/* ROM size 16 Mbyte. */
++#define ROM_START 0x00000000
++#define ROM_MASK 0x00ffffff
++#define ROM_END (ROM_START + ROM_MASK + 1)
++
++/* RAM size 16 Mbyte. */
++#define RAM_START 0x40000000
++#define RAM_MASK 0x00ffffff
++#define RAM_END (RAM_START + RAM_MASK + 1)
++
++/* Memory. */
++static unsigned char romb[ROM_END - ROM_START];
++static unsigned char ramb[RAM_END - RAM_START];
++static uint32 cache_ctrl;
++
++
++/* UART support variables. */
++
++/* File descriptor for input file. */
++static int32 fd1, fd2;
++
++/* UART status register */
++static int32 Ucontrol;
++
++static unsigned char aq[UARTBUF], bq[UARTBUF];
++static int32 anum, aind = 0;
++static int32 bnum, bind = 0;
++static char wbufa[UARTBUF], wbufb[UARTBUF];
++static unsigned wnuma;
++static unsigned wnumb;
++static FILE *f1in, *f1out;
++static struct termios ioc1, ioc2, iocold1, iocold2;
++static int f1open = 0;
++
++static char uarta_sreg, uarta_hreg;
++static uint32 uart_stat_reg;
++static uint32 uarta_data;
++
++/* Forward declarations. */
++
++static void mem_init (void);
++static void close_port (void);
++static void leon3_reset (void);
++static void irqmp_intack (int32 level);
++static void chk_irq (void);
++static void set_irq (int32 level);
++static int32 apb_read (uint32 addr, uint32 * data);
++static int apb_write (uint32 addr, uint32 data);
++static void port_init (void);
++static uint32 grlib_read_uart (uint32 addr);
++static void grlib_write_uart (uint32 addr, uint32 data);
++static void flush_uart (void);
++static void uarta_tx (void);
++static void uart_rx (caddr_t arg);
++static void uart_intr (caddr_t arg);
++static void uart_irq_start (void);
++static void gpt_intr (caddr_t arg);
++static void gpt_init (void);
++static void gpt_reset (void);
++static void gpt_scaler_set (uint32 val);
++static void timer_ctrl (uint32 val, int i);
++static unsigned char *get_mem_ptr (uint32 addr, uint32 size);
++static void store_bytes (unsigned char *mem, uint32 waddr,
++ uint32 * data, int sz, int32 * ws);
++
++static host_callback *callback;
++
++
++/* One-time init. */
++
++static void
++init_sim (void)
++{
++ callback = sim_callback;
++ grlib_init ();
++ mem_init ();
++ port_init ();
++ gpt_init ();
++}
++
++/* Power-on reset init. */
++
++static void
++reset (void)
++{
++ leon3_reset ();
++ uart_irq_start ();
++ gpt_reset ();
++}
++
++/* IU error mode manager. */
++
++static void
++error_mode (uint32 pc)
++{
++
++}
++
++/* Memory init. */
++
++static void
++mem_init (void)
++{
++
++/* Add AMBA P&P record for SRCTRL memory controller */
++
++ grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_SRCTRL, 0, 0),
++ GRLIB_PP_AHBADDR (0x00000000, 0xE00, 1, 1, 2),
++ GRLIB_PP_AHBADDR (0x40000000, 0xC00, 1, 1, 2),
++ GRLIB_PP_AHBADDR (0x20000000, 0xE00, 0, 0, 2), 0);
++ if (sis_verbose)
++ printf ("RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n",
++ RAM_START, (RAM_MASK + 1) / 1024, (ROM_MASK + 1) / 1024);
++}
++
++/* Flush ports when simulator stops. */
++
++static void
++sim_halt (void)
++{
++#ifdef FAST_UART
++ flush_uart ();
++#endif
++}
++
++static void
++close_port (void)
++{
++ if (f1open && f1in != stdin)
++ fclose (f1in);
++}
++
++static void
++exit_sim (void)
++{
++ close_port ();
++}
++
++static void
++leon3_reset (void)
++{
++ int i;
++
++ irqmp_ipr = 0;
++ irqmp_imr = 0;
++ irqmp_ifr = 0;
++
++ wnuma = wnumb = 0;
++ anum = aind = bnum = bind = 0;
++
++ uart_stat_reg = UARTA_SRE | UARTA_HRE;
++
++ gpt_counter[0] = 0xffffffff;
++ gpt_reload[0] = 0xffffffff;
++ gpt_scaler = 0xffff;
++ gpt_ctrl[0] = 0;
++ gpt_ctrl[1] = 0;
++
++}
++
++static void
++irqmp_intack (int32 level)
++{
++ int irq_test;
++
++ if (sis_verbose > 2)
++ printf ("interrupt %d acknowledged\n", level);
++ if (irqmp_ifr & (1 << level))
++ irqmp_ifr &= ~(1 << level);
++ else
++ irqmp_ipr &= ~(1 << level);
++ chk_irq ();
++}
++
++static void
++chk_irq (void)
++{
++ int32 i;
++ uint32 itmp;
++ int old_irl;
++
++ old_irl = ext_irl;
++ itmp = ((irqmp_ipr | irqmp_ifr) & irqmp_imr) & 0x0fffe;
++ ext_irl = 0;
++ if (itmp != 0)
++ {
++ for (i = 15; i > 0; i--)
++ {
++ if (((itmp >> i) & 1) != 0)
++ {
++ if ((sis_verbose > 2) && (i > old_irl))
++ printf ("IU irl: %d\n", i);
++ ext_irl = i;
++ set_int (i, irqmp_intack, i);
++ break;
++ }
++ }
++ }
++}
++
++static void
++set_irq (int32 level)
++{
++ irqmp_ipr |= (1 << level);
++ chk_irq ();
++}
++
++static int32
++apb_read (uint32 addr, uint32 * data)
++{
++
++ switch (addr & 0xfff)
++ {
++
++ case APBUART_RXTX: /* 0x100 */
++ case APBUART_STATUS: /* 0x104 */
++ *data = grlib_read_uart (addr);
++ break;
++
++ case IRQMP_IPR: /* 0x204 */
++ *data = irqmp_ipr;
++ break;
++
++ case IRQMP_IFR: /* 0x208 */
++ *data = irqmp_ifr;
++ break;
++
++ case IRQMP_IMR: /* 0x240 */
++ *data = irqmp_imr;
++ break;
++
++ case GPTIMER_SCALER: /* 0x300 */
++ *data = gpt_scaler - (now () - gpt_scaler_start);
++ break;
++
++ case GPTIMER_SCLOAD: /* 0x304 */
++ *data = gpt_scaler;
++ break;
++
++ case GPTIMER_CONFIG: /* 0x308 */
++ *data = 0x100 | (GPTIMER_IRQ << 3) | NGPTIMERS;
++ break;
++
++ case GPTIMER_TIMER1: /* 0x310 */
++ *data = gpt_counter[0];
++ break;
++
++ case GPTIMER_RELOAD1: /* 0x314 */
++ *data = gpt_reload[0];
++ break;
++
++ case GPTIMER_CTRL1: /* 0x318 */
++ *data = gpt_ctrl[0];
++ break;
++
++ case GPTIMER_TIMER2: /* 0x320 */
++ *data = gpt_counter[1];
++ break;
++
++ case GPTIMER_RELOAD2: /* 0x324 */
++ *data = gpt_reload[1];
++ break;
++
++ case GPTIMER_CTRL2: /* 0x328 */
++ *data = gpt_ctrl[1];
++ break;
++
++ default:
++ *data = 0;
++ break;
++ }
++
++ if (sis_verbose > 1)
++ printf ("APB read a: %08x, d: %08x\n", addr, *data);
++
++ return MOK;
++}
++
++static int
++apb_write (uint32 addr, uint32 data)
++{
++ if (sis_verbose > 1)
++ printf ("APB write a: %08x, d: %08x\n", addr, data);
++ switch (addr & 0xfff)
++ {
++
++ case APBUART_RXTX: /* 0x100 */
++ case APBUART_STATUS: /* 0x104 */
++ grlib_write_uart (addr, data);
++ break;
++
++ case IRQMP_IFR: /* 0x208 */
++ irqmp_ifr = data & 0xfffe;
++ chk_irq ();
++ break;
++
++ case IRQMP_ICR: /* 0x20C */
++ irqmp_ipr &= ~data & 0x0fffe;
++ chk_irq ();
++ break;
++
++ case IRQMP_IMR: /* 0x240 */
++ irqmp_imr = data & 0x7ffe;
++ chk_irq ();
++ break;
++
++ case GPTIMER_SCLOAD: /* 0x304 */
++ gpt_scaler_set (data);
++ break;
++
++ case GPTIMER_TIMER1: /* 0x310 */
++ gpt_counter[0] = data;
++ break;
++
++ case GPTIMER_RELOAD1: /* 0x314 */
++ gpt_reload[0] = data;
++ break;
++
++ case GPTIMER_CTRL1: /* 0x318 */
++ timer_ctrl (data, 0);
++ break;
++
++ case GPTIMER_TIMER2: /* 0x320 */
++ gpt_counter[1] = data;
++ break;
++
++ case GPTIMER_RELOAD2: /* 0x324 */
++ gpt_reload[1] = data;
++ break;
++
++ case GPTIMER_CTRL2: /* 0x328 */
++ timer_ctrl (data, 1);
++ break;
++
++ default:
++ break;
++ }
++ return MOK;
++}
++
++
++/* APBUART. */
++
++static int ifd1 = -1, ofd1 = -1;
++
++static void
++init_stdio (void)
++{
++ if (dumbio)
++ return;
++ if (ifd1 == 0 && f1open)
++ {
++ tcsetattr (0, TCSANOW, &ioc1);
++ tcflush (ifd1, TCIFLUSH);
++ }
++}
++
++static void
++restore_stdio (void)
++{
++ if (dumbio)
++ return;
++ if (ifd1 == 0 && f1open && tty_setup)
++ tcsetattr (0, TCSANOW, &iocold1);
++}
++
++#define DO_STDIO_READ( _fd_, _buf_, _len_ ) \
++ ( dumbio || nouartrx \
++ ? (0) /* no bytes read, no delay */ \
++ : (_fd_) == 1 && callback ? \
++ callback->read_stdin (callback, _buf_, _len_) : \
++ read( _fd_, _buf_, _len_ ) )
++
++static void
++port_init (void)
++{
++ f1in = stdin;
++ f1out = stdout;
++ if (uart_dev1[0] != 0)
++ if ((fd1 = open (uart_dev1, O_RDWR | O_NONBLOCK)) < 0)
++ {
++ printf ("Warning, couldn't open output device %s\n", uart_dev1);
++ }
++ else
++ {
++ if (sis_verbose)
++ printf ("serial port A on %s\n", uart_dev1);
++ f1in = f1out = fdopen (fd1, "r+");
++ setbuf (f1out, NULL);
++ f1open = 1;
++ }
++ if (f1in)
++ ifd1 = fileno (f1in);
++ if (ifd1 == 0)
++ {
++ if (callback && !callback->isatty (callback, ifd1))
++ tty_setup = 0;
++ if (sis_verbose)
++ printf ("serial port A on stdin/stdout\n");
++ if (!dumbio)
++ {
++ tcgetattr (ifd1, &ioc1);
++ if (tty_setup)
++ {
++ iocold1 = ioc1;
++ ioc1.c_lflag &= ~(ICANON | ECHO);
++ ioc1.c_cc[VMIN] = 0;
++ ioc1.c_cc[VTIME] = 0;
++ }
++ }
++ f1open = 1;
++ }
++
++ if (f1out)
++ {
++ ofd1 = fileno (f1out);
++ if (!dumbio && tty_setup && ofd1 == 1)
++ setbuf (f1out, NULL);
++ }
++
++ wnuma = 0;
++
++ grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_APBUART, 1, 3),
++ GRLIB_PP_APBADDR (0x80000100, 0xFFF));
++}
++
++static uint32
++grlib_read_uart (uint32 addr)
++{
++ unsigned tmp = 0;
++
++ switch (addr & 0xff)
++ {
++
++ case 0x00: /* UART 1 RX/TX */
++#ifndef _WIN32
++#ifdef FAST_UART
++
++ if (aind < anum)
++ {
++ if ((aind + 1) < anum)
++ set_irq (3);
++ return (uint32) aq[aind++];
++ }
++ else
++ {
++ if (f1open)
++ anum = DO_STDIO_READ (ifd1, aq, UARTBUF);
++ else
++ anum = 0;
++ if (anum > 0)
++ {
++ aind = 0;
++ if ((aind + 1) < anum)
++ set_irq (3);
++ return (uint32) aq[aind++];
++ }
++ else
++ return (uint32) aq[aind];
++ }
++#else
++ tmp = uarta_data;
++ uarta_data &= ~UART_DR;
++ uart_stat_reg &= ~UARTA_DR;
++ return tmp;
++#endif
++#else
++ return 0;
++#endif
++ break;
++
++ case 0x04: /* UART status register */
++#ifndef _WIN32
++#ifdef FAST_UART
++
++ Ucontrol = 0;
++ if (aind < anum)
++ {
++ Ucontrol |= 0x00000001;
++ }
++ else
++ {
++ if (f1open)
++ anum = DO_STDIO_READ (ifd1, aq, UARTBUF);
++ else
++ anum = 0;
++ if (anum > 0)
++ {
++ Ucontrol |= 0x00000001;
++ aind = 0;
++ set_irq (3);
++ }
++ }
++ Ucontrol |= 0x00000006;
++ return Ucontrol;
++#else
++ return uart_stat_reg;
++#endif
++#else
++ return 0x00060006;
++#endif
++ break;
++ default:
++ if (sis_verbose)
++ printf ("Read from unimplemented UART register (%x)\n", addr);
++ }
++
++ return 0;
++}
++
++static void
++grlib_write_uart (uint32 addr, uint32 data)
++{
++ unsigned char c;
++
++ c = (unsigned char) data;
++ switch (addr & 0xff)
++ {
++
++ case 0x00: /* UART A */
++#ifdef FAST_UART
++ if (f1open)
++ {
++ if (wnuma < UARTBUF)
++ wbufa[wnuma++] = c;
++ else
++ {
++ while (wnuma)
++ {
++ if (ofd1 == 1 && callback)
++ wnuma -= callback->write_stdout (callback, wbufa, wnuma);
++ else
++ wnuma -= fwrite (wbufa, 1, wnuma, f1out);
++ }
++ wbufa[wnuma++] = c;
++ }
++ }
++ set_irq (3);
++#else
++ if (uart_stat_reg & UARTA_SRE)
++ {
++ uarta_sreg = c;
++ uart_stat_reg &= ~UARTA_SRE;
++ event (uarta_tx, 0, UART_TX_TIME);
++ }
++ else
++ {
++ uarta_hreg = c;
++ uart_stat_reg &= ~UARTA_HRE;
++ }
++#endif
++ break;
++
++ case 0x04: /* UART status register */
++#ifndef FAST_UART
++ uart_stat_reg &= 1;
++#endif
++ break;
++ default:
++ if (sis_verbose)
++ printf ("Write to unimplemented UART register (%x)\n", addr);
++ }
++}
++
++static void
++flush_uart (void)
++{
++ while (wnuma && f1open)
++ {
++ if (ofd1 == 1 && callback)
++ {
++ wnuma -= callback->write_stdout (callback, wbufa, wnuma);
++ callback->flush_stdout (callback);
++ }
++ else
++ wnuma -= fwrite (wbufa, 1, wnuma, f1out);
++ }
++}
++
++static void
++uarta_tx (void)
++{
++ while (f1open)
++ {
++ if (ofd1 == 1 && callback)
++ while (callback->write_stdout (callback, &uarta_sreg, 1) != 1)
++ continue;
++ else
++ while (fwrite (&uarta_sreg, 1, 1, f1out) != 1)
++ continue;
++ }
++ if (uart_stat_reg & UARTA_HRE)
++ {
++ uart_stat_reg |= UARTA_SRE;
++ }
++ else
++ {
++ uarta_sreg = uarta_hreg;
++ uart_stat_reg |= UARTA_HRE;
++ event (uarta_tx, 0, UART_TX_TIME);
++ }
++ set_irq (3);
++}
++
++static void
++uart_rx (caddr_t arg)
++{
++ char rxd;
++ int32 rsize = 0;
++
++
++ if (f1open)
++ rsize = DO_STDIO_READ (ifd1, &rxd, 1);
++ else
++ rsize = 0;
++ if (rsize > 0)
++ {
++ uarta_data = rxd;
++ if (uart_stat_reg & UARTA_DR)
++ {
++ uart_stat_reg |= UARTA_OR;
++ }
++ uart_stat_reg |= UARTA_DR;
++ set_irq (3);
++ }
++ event (uart_rx, 0, UART_RX_TIME);
++}
++
++static void
++uart_intr (caddr_t arg)
++{
++ /* Check for UART interrupts every 1000 clk. */
++ grlib_read_uart (APBUART_STATUS);
++ flush_uart ();
++ event (uart_intr, 0, UART_FLUSH_TIME);
++}
++
++
++static void
++uart_irq_start (void)
++{
++#ifdef FAST_UART
++ event (uart_intr, 0, UART_FLUSH_TIME);
++#else
++#ifndef _WIN32
++ event (uart_rx, 0, UART_RX_TIME);
++#endif
++#endif
++}
++
++/* GPTIMER. */
++
++static void
++gpt_intr (caddr_t arg)
++{
++ int i;
++
++ for (i = 0; i < NGPTIMERS; i++)
++ {
++ if (gpt_ctrl[i] & 1)
++ {
++ gpt_counter[i] -= 1;
++ if (gpt_counter[i] == -1)
++ {
++ if (gpt_ctrl[i] & 8)
++ set_irq (GPTIMER_IRQ + i);
++ if (gpt_ctrl[i] & 2)
++ gpt_counter[i] = gpt_reload[i];
++ }
++ }
++ }
++ event (gpt_intr, 0, gpt_scaler + 1);
++ gpt_scaler_start = now ();
++}
++
++static void
++gpt_init (void)
++{
++ if (sis_verbose)
++ printf ("GPT started (period %d)\n\r", gpt_scaler + 1);
++
++ grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_GPTIMER, 0, 8),
++ GRLIB_PP_APBADDR (0x80000300, 0xFFF));
++}
++
++static void
++gpt_reset (void)
++{
++ event (gpt_intr, 0, gpt_scaler + 1);
++ gpt_scaler_start = now ();
++}
++
++static void
++gpt_scaler_set (uint32 val)
++{
++ /* Mask for 16-bit scaler. */
++ gpt_scaler = val & 0x0ffff;
++}
++
++static void
++timer_ctrl (uint32 val, int i)
++{
++ if (val & 4)
++ {
++ /* Reload. */
++ gpt_counter[i] = gpt_reload[i];
++ }
++ gpt_ctrl[i] = val & 0xb;
++}
++
++/* Store data in host byte order. MEM points to the beginning of the
++ emulated memory; WADDR contains the index the emulated memory,
++ DATA points to words in host byte order to be stored. SZ contains log(2)
++ of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word),
++ 2 (one word), or 3 (two words); WS should return the number of wait-states. */
++
++static void
++store_bytes (unsigned char *mem, uint32 waddr, uint32 * data, int32 sz,
++ int32 * ws)
++{
++ switch (sz)
++ {
++ case 0:
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= EBT;
++#endif
++ mem[waddr] = *data & 0x0ff;
++ *ws = 0;
++ break;
++ case 1:
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= 2;
++#endif
++ memcpy (&mem[waddr], data, 2);
++ *ws = 0;
++ break;
++ case 2:
++ memcpy (&mem[waddr], data, 4);
++ *ws = 0;
++ break;
++ case 3:
++ memcpy (&mem[waddr], data, 8);
++ *ws = 0;
++ break;
++ }
++}
++
++
++/* Memory emulation. */
++
++static int
++memory_iread (uint32 addr, uint32 * data, int32 * ws)
++{
++ if ((addr >= RAM_START) && (addr < RAM_END))
++ {
++ memcpy (data, &ramb[addr & RAM_MASK], 4);
++ *ws = 0;
++ return 0;
++ }
++ else if (addr < ROM_END)
++ {
++ memcpy (data, &romb[addr], 4);
++ *ws = 0;
++ return 0;
++ }
++
++ if (sis_verbose)
++ printf ("Memory exception at %x (illegal address)\n", addr);
++ *ws = MEM_EX_WS;
++ return 1;
++}
++
++static int
++memory_read (uint32 addr, uint32 * data, int32 sz, int32 * ws)
++{
++ int32 mexc;
++
++ if ((addr >= RAM_START) && (addr < RAM_END))
++ {
++ memcpy (data, &ramb[addr & RAM_MASK & ~3], 4);
++ *ws = 0;
++ return 0;
++ }
++ else if ((addr >= APBPP_START) && (addr <= APBPP_END))
++ {
++ *data = grlib_apbpnp_read (addr);
++ if (sis_verbose > 1)
++ printf ("APB PP read a: %08x, d: %08x\n", addr, *data);
++ *ws = 4;
++ return 0;
++ }
++ else if ((addr >= APBSTART) && (addr < APBEND))
++ {
++ mexc = apb_read (addr, data);
++ if (mexc)
++ *ws = MEM_EX_WS;
++ else
++ *ws = 0;
++ return mexc;
++ }
++ else if ((addr >= AHBPP_START) && (addr <= AHBPP_END))
++ {
++ if (sis_verbose > 1)
++ printf ("AHB PP read a: %08x, d: %08x\n", addr, *data);
++ *data = grlib_ahbpnp_read (addr);
++ *ws = 4;
++ return 0;
++ }
++ else if (addr < ROM_END)
++ {
++ memcpy (data, &romb[addr & ~3], 4);
++ *ws = 0;
++ return 0;
++ }
++
++ if (sis_verbose)
++ printf ("Memory exception at %x (illegal address)\n", addr);
++ *ws = MEM_EX_WS;
++ return 1;
++}
++
++static int
++memory_read_asi (int32 asi, uint32 addr, uint32 * data, int32 sz, int32 * ws)
++{
++ if (asi == 2)
++ {
++ if (addr == 0)
++ *data = cache_ctrl;
++ else
++ *data = 0;
++ return MOK;
++ }
++ else
++ return memory_read (addr, data, sz, ws);
++}
++
++static int
++memory_write (uint32 addr, uint32 * data, int32 sz, int32 * ws)
++{
++ uint32 byte_addr;
++ uint32 byte_mask;
++ uint32 waddr;
++ uint32 *ram;
++ int32 mexc;
++ int i;
++ int wphit[2];
++
++ if ((addr >= RAM_START) && (addr < RAM_END))
++ {
++ waddr = addr & RAM_MASK;
++ store_bytes (ramb, waddr, data, sz, ws);
++ return 0;
++ }
++ else if ((addr >= APBSTART) && (addr < APBEND))
++ {
++ if (sz != 2)
++ {
++ *ws = MEM_EX_WS;
++ return 1;
++ }
++ apb_write (addr, *data);
++ *ws = 0;
++ return 0;
++
++ }
++ else if (addr < ROM_END)
++ {
++ *ws = 0;
++ store_bytes (romb, addr, data, sz, ws);
++ return 0;
++ }
++
++ *ws = MEM_EX_WS;
++ return 1;
++}
++
++static int
++memory_write_asi (int32 asi, uint32 addr, uint32 * data, int32 sz, int32 * ws)
++{
++ if (asi == 2)
++ {
++ cache_ctrl = *data & 0x81000f;
++ if (sis_verbose)
++ printf ("cache ctrl reg : 0x%08x\n", cache_ctrl);
++ return MOK;
++ }
++ else
++ return (memory_write (addr, data, sz, ws));
++}
++
++static unsigned char *
++get_mem_ptr (uint32 addr, uint32 size)
++{
++ if ((addr + size) < ROM_END)
++ {
++ return &romb[addr];
++ }
++ else if ((addr >= RAM_START) && ((addr + size) < RAM_END))
++ {
++ return &ramb[addr & RAM_MASK];
++ }
++
++ return (char *) -1;
++}
++
++static int
++sis_memory_write (uint32 addr, const unsigned char *data, uint32 length)
++{
++ char *mem;
++
++ if ((mem = get_mem_ptr (addr, length)) == ((char *) -1))
++ return 0;
++
++ memcpy (mem, data, length);
++ return length;
++}
++
++static int
++sis_memory_read (uint32 addr, char *data, uint32 length)
++{
++ char *mem;
++ int ws;
++
++ if (length == 4)
++ {
++ memory_read (addr, (uint32 *) data, length, &ws);
++ return 4;
++ }
++
++ if ((mem = get_mem_ptr (addr, length)) == ((char *) -1))
++ return 0;
++
++ memcpy (data, mem, length);
++ return length;
++}
++
++static void
++boot_init (void)
++{
++ /* Generate 1 MHz RTC tick. */
++ apb_write (GPTIMER_SCALER, sregs.freq - 1);
++ apb_write (GPTIMER_SCLOAD, sregs.freq - 1);
++ apb_write (GPTIMER_TIMER1, -1);
++ apb_write (GPTIMER_RELOAD1, -1);
++ apb_write (GPTIMER_CTRL1, 0x7);
++
++ sregs.wim = 2;
++ sregs.psr = 0xF30010e0;
++ sregs.r[30] = RAM_END;
++ sregs.r[14] = sregs.r[30] - 96 * 4;
++ cache_ctrl = 0x81000f;
++}
++
++const struct memsys leon3 = {
++ init_sim,
++ reset,
++ error_mode,
++ sim_halt,
++ exit_sim,
++ init_stdio,
++ restore_stdio,
++ memory_iread,
++ memory_read,
++ memory_read_asi,
++ memory_write,
++ memory_write_asi,
++ sis_memory_write,
++ sis_memory_read,
++ boot_init
++};
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index 58478ef..e99d1a3 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -139,7 +139,7 @@ main(argc, argv)
+ for (i = 0; i < 64; i++)
+ cmdq[i] = 0;
+ printf("\n SIS - SPARC instruction simulator %s, copyright Jiri Gaisler 1995\n", sis_version);
+- printf(" Bug-reports to jgais at wd.estec.esa.nl\n\n");
++ printf (" Bug-reports to jiri at gaisler.se\n\n");
+ while (stat < argc) {
+ if (argv[stat][0] == '-') {
+ if (strcmp(argv[stat], "-v") == 0) {
+@@ -178,6 +178,10 @@ main(argc, argv)
+ dumbio = 1;
+ } else if (strcmp(argv[stat], "-nouartrx") == 0) {
+ nouartrx = 1;
++ } else if (strcmp (argv[stat], "-leon3") == 0) {
++ ms = &leon3;
++ if (freq == 14) freq = 50;
++ cputype = CPU_LEON3;
+ } else {
+ printf("unknown option %s\n", argv[stat]);
+ usage();
+@@ -188,13 +192,19 @@ main(argc, argv)
+ }
+ stat++;
+ }
++
++ switch (cputype) {
++ case CPU_LEON3:
++ printf (" LEON3 emulation enabled\n");
++ break;
++ default:
++ printf (" ERC32 emulation enabled\n");
++ }
++
+ if (nfp)
+- printf("FPU disabled\n");
+-#ifdef ERA
+- if (era)
+- printf("ERA ECC emulation enabled\n");
+-#endif
++ printf(" FPU disabled\n");
+ sregs.freq = freq;
++ printf("\n");
+
+ INIT_DISASSEMBLE_INFO(dinfo, stdout, (fprintf_ftype) fprintf);
+ #ifdef HOST_LITTLE_ENDIAN
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index 7cf8feb..d06566d 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -154,6 +154,7 @@ struct irqcell {
+ #define BPT_HIT 2
+ #define ERROR 3
+ #define CTRL_C 4
++#define CPU_LEON3 3
+
+ /* Prototypes */
+
+@@ -209,6 +210,7 @@ extern int nouartrx;
+ extern host_callback *sim_callback;
+ extern int dumbio;
+ extern int tty_setup;
++extern int cputype;
+
+
+ /* exec.c */
+@@ -239,14 +241,20 @@ struct memsys {
+ void (*init_stdio) (void);
+ void (*restore_stdio) (void);
+ int (*memory_iread) (uint32 addr, uint32 *data, int32 *ws);
+- int (*memory_read) (int32 asi, uint32 addr, uint32 *data,
++ int (*memory_read) (uint32 addr, uint32 *data, int32 sz, int32 *ws);
++ int (*memory_read_asi) (int32 asi, uint32 addr, uint32 *data,
++ int32 sz, int32 *ws);
++ int (*memory_write) (uint32 addr, uint32 *data, int32 sz, int32 *ws);
++ int (*memory_write_asi) (int32 asi, uint32 addr, uint32 *data,
+ int32 sz, int32 *ws);
+- int (*memory_write) (int32 asi, uint32 addr, uint32 *data,
+- int32 sz, int32 *ws);
+ int (*sis_memory_write) (uint32 addr,
+ const unsigned char *data, uint32 length);
+ int (*sis_memory_read) (uint32 addr, char *data,
+ uint32 length);
++ void (*boot_init) (void);
+ };
+
+ extern const struct memsys *ms;
++
++/* leon3.c */
++extern const struct memsys leon3;
+--
+2.7.4
+
+From cacd2f484af85520a7b940eadb12e9b2804b038b Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri at gaisler.se>
+Date: Tue, 29 Dec 2015 20:57:59 -0500
+Subject: [PATCH 5/9] sim/erc32: Add support for LEON2 processor emulation.
+
+ Added memory and I/O sub-system to emulate a LEON2 processor.
+ The cache and MMU are not emulated but enough functionallity
+ is provided to run any RTEMS and BCC compiled application.
+ The code is based on erc32.c and modified to emulate the
+ LEON2 address space and peripheral operations.
+
+ * Makefile.in : Added new object files.
+ * exec.c (init_regs): Add leon2 vendor/device ID to %psr.
+ * interf.c (sim_open): Add -leon2 to start-up switches.
+ (sim_open): Set leon2 default frequency to 50 MHz. Print out current
+ emulation mode.
+ * leon2.c : New file, emulation of leon2 memory and peripherals.
+ * sis.c (main): Add -leon2 switch. Set default leon2 frequency to 50 MHz.
+ * sis.h: Add memsys struct for leon2.
+---
+ sim/erc32/Makefile.in | 2 +-
+ sim/erc32/exec.c | 3 +
+ sim/erc32/interf.c | 11 +-
+ sim/erc32/leon2.c | 1030 +++++++++++++++++++++++++++++++++++++++++++++++++
+ sim/erc32/sis.c | 7 +
+ sim/erc32/sis.h | 4 +
+ 6 files changed, 1054 insertions(+), 3 deletions(-)
+ create mode 100644 sim/erc32/leon2.c
+
+diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
+index f1d6589..4fc54ca 100644
+--- a/sim/erc32/Makefile.in
++++ b/sim/erc32/Makefile.in
+@@ -22,7 +22,7 @@ TERMCAP_LIB = @TERMCAP@
+ READLINE_LIB = @READLINE@
+
+ # `sis' doesn't need interf.o.
+-SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o
++SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o leon2.o
+
+ SIM_OBJS = $(SIS_OFILES) interf.o
+ SIM_RUN_OBJS = sis.o
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index 4f15320..bacac4c 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -2192,6 +2192,9 @@ init_regs(sregs)
+ if (cputype == CPU_LEON3)
+ sregs->psr |= 0xF3000080; /* Set supervisor bit */
+ else
++ if (cputype == CPU_LEON2)
++ sregs->psr |= 0x00000080; /* Set supervisor bit */
++ else
+ sregs->psr |= 0x11000080; /* Set supervisor bit */
+ sregs->breakpoint = 0;
+ sregs->annul = 0;
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 1a088c1..b62ed40 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -171,6 +171,10 @@ sim_open (kind, callback, abfd, argv)
+ if (strcmp(argv[stat], "-nouartrx") == 0) {
+ nouartrx = 1;
+ } else
++ if (strcmp (argv[stat], "-leon2") == 0) {
++ ms = &leon2;
++ cputype = CPU_LEON2;
++ } else
+ if (strcmp (argv[stat], "-leon3") == 0) {
+ ms = &leon3;
+ cputype = CPU_LEON3;
+@@ -212,15 +216,18 @@ sim_open (kind, callback, abfd, argv)
+ stat++;
+ }
+
+- if (cputype == CPU_LEON3)
++ if ((cputype == CPU_LEON3) || (cputype == CPU_LEON2))
+ sregs.freq = freq ? freq : 50;
+ else
+ sregs.freq = freq ? freq : 14;
+
+ if (sis_verbose) {
+ (*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
+- (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jiri at gaisler.se)\n\n");
++ (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler (jiri at gaisler.se)\n\n");
+ switch (cputype) {
++ case CPU_LEON2:
++ (*sim_callback->printf_filtered) (sim_callback, "LEON2 emulation enabled\n");
++ break;
+ case CPU_LEON3:
+ (*sim_callback->printf_filtered) (sim_callback, "LEON3 emulation enabled\n");
+ break;
+diff --git a/sim/erc32/leon2.c b/sim/erc32/leon2.c
+new file mode 100644
+index 0000000..87bee6a
+--- /dev/null
++++ b/sim/erc32/leon2.c
+@@ -0,0 +1,1030 @@
++/*
++ * This file is part of SIS.
++ *
++ * SIS, SPARC instruction simulator V2.8 Copyright (C) 2015 Jiri Gaisler
++ *
++ * This program is free software; you can redistribute it and/or modify it under
++ * the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 3 of the License, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, see <http://www.gnu.org/licenses/>.
++ *
++ * Leon2 emulation, based on leon3.c and erc32.c/
++ */
++
++/* The control space devices. */
++
++#include "config.h"
++#include <errno.h>
++#include <sys/types.h>
++#include <stdio.h>
++#include <string.h>
++#include <termios.h>
++#include <sys/fcntl.h>
++#include <sys/file.h>
++#include <unistd.h>
++#include "sis.h"
++#include "grlib.h"
++#include "sim-config.h"
++
++/* APB registers */
++#define APBSTART 0x80000000
++#define APBEND 0x80000100
++
++/* Memory exception waitstates */
++#define MEM_EX_WS 1
++
++#define MOK 0
++
++/* LEON2 APB register addresses */
++
++#define IRQCTRL_IPR 0x094
++#define IRQCTRL_IMR 0x090
++#define IRQCTRL_ICR 0x09C
++#define IRQCTRL_IFR 0x098
++#define TIMER_SCALER 0x060
++#define TIMER_SCLOAD 0x064
++#define LEON2_CONFIG 0x024
++#define TIMER_TIMER1 0x040
++#define TIMER_RELOAD1 0x044
++#define TIMER_CTRL1 0x048
++#define TIMER_TIMER2 0x050
++#define TIMER_RELOAD2 0x054
++#define TIMER_CTRL2 0x058
++#define CACHE_CTRL 0x014
++#define POWER_DOWN 0x018
++
++#define APBUART_RXTX 0x070
++#define APBUART_STATUS 0x074
++
++/* Size of UART buffers (bytes). */
++#define UARTBUF 1024
++
++/* Number of simulator ticks between flushing the UARTS. */
++/* For good performance, keep above 1000. */
++#define UART_FLUSH_TIME 3000
++
++/* New uart defines. */
++#define UART_TX_TIME 1000
++#define UART_RX_TIME 1000
++#define UARTA_DR 0x1
++#define UARTA_SRE 0x2
++#define UARTA_HRE 0x4
++#define UARTA_OR 0x10
++
++/* IRQCTRL registers. */
++
++static uint32 irqctrl_ipr;
++static uint32 irqctrl_imr;
++static uint32 irqctrl_ifr;
++
++/* TIMER registers. */
++
++#define NTIMERS 2
++#define TIMER_IRQ 8
++
++static uint32 gpt_scaler;
++static uint32 gpt_scaler_start;
++static uint32 gpt_counter[NTIMERS];
++static uint32 gpt_reload[NTIMERS];
++static uint32 gpt_ctrl[NTIMERS];
++
++/* ROM size 16 Mbyte. */
++#define ROM_START 0x00000000
++#define ROM_MASK 0x00ffffff
++#define ROM_END (ROM_START + ROM_MASK + 1)
++
++/* RAM size 16 Mbyte. */
++#define RAM_START 0x40000000
++#define RAM_MASK 0x00ffffff
++#define RAM_END (RAM_START + RAM_MASK + 1)
++
++/* Memory. */
++static unsigned char romb[ROM_END - ROM_START];
++static unsigned char ramb[RAM_END - RAM_START];
++static uint32 cache_ctrl;
++
++
++/* UART support variables. */
++
++/* File descriptor for input file. */
++static int32 fd1, fd2;
++
++/* UART status register */
++static int32 Ucontrol;
++
++static unsigned char aq[UARTBUF], bq[UARTBUF];
++static int32 anum, aind = 0;
++static int32 bnum, bind = 0;
++static char wbufa[UARTBUF], wbufb[UARTBUF];
++static unsigned wnuma;
++static unsigned wnumb;
++static FILE *f1in, *f1out;
++static struct termios ioc1, ioc2, iocold1, iocold2;
++static int f1open = 0;
++
++static char uarta_sreg, uarta_hreg;
++static uint32 uart_stat_reg;
++static uint32 uarta_data;
++
++/* Forward declarations. */
++
++static void mem_init (void);
++static void close_port (void);
++static void leon2_reset (void);
++static void irqctrl_intack (int32 level);
++static void chk_irq (void);
++static void set_irq (int32 level);
++static int32 apb_read (uint32 addr, uint32 * data);
++static int apb_write (uint32 addr, uint32 data);
++static void port_init (void);
++static uint32 grlib_read_uart (uint32 addr);
++static void grlib_write_uart (uint32 addr, uint32 data);
++static void flush_uart (void);
++static void uarta_tx (void);
++static void uart_rx (caddr_t arg);
++static void uart_intr (caddr_t arg);
++static void uart_irq_start (void);
++static void gpt_intr (caddr_t arg);
++static void gpt_init (void);
++static void gpt_reset (void);
++static void gpt_scaler_set (uint32 val);
++static void timer_ctrl (uint32 val, int i);
++static unsigned char *get_mem_ptr (uint32 addr, uint32 size);
++static void store_bytes (unsigned char *mem, uint32 waddr,
++ uint32 * data, int sz, int32 * ws);
++
++static host_callback *callback;
++
++
++/* One-time init. */
++
++static void
++init_sim (void)
++{
++ callback = sim_callback;
++ grlib_init ();
++ mem_init ();
++ port_init ();
++ gpt_init ();
++}
++
++/* Power-on reset init. */
++
++static void
++reset (void)
++{
++ leon2_reset ();
++ uart_irq_start ();
++ gpt_reset ();
++}
++
++/* IU error mode manager. */
++
++static void
++error_mode (uint32 pc)
++{
++
++}
++
++/* Memory init. */
++
++static void
++mem_init (void)
++{
++
++ if (sis_verbose)
++ printf ("RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n",
++ RAM_START, (RAM_MASK + 1) / 1024, (ROM_MASK + 1) / 1024);
++}
++
++/* Flush ports when simulator stops. */
++
++static void
++sim_halt (void)
++{
++#ifdef FAST_UART
++ flush_uart ();
++#endif
++}
++
++static void
++close_port (void)
++{
++ if (f1open && f1in != stdin)
++ fclose (f1in);
++}
++
++static void
++exit_sim (void)
++{
++ close_port ();
++}
++
++static void
++leon2_reset (void)
++{
++ int i;
++
++ irqctrl_ipr = 0;
++ irqctrl_imr = 0;
++ irqctrl_ifr = 0;
++
++ wnuma = wnumb = 0;
++ anum = aind = bnum = bind = 0;
++
++ uart_stat_reg = UARTA_SRE | UARTA_HRE;
++
++ gpt_counter[0] = 0xffffffff;
++ gpt_reload[0] = 0xffffffff;
++ gpt_scaler = 0xffff;
++ gpt_ctrl[0] = 0;
++ gpt_ctrl[1] = 0;
++}
++
++static void
++irqctrl_intack (int32 level)
++{
++ int irq_test;
++
++ if (sis_verbose > 2)
++ printf ("interrupt %d acknowledged\n", level);
++ if (irqctrl_ifr & (1 << level))
++ irqctrl_ifr &= ~(1 << level);
++ else
++ irqctrl_ipr &= ~(1 << level);
++ chk_irq ();
++}
++
++static void
++chk_irq (void)
++{
++ int32 i;
++ uint32 itmp;
++ int old_irl;
++
++ old_irl = ext_irl;
++ itmp = ((irqctrl_ipr | irqctrl_ifr) & irqctrl_imr) & 0x0fffe;
++ ext_irl = 0;
++ if (itmp != 0)
++ {
++ for (i = 15; i > 0; i--)
++ {
++ if (((itmp >> i) & 1) != 0)
++ {
++ if ((sis_verbose > 2) && (i > old_irl))
++ printf ("IU irl: %d\n", i);
++ ext_irl = i;
++ set_int (i, irqctrl_intack, i);
++ break;
++ }
++ }
++ }
++}
++
++static void
++set_irq (int32 level)
++{
++ irqctrl_ipr |= (1 << level);
++ chk_irq ();
++}
++
++static int32
++apb_read (uint32 addr, uint32 * data)
++{
++
++ switch (addr & 0xfff)
++ {
++
++ case APBUART_RXTX: /* 0x100 */
++ case APBUART_STATUS: /* 0x104 */
++ *data = grlib_read_uart (addr);
++ break;
++
++ case IRQCTRL_IPR: /* 0x204 */
++ *data = irqctrl_ipr;
++ break;
++
++ case IRQCTRL_IFR: /* 0x208 */
++ *data = irqctrl_ifr;
++ break;
++
++ case IRQCTRL_IMR: /* 0x240 */
++ *data = irqctrl_imr;
++ break;
++
++ case TIMER_SCALER: /* 0x300 */
++ *data = gpt_scaler - (now () - gpt_scaler_start);
++ break;
++
++ case TIMER_SCLOAD: /* 0x304 */
++ *data = gpt_scaler;
++ break;
++
++ case LEON2_CONFIG: /* 0x308 */
++ *data = 0x700310;
++ break;
++
++ case TIMER_TIMER1: /* 0x310 */
++ *data = gpt_counter[0];
++ break;
++
++ case TIMER_RELOAD1: /* 0x314 */
++ *data = gpt_reload[0];
++ break;
++
++ case TIMER_CTRL1: /* 0x318 */
++ *data = gpt_ctrl[0];
++ break;
++
++ case TIMER_TIMER2: /* 0x320 */
++ *data = gpt_counter[1];
++ break;
++
++ case TIMER_RELOAD2: /* 0x324 */
++ *data = gpt_reload[1];
++ break;
++
++ case TIMER_CTRL2: /* 0x328 */
++ *data = gpt_ctrl[1];
++ break;
++
++ case CACHE_CTRL: /* 0x328 */
++ *data = cache_ctrl;
++ break;
++
++ default:
++ *data = 0;
++ break;
++ }
++
++ if (sis_verbose > 1)
++ printf ("APB read a: %08x, d: %08x\n", addr, *data);
++
++ return MOK;
++}
++
++static int
++apb_write (uint32 addr, uint32 data)
++{
++ if (sis_verbose > 1)
++ printf ("APB write a: %08x, d: %08x\n", addr, data);
++ switch (addr & 0xff)
++ {
++
++ case APBUART_RXTX: /* 0x100 */
++ case APBUART_STATUS: /* 0x104 */
++ grlib_write_uart (addr, data);
++ break;
++
++ case IRQCTRL_IFR: /* 0x208 */
++ irqctrl_ifr = data & 0xfffe;
++ chk_irq ();
++ break;
++
++ case IRQCTRL_ICR: /* 0x20C */
++ irqctrl_ipr &= ~data & 0x0fffe;
++ chk_irq ();
++ break;
++
++ case IRQCTRL_IMR: /* 0x240 */
++ irqctrl_imr = data & 0x7ffe;
++ chk_irq ();
++ break;
++
++ case TIMER_SCLOAD: /* 0x304 */
++ gpt_scaler_set (data);
++ break;
++
++ case TIMER_TIMER1: /* 0x310 */
++ gpt_counter[0] = data;
++ break;
++
++ case TIMER_RELOAD1: /* 0x314 */
++ gpt_reload[0] = data;
++ break;
++
++ case TIMER_CTRL1: /* 0x318 */
++ timer_ctrl (data, 0);
++ break;
++
++ case TIMER_TIMER2: /* 0x320 */
++ gpt_counter[1] = data;
++ break;
++
++ case TIMER_RELOAD2: /* 0x324 */
++ gpt_reload[1] = data;
++ break;
++
++ case TIMER_CTRL2: /* 0x328 */
++ timer_ctrl (data, 1);
++ break;
++
++ case POWER_DOWN: /* 0x328 */
++ wait_for_irq ();
++ break;
++
++ case CACHE_CTRL: /* 0x328 */
++ cache_ctrl = data & 0x1000f;
++ break;
++
++ default:
++ break;
++ }
++ return MOK;
++}
++
++
++/* APBUART. */
++
++static int ifd1 = -1, ofd1 = -1;
++
++static void
++init_stdio (void)
++{
++ if (dumbio)
++ return;
++ if (ifd1 == 0 && f1open)
++ {
++ tcsetattr (0, TCSANOW, &ioc1);
++ tcflush (ifd1, TCIFLUSH);
++ }
++}
++
++static void
++restore_stdio (void)
++{
++ if (dumbio)
++ return;
++ if (ifd1 == 0 && f1open && tty_setup)
++ tcsetattr (0, TCSANOW, &iocold1);
++}
++
++#define DO_STDIO_READ( _fd_, _buf_, _len_ ) \
++ ( dumbio || nouartrx \
++ ? (0) /* no bytes read, no delay */ \
++ : (_fd_) == 1 && callback ? \
++ callback->read_stdin (callback, _buf_, _len_) : \
++ read( _fd_, _buf_, _len_ ) )
++
++static void
++port_init (void)
++{
++ f1in = stdin;
++ f1out = stdout;
++ if (uart_dev1[0] != 0)
++ if ((fd1 = open (uart_dev1, O_RDWR | O_NONBLOCK)) < 0)
++ printf ("Warning, couldn't open output device %s\n", uart_dev1);
++ else
++ {
++ if (sis_verbose)
++ printf ("serial port A on %s\n", uart_dev1);
++ f1in = f1out = fdopen (fd1, "r+");
++ setbuf (f1out, NULL);
++ f1open = 1;
++ }
++ if (f1in)
++ ifd1 = fileno (f1in);
++ if (ifd1 == 0)
++ {
++ if (callback && !callback->isatty (callback, ifd1))
++ tty_setup = 0;
++ if (sis_verbose)
++ printf ("serial port A on stdin/stdout\n");
++ if (!dumbio)
++ {
++ tcgetattr (ifd1, &ioc1);
++ if (tty_setup)
++ {
++ iocold1 = ioc1;
++ ioc1.c_lflag &= ~(ICANON | ECHO);
++ ioc1.c_cc[VMIN] = 0;
++ ioc1.c_cc[VTIME] = 0;
++ }
++ }
++ f1open = 1;
++ }
++
++ if (f1out)
++ {
++ ofd1 = fileno (f1out);
++ if (!dumbio && tty_setup && ofd1 == 1)
++ setbuf (f1out, NULL);
++ }
++
++ wnuma = 0;
++}
++
++static uint32
++grlib_read_uart (uint32 addr)
++{
++
++ unsigned tmp = 0;
++
++ switch (addr & 0xfff)
++ {
++
++ case 0x070: /* UART 1 RX/TX */
++#ifndef _WIN32
++#ifdef FAST_UART
++ if (aind < anum)
++ {
++ if ((aind + 1) < anum)
++ set_irq (3);
++ return (uint32) aq[aind++];
++ }
++ else
++ {
++ if (f1open)
++ anum = DO_STDIO_READ (ifd1, aq, UARTBUF);
++ else
++ anum = 0;
++ if (anum > 0)
++ {
++ aind = 0;
++ if ((aind + 1) < anum)
++ set_irq (3);
++ return (uint32) aq[aind++];
++ }
++ else
++ return (uint32) aq[aind];
++ }
++#else
++ tmp = uarta_data;
++ uarta_data &= ~UART_DR;
++ uart_stat_reg &= ~UARTA_DR;
++ return tmp;
++#endif
++#else
++ return 0;
++#endif
++ break;
++
++ case 0x074: /* UART status register */
++#ifndef _WIN32
++#ifdef FAST_UART
++
++ Ucontrol = 0;
++ if (aind < anum)
++ Ucontrol |= 0x00000001;
++ else
++ {
++ if (f1open)
++ anum = DO_STDIO_READ (ifd1, aq, UARTBUF);
++ else
++ anum = 0;
++ if (anum > 0)
++ {
++ Ucontrol |= 0x00000001;
++ aind = 0;
++ set_irq (3);
++ }
++ }
++ Ucontrol |= 0x00000006;
++ return Ucontrol;
++#else
++ return uart_stat_reg;
++#endif
++#else
++ return 0x00060006;
++#endif
++ break;
++ default:
++ if (sis_verbose)
++ printf ("Read from unimplemented LEON2 register (%x)\n", addr);
++
++ }
++ return 0;
++}
++
++static void
++grlib_write_uart (uint32 addr, uint32 data)
++{
++ unsigned char c;
++
++ c = (unsigned char) data;
++ switch (addr & 0xfff)
++ {
++
++ case 0x070: /* UART A */
++#ifdef FAST_UART
++ if (f1open)
++ {
++ if (wnuma < UARTBUF)
++ wbufa[wnuma++] = c;
++ else
++ {
++ while (wnuma)
++ {
++ if (ofd1 == 1 && callback)
++ wnuma -= callback->write_stdout (callback, wbufa, wnuma);
++ else
++ wnuma -= fwrite (wbufa, 1, wnuma, f1out);
++ }
++ wbufa[wnuma++] = c;
++ }
++ }
++ set_irq (3);
++#else
++ if (uart_stat_reg & UARTA_SRE)
++ {
++ uarta_sreg = c;
++ uart_stat_reg &= ~UARTA_SRE;
++ event (uarta_tx, 0, UART_TX_TIME);
++ }
++ else
++ {
++ uarta_hreg = c;
++ uart_stat_reg &= ~UARTA_HRE;
++ }
++#endif
++ break;
++
++ case 0x074: /* UART status register */
++#ifndef FAST_UART
++ uart_stat_reg &= 1;
++#endif
++ break;
++ default:
++ if (sis_verbose)
++ printf ("Write to unimplemented APB register (%x)\n", addr);
++
++ }
++}
++
++static void
++flush_uart (void)
++{
++ while (wnuma && f1open)
++ {
++ if (ofd1 == 1 && callback)
++ {
++ wnuma -= callback->write_stdout (callback, wbufa, wnuma);
++ callback->flush_stdout (callback);
++ }
++ else
++ wnuma -= fwrite (wbufa, 1, wnuma, f1out);
++ }
++}
++
++static void
++uarta_tx (void)
++{
++ while (f1open)
++ {
++ if (ofd1 == 1 && callback)
++ while (callback->write_stdout (callback, &uarta_sreg, 1) != 1)
++ continue;
++ else
++ while (fwrite (&uarta_sreg, 1, 1, f1out) != 1)
++ continue;
++ }
++ if (uart_stat_reg & UARTA_HRE)
++ {
++ uart_stat_reg |= UARTA_SRE;
++ }
++ else
++ {
++ uarta_sreg = uarta_hreg;
++ uart_stat_reg |= UARTA_HRE;
++ event (uarta_tx, 0, UART_TX_TIME);
++ }
++ set_irq (3);
++}
++
++static void
++uart_rx (caddr_t arg)
++{
++ char rxd;
++ int32 rsize = 0;
++
++ if (f1open)
++ rsize = DO_STDIO_READ (ifd1, &rxd, 1);
++ else
++ rsize = 0;
++ if (rsize > 0)
++ {
++ uarta_data = rxd;
++ if (uart_stat_reg & UARTA_DR)
++ {
++ uart_stat_reg |= UARTA_OR;
++ }
++ uart_stat_reg |= UARTA_DR;
++ set_irq (3);
++ }
++ event (uart_rx, 0, UART_RX_TIME);
++}
++
++static void
++uart_intr (caddr_t arg)
++{
++ /* Check for UART interrupts every 1000 clk. */
++ grlib_read_uart (APBUART_STATUS);
++ flush_uart ();
++ event (uart_intr, 0, UART_FLUSH_TIME);
++}
++
++
++static void
++uart_irq_start (void)
++{
++#ifdef FAST_UART
++ event (uart_intr, 0, UART_FLUSH_TIME);
++#else
++#ifndef _WIN32
++ event (uart_rx, 0, UART_RX_TIME);
++#endif
++#endif
++}
++
++/* TIMER */
++
++static void
++gpt_intr (caddr_t arg)
++{
++ int i;
++
++ for (i = 0; i < NTIMERS; i++)
++ {
++ if (gpt_ctrl[i] & 1)
++ {
++ gpt_counter[i] -= 1;
++ if (gpt_counter[i] == -1)
++ {
++ set_irq (TIMER_IRQ + i);
++ if (gpt_ctrl[i] & 2)
++ gpt_counter[i] = gpt_reload[i];
++ }
++ }
++ }
++ event (gpt_intr, 0, gpt_scaler + 1);
++ gpt_scaler_start = now ();
++}
++
++static void
++gpt_init (void)
++{
++ if (sis_verbose)
++ printf ("GPT started (period %d)\n\r", gpt_scaler + 1);
++}
++
++static void
++gpt_reset (void)
++{
++ event (gpt_intr, 0, gpt_scaler + 1);
++ gpt_scaler_start = now ();
++}
++
++static void
++gpt_scaler_set (uint32 val)
++{
++ /* Mask for 16-bit scaler. */
++ gpt_scaler = val & 0x0ffff;
++}
++
++static void
++timer_ctrl (uint32 val, int i)
++{
++ if (val & 4)
++ {
++ /* Reload. */
++ gpt_counter[i] = gpt_reload[i];
++ }
++ gpt_ctrl[i] = val & 0xb;
++}
++
++/* Store data in host byte order. MEM points to the beginning of the
++ emulated memory; WADDR contains the index the emulated memory,
++ DATA points to words in host byte order to be stored. SZ contains log(2)
++ of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word),
++ 2 (one word), or 3 (two words); WS should return the number of wait-states. */
++
++static void
++store_bytes (unsigned char *mem, uint32 waddr, uint32 * data, int32 sz,
++ int32 * ws)
++{
++ switch (sz)
++ {
++ case 0:
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= EBT;
++#endif
++ mem[waddr] = *data & 0x0ff;
++ *ws = 0;
++ break;
++ case 1:
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= 2;
++#endif
++ memcpy (&mem[waddr], data, 2);
++ *ws = 0;
++ break;
++ case 2:
++ memcpy (&mem[waddr], data, 4);
++ *ws = 0;
++ break;
++ case 3:
++ memcpy (&mem[waddr], data, 8);
++ *ws = 0;
++ break;
++ }
++}
++
++
++/* Memory emulation. */
++
++static int
++memory_iread (uint32 addr, uint32 * data, int32 * ws)
++{
++ if ((addr >= RAM_START) && (addr < RAM_END))
++ {
++ memcpy (data, &ramb[addr & RAM_MASK], 4);
++ *ws = 0;
++ return 0;
++ }
++ else if (addr < ROM_END)
++ {
++ memcpy (data, &romb[addr], 4);
++ *ws = 0;
++ return 0;
++ }
++
++ if (sis_verbose)
++ printf ("Memory exception at %x (illegal address)\n", addr);
++ *ws = MEM_EX_WS;
++ return 1;
++}
++
++static int
++memory_read (uint32 addr, uint32 * data, int32 sz, int32 * ws)
++{
++ int32 mexc;
++
++ if ((addr >= RAM_START) && (addr < RAM_END))
++ {
++ memcpy (data, &ramb[addr & RAM_MASK & ~3], 4);
++ *ws = 0;
++ return 0;
++ }
++ else if ((addr >= APBSTART) && (addr < APBEND))
++ {
++ mexc = apb_read (addr, data);
++ if (mexc)
++ *ws = MEM_EX_WS;
++ else
++ *ws = 0;
++ return mexc;
++ }
++ else if (addr < ROM_END)
++ {
++ memcpy (data, &romb[addr & ~3], 4);
++ *ws = 0;
++ return 0;
++ }
++
++ if (sis_verbose)
++ printf ("Memory exception at %x (illegal address)\n", addr);
++ *ws = MEM_EX_WS;
++ return 1;
++}
++
++static int
++memory_read_asi (int32 asi, uint32 addr, uint32 * data, int32 sz, int32 * ws)
++{
++ return memory_read (addr, data, sz, ws);
++}
++
++static int
++memory_write (uint32 addr, uint32 * data, int32 sz, int32 * ws)
++{
++ uint32 byte_addr;
++ uint32 byte_mask;
++ uint32 waddr;
++ uint32 *ram;
++ int32 mexc;
++ int i;
++ int wphit[2];
++
++ if ((addr >= RAM_START) && (addr < RAM_END))
++ {
++ waddr = addr & RAM_MASK;
++ store_bytes (ramb, waddr, data, sz, ws);
++ return 0;
++ }
++ else if ((addr >= APBSTART) && (addr < APBEND))
++ {
++ if (sz != 2)
++ {
++ *ws = MEM_EX_WS;
++ return 1;
++ }
++ apb_write (addr, *data);
++ *ws = 0;
++ return 0;
++ }
++ else if (addr < ROM_END)
++ {
++ *ws = 0;
++ store_bytes (romb, addr, data, sz, ws);
++ return 0;
++ }
++
++ *ws = MEM_EX_WS;
++ return 1;
++}
++
++static int
++memory_write_asi (int32 asi, uint32 addr, uint32 * data, int32 sz, int32 * ws)
++{
++ return memory_write (addr, data, sz, ws);
++}
++
++static unsigned char *
++get_mem_ptr (uint32 addr, uint32 size)
++{
++ if ((addr + size) < ROM_END)
++ {
++ return &romb[addr];
++ }
++ else if ((addr >= RAM_START) && ((addr + size) < RAM_END))
++ {
++ return &ramb[addr & RAM_MASK];
++ }
++
++ return (char *) -1;
++}
++
++static int
++sis_memory_write (uint32 addr, const unsigned char *data, uint32 length)
++{
++ char *mem;
++
++ if ((mem = get_mem_ptr (addr, length)) == ((char *) -1))
++ return 0;
++
++ memcpy (mem, data, length);
++ return length;
++}
++
++static int
++sis_memory_read (uint32 addr, char *data, uint32 length)
++{
++ char *mem;
++ int ws;
++ int w4;
++
++ if (length == 4)
++ {
++ memory_read (addr, &w4, length, &ws);
++ memcpy (data, &w4, length);
++ return 4;
++ }
++
++ if ((mem = get_mem_ptr (addr, length)) == ((char *) -1))
++ return 0;
++
++ memcpy (data, mem, length);
++ return length;
++}
++
++static void
++boot_init (void)
++{
++ /* Generate 1 MHz RTC tick. */
++ apb_write (TIMER_SCALER, sregs.freq - 1);
++ apb_write (TIMER_SCLOAD, sregs.freq - 1);
++ apb_write (TIMER_TIMER1, -1);
++ apb_write (TIMER_RELOAD1, -1);
++ apb_write (TIMER_CTRL1, 0x7);
++
++ sregs.wim = 2;
++ sregs.psr = 0x000010e0;
++ sregs.r[30] = RAM_END;
++ sregs.r[14] = sregs.r[30] - 96 * 4;
++ cache_ctrl = 0x01000f;
++}
++
++const struct memsys leon2 = {
++ init_sim,
++ reset,
++ error_mode,
++ sim_halt,
++ exit_sim,
++ init_stdio,
++ restore_stdio,
++ memory_iread,
++ memory_read,
++ memory_read_asi,
++ memory_write,
++ memory_write_asi,
++ sis_memory_write,
++ sis_memory_read,
++ boot_init
++};
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index e99d1a3..7ff10c9 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -178,6 +178,10 @@ main(argc, argv)
+ dumbio = 1;
+ } else if (strcmp(argv[stat], "-nouartrx") == 0) {
+ nouartrx = 1;
++ } else if (strcmp (argv[stat], "-leon2") == 0) {
++ ms = &leon2;
++ if (freq == 14) freq = 50;
++ cputype = CPU_LEON2;
+ } else if (strcmp (argv[stat], "-leon3") == 0) {
+ ms = &leon3;
+ if (freq == 14) freq = 50;
+@@ -194,6 +198,9 @@ main(argc, argv)
+ }
+
+ switch (cputype) {
++ case CPU_LEON2:
++ printf (" LEON2 emulation enabled\n");
++ break;
+ case CPU_LEON3:
+ printf (" LEON3 emulation enabled\n");
+ break;
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index d06566d..098fb11 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -154,6 +154,7 @@ struct irqcell {
+ #define BPT_HIT 2
+ #define ERROR 3
+ #define CTRL_C 4
++#define CPU_LEON2 2
+ #define CPU_LEON3 3
+
+ /* Prototypes */
+@@ -256,5 +257,8 @@ struct memsys {
+
+ extern const struct memsys *ms;
+
++/* leon2.c */
++extern const struct memsys leon2;
++
+ /* leon3.c */
+ extern const struct memsys leon3;
+--
+2.7.4
+
+From 1934e8c21556a8d19f11112573cc3733d7ca66b5 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri at gaisler.se>
+Date: Wed, 18 Feb 2015 23:10:51 +0100
+Subject: [PATCH 6/9] sim/erc32: Updated documentation.
+
+ Cleaned up documentation. Obsolote README files were removed,
+ main documentation on operation is now in READMEM.sis.
+---
+ sim/erc32/NEWS | 108 ---------------------------
+ sim/erc32/README.gdb | 67 -----------------
+ sim/erc32/README.leon2 | 53 ++++++++++++++
+ sim/erc32/README.sis | 193 ++++++++++++++++---------------------------------
+ sim/erc32/startsim | 18 -----
+ 5 files changed, 117 insertions(+), 322 deletions(-)
+ delete mode 100644 sim/erc32/NEWS
+ delete mode 100644 sim/erc32/README.gdb
+ create mode 100644 sim/erc32/README.leon2
+ delete mode 100644 sim/erc32/startsim
+
+diff --git a/sim/erc32/NEWS b/sim/erc32/NEWS
+deleted file mode 100644
+index dd24b7b..0000000
+--- a/sim/erc32/NEWS
++++ /dev/null
+@@ -1,108 +0,0 @@
+-
+-version 2.0 05-02-96
+---------------------
+-
+-* Switched to bfd library. Any supported format (elf, coff, ...) can be used.
+-* The UART devices can be set through -uart1 and -uart2 switches.
+-* Switched to GNU readline.
+-* Added -c option to run batch files at startup
+-* 'reg' command can show different register windows (eg 'reg w3').
+-* Use 'help' for online help on simulator commands
+-
+-version 1.8.1 20-01-96
+---------------------
+-
+-* added -mevrev0 switch to simulate MEC rev.0 bugs in timer and uart
+-
+-* added -iurev0 switch to simulate IU rev.0 jmpl/restore bug
+-
+-* Added sis command 'batch' to run batch files
+-
+-
+-version 1.8 30-10-95
+---------------------
+-
+-* Added s-record support. Use the '-s' switch with sis or the 'load' command.
+-
+-* IU load dependencies are now modelled
+-
+-version 1.7 30-10-95
+---------------------
+-
+-* Power-down mode implemented in erc32.c.
+-
+-* Performance display shows the ratio between simulator-time and real-time.
+-
+-
+-version 1.6.2 25-10-95
+---------------------
+-
+-* The UARTs can now be run at a given speed (simulator time) to better
+- simulate the behaviour of interrupt routines. The "true mode" is
+- selected through a compile switch in the makefile.
+-
+-
+-version 1.6 28-09-95
+---------------------
+-
+-* Major reorganisation of the code. mec.c and mem.c merged into erc32.c.
+-
+-* The load command does NOT longer load the initialised data at an address
+- defined by .bdata. This is done in srt0.s using _environ.
+-
+-* Additional MEC functionallity added - software reset, memory access
+- protection and waitstate configuration register.
+-
+-* interf.c - a GDB interface added
+-
+-* -v switch (verbose) added
+-
+-version 1.5 14-09-95
+---------------------
+-
+-* Added a instruction trace buffer, enabled through the 'hist' command.
+-
+-* Added a 'perf' command to display statistics such as instruction mix,
+- CPI, FPU holds etc.
+-
+-* Added -nfp switch to disable FPU.
+-
+-* Added -freq switch to set simulated frequency.
+-
+-version 1.4 22-08-95
+---------------------
+-
+-* A -g is provided for those who have problems with GNU readline().
+-
+-version 1.3 26-07-95
+---------------------
+-
+-* No major news, just a bug fix release ...
+-
+-
+-version 1.2 13-07-95
+---------------------
+-
+-* Added setting of IU registers through the 'reg' command. See README.
+-
+-* The GNU readline() function is used for command input. However, a
+-ctrl-D still kills the simulator ...
+-
+-
+-version 1.1 07-07-95
+---------------------
+-
+-
+-* Added a 'go' command
+-
+-* Added cycle counting for interrupt overhead.
+-
+-* Function 'get_mem_ptr' takes one more parameter to avoid segmentation
+- faults if a.out files are loaded outside the simulated memory. See README.
+-
+-* Added user-defined function sim_stop().
+-
+-* Added a reset command. See README.
+-
+-* Implemented buffered output for MEC uarts to improve output speed.
+-
+diff --git a/sim/erc32/README.gdb b/sim/erc32/README.gdb
+deleted file mode 100644
+index 619fcb3..0000000
+--- a/sim/erc32/README.gdb
++++ /dev/null
+@@ -1,67 +0,0 @@
+-How to use SIS with GDB
+------------------------
+-
+-1. Building GDB with SIS
+-
+-To build GDB with the SIS/ERC32 simulator, configure with option
+-'--target sparc-erc32-aout' and build as usual.
+-
+-2. Attaching the simulator
+-
+-To attach GDB to the simulator, use:
+-
+-target sim [options] [files]
+-
+-The following options are supported:
+-
+- -nfp Disable FPU. FPops will cause an FPU disabled trap.
+-
+- -freq <f> Set the simulated "system clock" to <f> MHz.
+-
+- -v Verbose mode.
+-
+- -nogdb Disable GDB breakpoint handling (see below)
+-
+-The listed [files] are expected to be in aout format and will be
+-loaded in the simulator memory prior. This could be used to load
+-a boot block at address 0x0 if the application is linked to run
+-from RAM (0x2000000).
+-
+-To start debugging a program type 'load <program>' and debug as
+-usual.
+-
+-The native simulator commands can be reached using the GDB 'sim'
+-command:
+-
+-sim <sis_command>
+-
+-Direct simulator commands during a GDB session must be issued
+-with care not to disturb GDB's operation ...
+-
+-For info on supported ERC32 functionality, see README.sis.
+-
+-
+-3. Loading aout files
+-
+-The GDB load command loads an aout file into the simulator
+-memory with the data section starting directly after the text
+-section regardless of wich start address was specified for the data
+-at link time! This means that your applications either has to include
+-a routine that initialise the data segment at the proper address or
+-link with the data placed directly after the text section.
+-
+-A copying routine is fairly simple, just copy all data between
+-_etext and _data to a memory loaction starting at _environ. This
+-should be done at the same time as the bss is cleared (in srt0.s).
+-
+-
+-4. GDB breakpoint handling
+-
+-GDB inserts breakpoint in the form of the 'ta 1' instruction. The
+-GDB-integrated simulator will therefore recognize the breakpoint
+-instruction and return control to GDB. If the application uses
+-'ta 1', the breakpoint detection can be disabled with the -nogdb
+-switch. In this case however, GDB breakpoints will not work.
+-
+-
+-Report problems to Jiri Gaisler ESA/ESTEC (jgais at wd.estec.esa.nl)
+diff --git a/sim/erc32/README.leon2 b/sim/erc32/README.leon2
+new file mode 100644
+index 0000000..19f2fbb
+--- /dev/null
++++ b/sim/erc32/README.leon2
+@@ -0,0 +1,53 @@
++
++1. LEON2 emulation
++
++The file 'leon2.c' contains a model of simple LEON2 sub-system. It
++contains 16 Mbyte ROM and 16 Mbyte RAM. Standard peripherals
++such as interrupt controller, UART and timer are provided.
++The model can execute leon2 binaries that do not require an
++MMU.
++
++To start sis in Leon2 mode, add the -leon2 switch. In gdb,
++use 'target sim -leon2' .
++
++1.1 UART
++
++One LEON2 UART is emaulted, and is located at address 0x80000070.
++The following registers are implemeted:
++
++- UART RX and TX register (0x80000070)
++- UART status register (0x80000074)
++
++The UART generates interrupt 3.
++
++1.2 Timer unit
++
++The LEON2 timer unit is emulated and located at address 0x80000040.
++It is configured with two timers and separate interrupts (8 and 9).
++The scaler is configured to 16 bits, while the counters are 32 bits.
++
++1.3 Interrupt controller
++
++The interrupt controller is implemented as described in the
++LEON2 IP manual, with the exception of the interrupt level register.
++Secondary interrupts are not supported. The registers are located
++at address 0x80000090.
++
++1.5 Memory interface
++
++The following memory areas are valid for the Leon3 simulator:
++
++0x00000000 - 0x01000000 ROM (16 Mbyte, loaded at start-up)
++0x40000000 - 0x41000000 RAM (16 Mbyte, loaded at start-up)
++0x80000000 - 0x81000000 APB bus, including plug&play
++0xFFFFF000 - 0xFFFFFFFF AHB plug&play area
++
++Access to non-existing memory will result in a memory exception trap.
++
++1.8 Power-down mode
++
++The Leon2 power-down register (0x80000018) is supported. When power-down is
++entered, time is skipped forward until the next event in the event queue.
++However, if the simulator event queue is empty, power-down mode is not
++entered since no interrupt would be generated to exit from the mode. A
++Ctrl-C in the simulator window will exit the power-down mode.
+diff --git a/sim/erc32/README.sis b/sim/erc32/README.sis
+index db6b4cc..60a9c3f 100644
+--- a/sim/erc32/README.sis
++++ b/sim/erc32/README.sis
+@@ -11,13 +11,14 @@ and peripherals.
+
+ 2. Usage
+
+-The simulator is started as follows:
++The simulator is started as follows:
+
+-sis [-leon3] [-uart1 uart_device1] [-uart2 uart_device2]
+- [-nfp] [-freq frequency] [-c batch_file] [files]
++sis [-leon2] [-leon3] [-uart1 uart_device1] [-uart2 uart_device2]
++ [-nfp] [-freq frequency] [-c batch_file] [-v] [files]
+
+-By default, SIS emulates an ERC32 system. The -leon3 switch
+-enables emulation of a LEON3 SOC system.
++By default, SIS emulates an ERC32 system. The -leon2 switch enables
++LEON2 emulation, while the -leon3 switch enables emulation of a
++LEON3 SOC system.
+
+ The emulated console uart is connected to stdin/stdout. The -uart[1,2]
+ switch can be used to connect the uarts to other devices.
+@@ -143,8 +144,50 @@ Typing a 'Ctrl-C' will interrupt a running simulator.
+ Short forms of the commands are allowed, e.g 'c' 'co' or 'con' are all
+ interpreted as 'cont'.
+
++2. Using SIS with GDB
+
+-3. Simulator core
++To attach GDB to the simulator, use:
++
++target sim [options]
++
++The following options are supported:
++
++ -leon2 Emulate a LEON2 system
++
++ -leon3 Emulate a LEON3 system
++
++ -nfp Disable FPU. FPops will cause an FPU disabled trap.
++
++ -freq <f> Set the simulated "system clock" to <f> MHz.
++
++ -v Verbose mode.
++
++ -nogdb Disable GDB breakpoint handling (see below)
++
++To start debugging a program type 'load <program>' and debug as
++usual.
++
++The native simulator commands can be reached using the GDB 'sim'
++command:
++
++sim <sis_command>
++
++Direct simulator commands during a GDB session must be issued
++with care not to disturb GDB's operation ...
++
++A program can be restarted in GDB by first issuing the load command,
++followed by run.
++
++3. GDB breakpoint handling
++
++GDB inserts breakpoint in the form of the 'ta 1' instruction. The
++GDB-integrated simulator will therefore recognize the breakpoint
++instruction and return control to GDB. If the application uses
++'ta 1', the breakpoint detection can be disabled with the -nogdb
++switch. In this case however, GDB breakpoints will not work.
++
++
++4. Simulator core
+
+ In ERC32 mode, SIS emulates the behavior of the 90C601E and 90C602E
+ sparc IU and FPU from Matra MHS. These are roughly equivalent to the
+@@ -153,129 +196,10 @@ time is maintained and incremented according the IU and FPU instruction timing.
+ The parallel execution between the IU and FPU is modelled, as well as
+ stalls due to operand dependencies (FPU).
+
+-In Leon3 mode, the core emulates the Leon3 SPARC V8 core from
++In Leon2/3 mode, the core emulates the Leon2/3 SPARC V8 core from
+ Gaisler Research. All SPARC V8 instructions are supported but
+ emulation is not fully cycle-true as the cache is not emulated.
+
+-The core interacts with the user-defined memory modules through
+-a number of functions. The memory module must provide the following
+-functions:
+-
+-int memory_read(asi,addr,data,ws)
+-int asi;
+-unsigned int addr;
+-unsigned int *data;
+-int *ws;
+-
+-int memory_write(asi,addr,data,sz,ws)
+-int asi;
+-unsigned int addr;
+-unsigned int *data;
+-int sz;
+-int *ws;
+-
+-int sis_memory_read(addr, data, length)
+-unsigned int addr;
+-char *data;
+-unsigned int length;
+-
+-int sis_memory_write(addr, data, length)
+-unsigned int addr;
+-char *data;
+-unsigned int length;
+-
+-int init_sim()
+-
+-int reset()
+-
+-int error_mode(pc)
+-unsigned int pc;
+-
+-memory_read() is used by the simulator to fetch instructions and
+-operands. The address space identifier (asi) and address is passed as
+-parameters. The read data should be assigned to the data pointer
+-(*data) and the number of waitstate to *ws. 'memory_read' should return
+-0 on success and 1 on failure. A failure will cause a data or
+-instruction fetch trap. memory_read() always reads one 32-bit word.
+-
+-sis_memory_read() is used by the simulator to display and disassemble
+-memory contants. The function should copy 'length' bytes of the simulated
+-memory starting at 'addr' to '*data'.
+-The sis_memory_read() should return 1 on success and 0 on failure.
+-Failure should only be indicated if access to unimplemented memory is attempted.
+-
+-memory_write() is used to write to memory. In addition to the asi
+-and address parameters, the size of the written data is given by 'sz'.
+-The pointer *data points to the data to be written. The 'sz' is coded
+-as follows:
+-
+- sz access type
+- 0 byte
+- 1 halfword
+- 2 word
+- 3 double-word
+-
+-If a double word is written, the most significant word is in data[0] and
+-the least significant in data[1].
+-
+-sis_memory_write() is used by the simulator during loading of programs.
+-The function should copy 'length' bytes from *data to the simulated
+-memory starting at 'addr'. sis_memory_write() should return 1 on
+-success and 0 on failure. Failure should only be indicated if access
+-to unimplemented memory is attempted. See erc32.c for more details
+-on how to define the memory emulation functions.
+-
+-The 'init_sim' is called once when the simulator is started. This function
+-should be used to perform initialisations of user defined memory or
+-peripherals that only have to be done once, such as opening files etc.
+-
+-The 'reset' is called every time the simulator is reset, i.e. when a
+-'run' command is given. This function should be used to simulate a power
+-on reset of memory and peripherals.
+-
+-error_mode() is called by the simulator when the IU goes into error mode,
+-typically if a trap is caused when traps are disabled. The memory module
+-can then take actions, such as issue a reset.
+-
+-sys_reset() can be called by the memory module to reset the simulator. A
+-reset will empty the event queue and perform a power-on reset.
+-
+-4. Events and interrupts
+-
+-The simulator supports an event queue and the generation of processor
+-interrupts. The following functions are available to the user-defined
+-memory module:
+-
+-event(cfunc,arg,delta)
+-void (*cfunc)();
+-int arg;
+-unsigned int delta;
+-
+-set_int(level,callback,arg)
+-int level;
+-void (*callback)();
+-int arg;
+-
+-clear_int(level)
+-int level;
+-
+-sim_stop()
+-
+-The 'event' functions will schedule the execution of the function 'cfunc'
+-at time 'now + delta' clock cycles. The parameter 'arg' is passed as a
+-parameter to 'cfunc'.
+-
+-The 'set_int' function set the processor interrupt 'level'. When the interrupt
+-is taken, the function 'callback' is called with the argument 'arg'. This
+-will also clear the interrupt. An interrupt can be cleared before it is
+-taken by calling 'clear_int' with the appropriate interrupt level.
+-
+-The sim_stop function is called each time the simulator stops execution.
+-It can be used to flush buffered devices to get a clean state during
+-single stepping etc.
+-
+-See 'erc32.c' for examples on how to use events and interrupts.
+-
+ 5. Memory module
+
+ The ERC32 memory module (erc32.c) emulates the functions of memory and
+@@ -292,6 +216,19 @@ the MEC asic developed for the 90C601/2. It includes the following functions:
+
+ See README.erc32 on how the MEC functions are emulated.
+
++The Leon2 memory module (leon2.c) emulates on-chip peripherals and
++external memory for a simple Leon2 system. The modules includes the
++following functions:
++
++* AHB and APB buses
++* One UART
++* Interrupt controller
++* Timer unit with two timers
++* PROM/SRAM memory controller
++* 16 Mbyte PROM, 16 Mbyte SRAM
++
++See README.leon2 for further details on Leon2 emulation.
++
+ The Leon3 memory module (leon3.c) emulates on-chip peripherals and
+ external memory for a simple Leon3 system. The modules includes the
+ following functions:
+@@ -305,9 +242,7 @@ following functions:
+
+ See README.leon3 for further details on Leon3 emulation.
+
+-6. Compile and linking programs
+-
+-7. IU and FPU instruction timing.
++6. IU and FPU instruction timing.
+
+ The simulator provides cycle true simulation for ERC32. The following table
+ shows the emulated instruction timing for 90C601E & 90C602E:
+diff --git a/sim/erc32/startsim b/sim/erc32/startsim
+deleted file mode 100644
+index 5a4f2cf..0000000
+--- a/sim/erc32/startsim
++++ /dev/null
+@@ -1,18 +0,0 @@
+-# Copyright (C) 1996-2016 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 3 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program. If not, see <http://www.gnu.org/licenses/>.
+-
+-xterm -e sis $* &
+-xterm -e tip /dev/ttypc &
+-
+--
+2.7.4
+
+From 13160e2a8af0441239ff5d308d6c1cc1a12ac502 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri at gaisler.se>
+Date: Sun, 8 May 2016 15:30:24 +0200
+Subject: [PATCH 7/9] sim/erc32: Add data watchpoint support
+
+ Added watchpoint support to all processor targets (erc32, leon2, leon3).
+---
+ sim/erc32/exec.c | 56 ++++++++++++++++++++++++++-------
+ sim/erc32/func.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ sim/erc32/interf.c | 3 +-
+ sim/erc32/sis.c | 32 ++++++++++++++-----
+ sim/erc32/sis.h | 25 +++++++++++++--
+ 5 files changed, 182 insertions(+), 24 deletions(-)
+
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index bacac4c..fb17060 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -392,6 +392,20 @@ extract_byte_signed (uint32 data, uint32 address)
+ return tmp;
+ }
+
++/* Decode watchpoint address mask from opcode. Not correct for LDST,
++ SWAP and STFSR but watchpoints will work anyway. */
++
++static unsigned char
++wpmask(uint32 op3)
++{
++ switch (op3 & 3) {
++ case 0: return(3); /* word */
++ case 1: return(0); /* byte */
++ case 2: return(1); /* half-word */
++ case 3: return(7); /* double word */
++ }
++}
++
+ int
+ dispatch_instruction(sregs)
+ struct pstate *sregs;
+@@ -695,6 +709,12 @@ dispatch_instruction(sregs)
+ }
+ if (eicc & 1) {
+ sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f));
++ if ((sregs->trap == 129) && (sis_gdb_break) &&
++ (sregs->inst == 0x91d02001))
++ {
++ sregs->trap = WPT_TRAP;
++ sregs->bphit = 1;
++ }
+ }
+ break;
+
+@@ -1201,18 +1221,25 @@ dispatch_instruction(sregs)
+
+ address = rs1 + operand2;
+
+- if (sregs->psr & PSR_S)
+- asi = 11;
+- else
+- asi = 10;
+-
+ if (op3 & 4) {
+ sregs->icnt = T_ST; /* Set store instruction count */
++ if (sregs->wpwnum) {
++ if (sregs->wphit = check_wpw(sregs, address, wpmask(op3))) {
++ sregs->trap = WPT_TRAP;
++ break;
++ }
++ }
+ #ifdef STAT
+ sregs->nstore++;
+ #endif
+ } else {
+ sregs->icnt = T_LD; /* Set load instruction count */
++ if (sregs->wprnum) {
++ if (sregs->wphit = check_wpr(sregs, address, wpmask(op3))) {
++ sregs->trap = WPT_TRAP;
++ break;
++ }
++ }
+ #ifdef STAT
+ sregs->nload++;
+ #endif
+@@ -2118,12 +2145,18 @@ execute_trap(sregs)
+ {
+ int32 cwp;
+
+- if (sregs->trap == 256) {
+- sregs->pc = 0;
+- sregs->npc = 4;
+- sregs->trap = 0;
+- } else if (sregs->trap == 257) {
+- return ERROR;
++ if (sregs->trap >= 256) {
++ switch (sregs->trap) {
++ case 256:
++ sregs->pc = 0;
++ sregs->npc = 4;
++ sregs->trap = 0;
++ break;
++ case ERROR_TRAP:
++ return (ERROR);
++ case WPT_TRAP:
++ return (WPT_HIT);
++ }
+ } else {
+
+ if ((sregs->psr & PSR_ET) == 0)
+@@ -2216,6 +2249,7 @@ init_regs(sregs)
+ sregs->fpu_pres = !nfp;
+ set_fsr(sregs->fsr);
+ sregs->bphit = 0;
++ sregs->wphit = 0;
+ sregs->ildreg = 0;
+ sregs->ildtime = 0;
+
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index 29fb667..5c0b185 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -59,7 +59,8 @@ uint32 last_load_addr = 0;
+ int nouartrx = 0;
+ host_callback *sim_callback;
+ const struct memsys *ms = &erc32sys;
+-int cputype = 0; /* 0 = erc32, 3 = leon3 */
++int cputype = 0; /* 0 = erc32, 2 = leon2,3 = leon3 */
++int sis_gdb_break;
+
+ #ifdef ERRINJ
+ uint32 errcnt = 0;
+@@ -614,6 +615,53 @@ exec_cmd(struct pstate *sregs, const char *cmd)
+ stat = run_sim(sregs, UINT64_MAX, 0);
+ daddr = sregs->pc;
+ ms->sim_halt ();
++ } else if (strncmp(cmd1, "wp", clen) == 0) {
++ for (i = 0; i < sregs->wprnum; i++) {
++ printf(" %d : 0x%08x (read)\n", i + 1, sregs->wprs[i]);
++ }
++ for (i = 0; i < sregs->wpwnum; i++) {
++ printf(" %d : 0x%08x (write)\n", i + 1, sregs->wpws[i]);
++ }
++ } else if (strncmp(cmd1, "+wpr", clen) == 0) {
++ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
++ sregs->wprs[sregs->wprnum] = VAL(cmd1) & ~0x3;
++ sregs->wprm[sregs->wprnum] = 3;
++ printf("added read watchpoint %d at 0x%08x\n",
++ sregs->wprnum + 1, sregs->wprs[sregs->wprnum]);
++ sregs->wprnum += 1;
++ }
++ } else if (strncmp(cmd1, "-wpr", clen) == 0) {
++ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
++ i = VAL(cmd1) - 1;
++ if ((i >= 0) && (i < sregs->wprnum)) {
++ printf("deleted read watchpoint %d at 0x%08x\n", i + 1,
++ sregs->wprs[i]);
++ for (; i < sregs->wprnum - 1; i++) {
++ sregs->wprs[i] = sregs->wprs[i + 1];
++ }
++ sregs->wprnum -= 1;
++ }
++ }
++ } else if (strncmp(cmd1, "+wpw", clen) == 0) {
++ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
++ sregs->wpws[sregs->wpwnum] = VAL(cmd1) & ~0x3;
++ sregs->wpwm[sregs->wpwnum] = 3;
++ printf("added write watchpoint %d at 0x%08x\n",
++ sregs->wpwnum + 1, sregs->wpws[sregs->wpwnum]);
++ sregs->wpwnum += 1;
++ }
++ } else if (strncmp(cmd1, "-wpw", clen) == 0) {
++ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
++ i = VAL(cmd1) - 1;
++ if ((i >= 0) && (i < sregs->wpwnum)) {
++ printf("deleted write watchpoint %d at 0x%08x\n", i + 1,
++ sregs->wpws[i]);
++ for (; i < sregs->wpwnum - 1; i++) {
++ sregs->wpws[i] = sregs->wpws[i + 1];
++ }
++ sregs->wpwnum -= 1;
++ }
++ }
+ } else
+ printf("syntax error\n");
+ }
+@@ -704,6 +752,8 @@ init_bpt(sregs)
+ struct pstate *sregs;
+ {
+ sregs->bptnum = 0;
++ sregs->wprnum = 0;
++ sregs->wpwnum = 0;
+ sregs->histlen = 0;
+ sregs->histind = 0;
+ sregs->histbuf = NULL;
+@@ -1011,6 +1061,44 @@ check_bpt(sregs)
+ return 0;
+ }
+
++int
++check_wpr(sregs, address, mask)
++ struct pstate *sregs;
++ int32 address;
++ unsigned char mask;
++{
++ int32 i, msk;
++
++ for (i = 0; i < sregs->wprnum; i++) {
++ msk = ~(mask | sregs->wprm[i]);
++ if (((address ^ sregs->wprs[i]) & msk) == 0) {
++ sregs->wpaddress = address;
++ if (sregs->wphit) return (0);
++ return (WPT_HIT);
++ }
++ }
++ return (0);
++}
++
++int
++check_wpw(sregs, address, mask)
++ struct pstate *sregs;
++ int32 address;
++ unsigned char mask;
++{
++ int32 i, msk;
++
++ for (i = 0; i < sregs->wpwnum; i++) {
++ msk = ~(mask | sregs->wpwm[i]);
++ if (((address ^ sregs->wpws[i]) & msk) == 0) {
++ sregs->wpaddress = address;
++ if (sregs->wphit) return (0);
++ return (WPT_HIT);
++ }
++ }
++ return (0);
++}
++
+ void
+ reset_all()
+ {
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index b62ed40..bcc31ad 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -33,8 +33,6 @@
+
+ #define PSR_CWP 0x7
+
+-int sis_gdb_break = 1;
+-
+ int
+ run_sim(sregs, icount, dis)
+ struct pstate *sregs;
+@@ -147,6 +145,7 @@ sim_open (kind, callback, abfd, argv)
+
+ sim_callback = callback;
+
++ sis_gdb_break = 1;
+ argc = countargv (argv);
+ while (stat < argc) {
+ if (argv[stat][0] == '-') {
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index 7ff10c9..d7581ec 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -72,11 +72,7 @@ run_sim(sregs, icount, dis)
+ sregs->trap = I_ACC_EXC;
+ } else {
+ if (deb) {
+- if ((sregs->bphit = check_bpt(sregs)) != 0) {
+- ms->restore_stdio ();
+- return BPT_HIT;
+- }
+- if (sregs->histlen) {
++ if (sregs->histlen) {
+ sregs->histbuf[sregs->histind].addr = sregs->pc;
+ sregs->histbuf[sregs->histind].time = ebase.simtime;
+ sregs->histind++;
+@@ -87,14 +83,25 @@ run_sim(sregs, icount, dis)
+ printf(" %8" PRIu64 " ", ebase.simtime);
+ dis_mem(sregs->pc, 1, &dinfo);
+ }
++ if ((sregs->bptnum) && (sregs->bphit = check_bpt(sregs)))
++ icount = 0;
++ else {
++ dispatch_instruction(sregs);
++ icount--;
++ }
++ } else {
++ dispatch_instruction(sregs);
++ icount--;
+ }
+- dispatch_instruction(sregs);
+- icount--;
+ }
+ }
+ if (sregs->trap) {
+ irq = 0;
+- sregs->err_mode = execute_trap(sregs);
++ if ((sregs->err_mode = execute_trap(sregs)) == WPT_HIT) {
++ sregs->err_mode = 0;
++ sregs->trap = 0;
++ icount = 0;
++ }
+ if (sregs->err_mode) {
+ ms->error_mode (sregs->pc);
+ icount = 0;
+@@ -115,6 +122,10 @@ run_sim(sregs, icount, dis)
+ ctrl_c = 0;
+ return CTRL_C;
+ }
++ if (sregs->bphit)
++ return (BPT_HIT);
++ if (sregs->wphit)
++ return (WPT_HIT);
+ return TIME_OUT;
+ }
+
+@@ -278,6 +289,11 @@ main(argc, argv)
+ printf(" %8" PRIu64 " ", ebase.simtime);
+ dis_mem(sregs.pc, 1, &dinfo);
+ break;
++ case WPT_HIT:
++ printf("watchpoint at 0x%08x reached, pc = 0x%08x\n",
++ sregs.wpaddress, sregs.pc);
++ sregs.wphit = 1;
++ break;
+ default:
+ break;
+ }
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index 098fb11..f370dce 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -36,8 +36,10 @@
+ /* Maximum # of floating point queue */
+ #define FPUQN 1
+
+-/* Maximum # of breakpoints */
++/* Maximum # of breakpoints and watchpoints */
+ #define BPT_MAX 256
++#define WPR_MAX 256
++#define WPW_MAX 256
+
+ struct histype {
+ unsigned addr;
+@@ -97,6 +99,14 @@ struct pstate {
+ uint32 bptnum;
+ uint32 bphit;
+ uint32 bpts[BPT_MAX]; /* Breakpoints */
++ uint32 wprnum;
++ uint32 wphit;
++ uint32 wprs[WPR_MAX]; /* Read Watchpoints */
++ unsigned char wprm[WPR_MAX]; /* Read Watchpoint masks*/
++ uint32 wpwnum;
++ uint32 wpws[WPW_MAX]; /* Write Watchpoints */
++ unsigned char wpwm[WPW_MAX]; /* Write Watchpoint masks */
++ uint32 wpaddress;
+
+ uint32 ltime; /* Load interlock time */
+ uint32 hold; /* IU hold cycles in current inst */
+@@ -148,12 +158,19 @@ struct irqcell {
+ int32 arg;
+ };
+
+-
++/* return values for run_sim */
+ #define OK 0
+ #define TIME_OUT 1
+ #define BPT_HIT 2
+ #define ERROR 3
+ #define CTRL_C 4
++#define WPT_HIT 5
++
++/* special simulator trap types */
++#define ERROR_TRAP 257
++#define WPT_TRAP 258
++
++/* cpu type defines */
+ #define CPU_LEON2 2
+ #define CPU_LEON3 3
+
+@@ -202,6 +219,9 @@ extern void advance_time (struct pstate *sregs);
+ extern uint32 now (void);
+ extern int wait_for_irq (void);
+ extern int check_bpt (struct pstate *sregs);
++extern int check_wpr(struct pstate *sregs, int32 address, unsigned char mask);
++extern int check_wpw(struct pstate *sregs, int32 address, unsigned char mask);
++
+ extern void reset_all (void);
+ extern void sys_reset (void);
+ extern void sys_halt (void);
+@@ -212,6 +232,7 @@ extern host_callback *sim_callback;
+ extern int dumbio;
+ extern int tty_setup;
+ extern int cputype;
++extern int sis_gdb_break;
+
+
+ /* exec.c */
+--
+2.7.4
+
+From 313bdf9a8221dd769304bdc8223c925a3d05d87f Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri at gaisler.se>
+Date: Sat, 21 May 2016 22:48:58 +0200
+Subject: [PATCH 8/9] Add watchpoint support to gdb simulator interface.
+
+ Currently, only the sparc sim supports watchpoints. Stubs for the
+ watchpoint functions were added to all other built-in sims
+ to avoid linking errors.
+---
+ gdb/remote-sim.c | 69 +++++++++++++
+ include/gdb/remote-sim.h | 24 +++++
+ sim/arm/wrapper.c | 25 +++++
+ sim/avr/interp.c | 25 +++++
+ sim/bfin/Makefile.in | 1 +
+ sim/common/sim-watch-remote.c | 27 +++++
+ sim/cris/Makefile.in | 1 +
+ sim/erc32/interf.c | 233 +++++++++++++++++++++++++++++++++---------
+ sim/frv/Makefile.in | 1 +
+ sim/ft32/Makefile.in | 1 +
+ sim/h8300/Makefile.in | 1 +
+ sim/iq2000/Makefile.in | 1 +
+ sim/lm32/Makefile.in | 1 +
+ sim/m32c/gdb-if.c | 25 +++++
+ sim/m32r/Makefile.in | 1 +
+ sim/m68hc11/Makefile.in | 1 +
+ sim/mcore/interp.c | 25 +++++
+ sim/microblaze/Makefile.in | 1 +
+ sim/mips/Makefile.in | 2 +-
+ sim/mn10300/Makefile.in | 1 +
+ sim/moxie/interp.c | 25 +++++
+ sim/msp430/Makefile.in | 1 +
+ sim/ppc/gdb-sim.c | 25 +++++
+ sim/rl78/gdb-if.c | 25 +++++
+ sim/rx/gdb-if.c | 25 +++++
+ sim/sh/interp.c | 25 +++++
+ sim/sh64/Makefile.in | 1 +
+ sim/v850/Makefile.in | 1 +
+ 28 files changed, 543 insertions(+), 51 deletions(-)
+ create mode 100644 sim/common/sim-watch-remote.c
+
+diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
+index 8489eb6..488caf6 100644
+--- a/gdb/remote-sim.c
++++ b/gdb/remote-sim.c
+@@ -1303,6 +1303,70 @@ gdbsim_has_memory (struct target_ops *ops)
+ return 1;
+ }
+
++static int
++gdbsim_insert_watchpoint (struct target_ops *self,
++ CORE_ADDR addr, int len, enum target_hw_bp_type type,
++ struct expression *cond)
++{
++ struct sim_inferior_data *sim_data
++ = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
++
++ if (remote_debug)
++ fprintf_unfiltered (gdb_stdlog, "gdbsim_insert_watchpoint: %d\n", type);
++
++ if (sim_set_watchpoint (sim_data->gdbsim_desc, addr, len, type) != SIM_RC_OK)
++ return -1;
++
++ return 0;
++}
++
++static int
++gdbsim_remove_watchpoint (struct target_ops *self,
++ CORE_ADDR addr, int len, enum target_hw_bp_type type,
++ struct expression *cond)
++{
++ struct sim_inferior_data *sim_data
++ = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
++
++ if (remote_debug)
++ fprintf_unfiltered (gdb_stdlog, "gdbsim_remove_watchpoint: %d\n", type);
++
++ if (sim_clear_watchpoint (sim_data->gdbsim_desc, addr, len, type) != SIM_RC_OK)
++ return -1;
++
++ return 0;
++}
++
++
++static int
++gdbsim_can_use_hw_breakpoint (struct target_ops *self,
++ enum bptype type, int cnt, int othertype)
++{
++ struct sim_inferior_data *sim_data
++ = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
++
++ return (sim_can_use_hw_breakpoint(sim_data->gdbsim_desc, type, cnt, othertype));
++}
++
++static int
++gdbsim_stopped_by_watchpoint (struct target_ops *ops)
++{
++ struct sim_inferior_data *sim_data
++ = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
++
++ return (sim_stopped_by_watchpoint(sim_data->gdbsim_desc));;
++}
++
++static int
++gdbsim_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr)
++{
++ struct sim_inferior_data *sim_data
++ = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
++
++ *addr = sim_watchpoint_address(sim_data->gdbsim_desc);;
++ return (1);
++}
++
+ /* Define the target subroutine names. */
+
+ struct target_ops gdbsim_ops;
+@@ -1325,6 +1389,11 @@ init_gdbsim_ops (void)
+ gdbsim_ops.to_files_info = gdbsim_files_info;
+ gdbsim_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ gdbsim_ops.to_remove_breakpoint = memory_remove_breakpoint;
++ gdbsim_ops.to_insert_watchpoint = gdbsim_insert_watchpoint;
++ gdbsim_ops.to_remove_watchpoint = gdbsim_remove_watchpoint;
++ gdbsim_ops.to_stopped_by_watchpoint = gdbsim_stopped_by_watchpoint;
++ gdbsim_ops.to_can_use_hw_breakpoint = gdbsim_can_use_hw_breakpoint;
++ gdbsim_ops.to_stopped_data_address = gdbsim_stopped_data_address;
+ gdbsim_ops.to_kill = gdbsim_kill;
+ gdbsim_ops.to_load = gdbsim_load;
+ gdbsim_ops.to_create_inferior = gdbsim_create_inferior;
+diff --git a/include/gdb/remote-sim.h b/include/gdb/remote-sim.h
+index fc12898..6080afb 100644
+--- a/include/gdb/remote-sim.h
++++ b/include/gdb/remote-sim.h
+@@ -283,6 +283,30 @@ void sim_do_command (SIM_DESC sd, const char *cmd);
+
+ char **sim_complete_command (SIM_DESC sd, const char *text, const char *word);
+
++/* Add hardware watchpoint. See to_insert_watchpoint() in target.h
++ for description of parameters. */
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type);
++
++/* Remove hardware watchpoint. See to_remove_watchpoint() in target.h
++ for description of parameters. */
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type);
++
++/* Returns data address when watchpoint has been hit. See
++ to_stopped_data_address() in target.h for description. */
++
++int sim_watchpoint_address (SIM_DESC sd);
++
++/* Returns 1 if simulator was stopped by watchpoint hit. */
++
++int sim_stopped_by_watchpoint(SIM_DESC sd);
++
++/* Returns non-zero if we can set a hardware watchpoint of type TYPE.
++ See to_can_use_hw_breakpoint() in target.h for details. */
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/sim/arm/wrapper.c b/sim/arm/wrapper.c
+index 941a8fd..da04ba5 100644
+--- a/sim/arm/wrapper.c
++++ b/sim/arm/wrapper.c
+@@ -921,3 +921,28 @@ sim_stop_reason (SIM_DESC sd ATTRIBUTE_UNUSED,
+ *sigrc = 0;
+ }
+ }
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/avr/interp.c b/sim/avr/interp.c
+index 31a9940..35c314b 100644
+--- a/sim/avr/interp.c
++++ b/sim/avr/interp.c
+@@ -1775,3 +1775,28 @@ sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
+
+ return SIM_RC_OK;
+ }
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/bfin/Makefile.in b/sim/bfin/Makefile.in
+index 873e86b..f2e5748 100644
+--- a/sim/bfin/Makefile.in
++++ b/sim/bfin/Makefile.in
+@@ -27,6 +27,7 @@ SIM_OBJS = \
+ gui.o \
+ interp.o \
+ machs.o \
++ sim-watch-remote.o \
+ sim-resume.o
+
+ INCLUDE = bfin-sim.h
+diff --git a/sim/common/sim-watch-remote.c b/sim/common/sim-watch-remote.c
+new file mode 100644
+index 0000000..279bb06
+--- /dev/null
++++ b/sim/common/sim-watch-remote.c
+@@ -0,0 +1,27 @@
++
++#include "gdb/remote-sim.h"
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/cris/Makefile.in b/sim/cris/Makefile.in
+index 4c7e17a..f41c202 100644
+--- a/sim/cris/Makefile.in
++++ b/sim/cris/Makefile.in
+@@ -24,6 +24,7 @@ CRISV32F_OBJS = crisv32f.o cpuv32.o decodev32.o modelv32.o mloopv32f.o
+
+ SIM_OBJS = \
+ $(SIM_NEW_COMMON_OBJS) \
++ sim-watch-remote.o \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o \
+ sim-if.o arch.o \
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index bcc31ad..f19054a 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -30,6 +30,7 @@
+
+ #include "gdb/remote-sim.h"
+ #include "gdb/signals.h"
++#include "gdb/common/break-common.h"
+
+ #define PSR_CWP 0x7
+
+@@ -47,38 +48,15 @@ run_sim(sregs, icount, dis)
+ ms->init_stdio ();
+ sregs->starttime = get_time();
+ irq = 0;
++ if (sregs->err_mode) icount = 0;
+ if ((sregs->pc != 0) && (ebase.simtime == 0))
+ ms->boot_init ();
+- while (!sregs->err_mode & (icount > 0)) {
+-
++ while (icount > 0) {
+ sregs->fhold = 0;
+- sregs->hold = 0;
+ sregs->icnt = 1;
+-
+- if (sregs->psr & 0x080)
+- sregs->asi = 8;
+- else
+- sregs->asi = 9;
+-
+-#if 0 /* DELETE ME! for debugging purposes only */
+- if (sis_verbose > 1)
+- if (sregs->pc == 0 || sregs->npc == 0)
+- printf ("bogus pc or npc\n");
+-#endif
+ mexc = ms->memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
+-#if 0 /* DELETE ME! for debugging purposes only */
+- if (sis_verbose > 2)
+- printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
+- sregs->pc, sregs->npc,
+- sregs->r[(((sregs->psr & 7) << 4) + 14) & 0x7f],
+- sregs->r[(((sregs->psr & 7) << 4) + 30) & 0x7f],
+- sregs->wim,
+- sregs->psr & 7,
+- sregs->inst);
+-#endif
+ if (sregs->annul) {
+ sregs->annul = 0;
+- sregs->icnt = 1;
+ sregs->pc = sregs->npc;
+ sregs->npc = sregs->npc + 4;
+ } else {
+@@ -87,47 +65,39 @@ run_sim(sregs, icount, dis)
+ if (mexc) {
+ sregs->trap = I_ACC_EXC;
+ } else {
+- if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) {
+- if (sis_verbose)
+- (*sim_callback->printf_filtered) (sim_callback,
+- "SW BP hit at %x\n", sregs->pc);
+- ms->sim_halt ();
+- ms->restore_stdio ();
+- clearerr(stdin);
+- return BPT_HIT;
+- } else
+- dispatch_instruction(sregs);
++ dispatch_instruction(sregs);
++ icount--;
+ }
+- icount--;
+ }
+ if (sregs->trap) {
+ irq = 0;
+- sregs->err_mode = execute_trap(sregs);
++ if ((sregs->err_mode = execute_trap(sregs)) == WPT_HIT) {
++ sregs->err_mode = 0;
++ sregs->trap = 0;
++ icount = 0;
++ }
++ if (sregs->err_mode) icount = 0;
+ }
+ }
+ advance_time(sregs);
+- if (ctrl_c) {
++ if (ctrl_c)
+ icount = 0;
+- }
+ }
+ ms->sim_halt ();
+ sregs->tottime += get_time() - sregs->starttime;
+ ms->restore_stdio ();
+ clearerr(stdin);
+- if (sregs->err_mode)
++ if (sregs->err_mode) {
+ ms->error_mode (sregs->pc);
+- if (sregs->err_mode)
+ return ERROR;
+- if (sregs->bphit) {
+- if (sis_verbose)
+- (*sim_callback->printf_filtered) (sim_callback,
+- "HW BP hit at %x\n", sregs->pc);
+- return BPT_HIT;
+ }
+ if (ctrl_c) {
+ ctrl_c = 0;
++ sregs->wphit = sregs->bphit = 0;
+ return CTRL_C;
+ }
++ if ((sregs->bphit) || (sregs->wphit))
++ return (BPT_HIT);
+ return TIME_OUT;
+ }
+
+@@ -144,6 +114,7 @@ sim_open (kind, callback, abfd, argv)
+ int freq = 0;
+
+ sim_callback = callback;
++ sis_gdb_break = 1;
+
+ sis_gdb_break = 1;
+ argc = countargv (argv);
+@@ -369,12 +340,15 @@ sim_stop_reason(sd, reason, sigrc)
+ {
+
+ switch (simstat) {
+- case CTRL_C:
++ case CTRL_C:
+ *reason = sim_stopped;
+ *sigrc = GDB_SIGNAL_INT;
+ break;
+ case OK:
+ case TIME_OUT:
++ *reason = sim_stopped;
++ *sigrc = 0;
++ break;
+ case BPT_HIT:
+ *reason = sim_stopped;
+ *sigrc = GDB_SIGNAL_TRAP;
+@@ -383,8 +357,10 @@ sim_stop_reason(sd, reason, sigrc)
+ *sigrc = 0;
+ *reason = sim_exited;
+ }
+- ctrl_c = 0;
+- simstat = OK;
++
++ if (sis_verbose)
++ (*sim_callback->printf_filtered) (sim_callback,
++ "sim_stop_reason %x : %x\n", *reason, *sigrc);
+ }
+
+ /* Flush all register windows out to the stack. Starting after the invalid
+@@ -445,7 +421,25 @@ flush_windows ()
+ void
+ sim_resume(SIM_DESC sd, int step, int siggnal)
+ {
+- simstat = run_sim(&sregs, UINT64_MAX, 0);
++ if (sis_verbose)
++ (*sim_callback->printf_filtered) (sim_callback,
++ "sim_resume %x : %x : %x : %x : 0x%08x\n", step, siggnal, sregs.bphit, sregs.wphit, sregs.pc);
++ if (step) {
++ sregs.bphit = 0;
++ sregs.wphit = 1;
++ simstat = run_sim(&sregs, 1, 0);
++ sregs.bphit = 0;
++ sregs.wphit = 0;
++ } else if (sregs.bphit || sregs.wphit) {
++ sregs.bphit = 0;
++ sregs.wphit = 1;
++ simstat = run_sim(&sregs, 1, 0);
++ sregs.bphit = sregs.wphit = 0;
++ simstat = run_sim(&sregs, UINT64_MAX, 0);
++ sregs.bphit = 0;
++ }
++ else
++ simstat = run_sim(&sregs, UINT64_MAX, 0);
+
+ if (sis_gdb_break) flush_windows ();
+ }
+@@ -471,6 +465,145 @@ sim_stop (SIM_DESC sd)
+ return 1;
+ }
+
++static int
++sis_insert_watchpoint_read(int addr, unsigned char mask)
++{
++ if (sregs.wprnum < WPR_MAX) {
++ sregs.wprs[sregs.wprnum] = addr;
++ sregs.wprm[sregs.wprnum] = mask;
++ sregs.wprnum++;
++ if (sis_verbose)
++ (*sim_callback->printf_filtered) (sim_callback, "inserted read watchpoint at %x\n", addr);
++ return SIM_RC_OK;
++ } else
++ return SIM_RC_FAIL;
++}
++
++static int
++sis_remove_watchpoint_read(int addr)
++{
++ int i = 0;
++
++ while ((i < sregs.wprnum) && (sregs.wprs[i] != addr))
++ i++;
++ if (addr == sregs.wprs[i]) {
++ for (; i < sregs.wprnum - 1; i++)
++ sregs.wprs[i] = sregs.wprs[i + 1];
++ sregs.wprnum -= 1;
++ if (sis_verbose)
++ (*sim_callback->printf_filtered) (sim_callback, "removed read watchpoint at %x\n", addr);
++ return 0;
++ }
++ return 1;
++}
++
++static int
++sis_insert_watchpoint_write(int32 addr, unsigned char mask)
++{
++ if (sregs.wpwnum < WPR_MAX) {
++ sregs.wpws[sregs.wpwnum] = addr;
++ sregs.wpwm[sregs.wpwnum] = mask;
++ sregs.wpwnum++;
++ if (sis_verbose)
++ (*sim_callback->printf_filtered) (sim_callback, "sim_insert_watchpoint_write: 0x%08x : %x\n", addr, mask);
++ return SIM_RC_OK;
++ } else
++ return SIM_RC_FAIL;
++}
++
++static int
++sis_remove_watchpoint_write(int addr)
++{
++ int i = 0;
++
++ while ((i < sregs.wpwnum) && (sregs.wpws[i] != addr))
++ i++;
++ if (addr == sregs.wpws[i]) {
++ for (; i < sregs.wpwnum - 1; i++)
++ sregs.wpws[i] = sregs.wpws[i + 1];
++ sregs.wpwnum -= 1;
++ if (sis_verbose)
++ (*sim_callback->printf_filtered) (sim_callback, "removed write watchpoint at %x\n", addr);
++ return SIM_RC_OK;
++ }
++ return SIM_RC_FAIL;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ if (type == 2) /* bp_hardware_breakpoint not supported */
++ return 0;
++ else
++ return 1;
++}
++
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ int res;
++ unsigned char mask;
++
++ switch (length) {
++ case 1: mask = 0; break;
++ case 2: mask = 1; break;
++ case 4: mask = 3; break;
++ default: mask = 7; break;
++ }
++
++ switch (type) {
++ case 0:
++ res = sis_insert_watchpoint_write (mem, mask);
++ break;
++ case 1:
++ res = sis_insert_watchpoint_read (mem, mask);
++ break;
++ case 2:
++ if ((res = sis_insert_watchpoint_write (mem, mask)) == SIM_RC_OK)
++ res = sis_insert_watchpoint_read (mem, mask);
++ if (res == SIM_RC_FAIL)
++ sis_remove_watchpoint_read (mem);
++ break;
++ default:
++ res = -1;
++ }
++ return (res);
++}
++
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ int res;
++ switch (type) {
++ case 0:
++ res = sis_remove_watchpoint_write (mem);
++ break;
++ case 1:
++ res = sis_remove_watchpoint_read (mem);
++ break;
++ case 2:
++ if ((res = sis_remove_watchpoint_write (mem)) == SIM_RC_OK)
++ res = sis_remove_watchpoint_read (mem);
++ else
++ sis_remove_watchpoint_read (mem);
++ break;
++ default:
++ res = -1;
++ }
++ return (res);
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ if (sis_verbose)
++ (*sim_callback->printf_filtered) (sim_callback, "sim_stopped_by_watchpoint %x\n", sregs.wphit);
++ return((sregs.wphit != 0));
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return(sregs.wpaddress);
++}
++
+ #if 0 /* FIXME: These shouldn't exist. */
+
+ int
+diff --git a/sim/frv/Makefile.in b/sim/frv/Makefile.in
+index eaadd66..7c5ea39 100644
+--- a/sim/frv/Makefile.in
++++ b/sim/frv/Makefile.in
+@@ -21,6 +21,7 @@ FRV_OBJS = frv.o cpu.o decode.o sem.o model.o mloop.o cgen-par.o
+
+ SIM_OBJS = \
+ $(SIM_NEW_COMMON_OBJS) \
++ sim-watch-remote.o \
+ cgen-utils.o cgen-trace.o cgen-scache.o cgen-fpu.o cgen-accfp.o \
+ cgen-run.o \
+ sim-if.o arch.o \
+diff --git a/sim/ft32/Makefile.in b/sim/ft32/Makefile.in
+index ad5d519..ae7d5b0 100644
+--- a/sim/ft32/Makefile.in
++++ b/sim/ft32/Makefile.in
+@@ -21,6 +21,7 @@
+ SIM_OBJS = \
+ $(SIM_NEW_COMMON_OBJS) \
+ interp.o \
++ sim-watch-remote.o \
+ sim-resume.o
+
+ ## COMMON_POST_CONFIG_FRAG
+diff --git a/sim/h8300/Makefile.in b/sim/h8300/Makefile.in
+index dcca158..4c60207 100644
+--- a/sim/h8300/Makefile.in
++++ b/sim/h8300/Makefile.in
+@@ -19,6 +19,7 @@
+
+ SIM_OBJS = compile.o \
+ $(SIM_NEW_COMMON_OBJS) \
++ sim-watch-remote.o \
+ sim-resume.o
+
+ ## COMMON_POST_CONFIG_FRAG
+diff --git a/sim/iq2000/Makefile.in b/sim/iq2000/Makefile.in
+index d674adf..c050b36 100644
+--- a/sim/iq2000/Makefile.in
++++ b/sim/iq2000/Makefile.in
+@@ -21,6 +21,7 @@ IQ2000_OBJS = iq2000.o cpu.o decode.o sem.o model.o mloop.o
+
+ SIM_OBJS = \
+ $(SIM_NEW_COMMON_OBJS) \
++ sim-watch-remote.o \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o \
+ sim-if.o arch.o \
+diff --git a/sim/lm32/Makefile.in b/sim/lm32/Makefile.in
+index 6a71ace..c8d4ebe 100644
+--- a/sim/lm32/Makefile.in
++++ b/sim/lm32/Makefile.in
+@@ -9,6 +9,7 @@ SIM_OBJS = \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o \
+ sim-if.o arch.o \
++ sim-watch-remote.o \
+ cpu.o decode.o sem.o model.o mloop.o \
+ lm32.o traps.o user.o
+
+diff --git a/sim/m32c/gdb-if.c b/sim/m32c/gdb-if.c
+index 46e151b..a933127 100644
+--- a/sim/m32c/gdb-if.c
++++ b/sim/m32c/gdb-if.c
+@@ -712,3 +712,28 @@ sim_info (SIM_DESC sd, int verbose)
+ {
+ printf ("The m32c minisim doesn't collect any statistics.\n");
+ }
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/m32r/Makefile.in b/sim/m32r/Makefile.in
+index 9d0b39f..2b45db1 100644
+--- a/sim/m32r/Makefile.in
++++ b/sim/m32r/Makefile.in
+@@ -29,6 +29,7 @@ SIM_OBJS = \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o \
+ sim-if.o arch.o \
++ sim-watch-remote.o \
+ $(M32R_OBJS) \
+ $(M32RX_OBJS) \
+ $(M32R2_OBJS) \
+diff --git a/sim/m68hc11/Makefile.in b/sim/m68hc11/Makefile.in
+index c4b3ee8..1285bdb 100644
+--- a/sim/m68hc11/Makefile.in
++++ b/sim/m68hc11/Makefile.in
+@@ -22,6 +22,7 @@ M68HC11_OBJS = interp.o m68hc11int.o m68hc12int.o \
+
+ SIM_OBJS = $(M68HC11_OBJS) \
+ $(SIM_NEW_COMMON_OBJS) \
++ sim-watch-remote.o \
+ sim-resume.o
+
+ SIM_PROFILE= -DPROFILE=1 -DWITH_PROFILE=-1
+diff --git a/sim/mcore/interp.c b/sim/mcore/interp.c
+index 4509489..2550ce3 100644
+--- a/sim/mcore/interp.c
++++ b/sim/mcore/interp.c
+@@ -1529,3 +1529,28 @@ sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
+
+ return SIM_RC_OK;
+ }
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/microblaze/Makefile.in b/sim/microblaze/Makefile.in
+index 6c4bf7a..5d45629 100644
+--- a/sim/microblaze/Makefile.in
++++ b/sim/microblaze/Makefile.in
+@@ -20,6 +20,7 @@
+ SIM_OBJS = \
+ interp.o \
+ $(SIM_NEW_COMMON_OBJS) \
++ sim-watch-remote.o \
+ sim-resume.o
+
+ ## COMMON_POST_CONFIG_FRAG
+diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
+index 7f1c916..e6c943b 100644
+--- a/sim/mips/Makefile.in
++++ b/sim/mips/Makefile.in
+@@ -70,7 +70,7 @@ SIM_OBJS = \
+ dsp.o \
+ sim-main.o \
+ sim-resume.o \
+-
++ sim-watch-remote.o
+
+ # List of flags to always pass to $(CC).
+ SIM_SUBTARGET=@SIM_SUBTARGET@
+diff --git a/sim/mn10300/Makefile.in b/sim/mn10300/Makefile.in
+index 6fce876..eeac1a1 100644
+--- a/sim/mn10300/Makefile.in
++++ b/sim/mn10300/Makefile.in
+@@ -21,6 +21,7 @@ MN10300_OBJS = \
+ itable.o semantics.o idecode.o icache.o engine.o irun.o support.o \
+ $(SIM_NEW_COMMON_OBJS) \
+ op_utils.o \
++ sim-watch-remote.o \
+ sim-resume.o
+
+ SIM_OBJS = $(MN10300_OBJS) interp.o
+diff --git a/sim/moxie/interp.c b/sim/moxie/interp.c
+index 6de1aa0..87be968 100644
+--- a/sim/moxie/interp.c
++++ b/sim/moxie/interp.c
+@@ -1323,3 +1323,28 @@ sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
+
+ return SIM_RC_OK;
+ }
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/msp430/Makefile.in b/sim/msp430/Makefile.in
+index 4194690..240787f 100644
+--- a/sim/msp430/Makefile.in
++++ b/sim/msp430/Makefile.in
+@@ -27,6 +27,7 @@
+ SIM_OBJS = \
+ $(SIM_NEW_COMMON_OBJS) \
+ msp430-sim.o \
++ sim-watch-remote.o \
+ sim-resume.o
+
+ # List of extra dependencies.
+diff --git a/sim/ppc/gdb-sim.c b/sim/ppc/gdb-sim.c
+index 952c9b5..deb6987 100644
+--- a/sim/ppc/gdb-sim.c
++++ b/sim/ppc/gdb-sim.c
+@@ -1296,3 +1296,28 @@ sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
+ return psim_write_register(simulator, MAX_NR_PROCESSORS,
+ buf, regname, raw_transfer);
+ }
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/rl78/gdb-if.c b/sim/rl78/gdb-if.c
+index e21fc1d..c1c67b3 100644
+--- a/sim/rl78/gdb-if.c
++++ b/sim/rl78/gdb-if.c
+@@ -603,3 +603,28 @@ sim_complete_command (SIM_DESC sd, const char *text, const char *word)
+ {
+ return NULL;
+ }
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/rx/gdb-if.c b/sim/rx/gdb-if.c
+index eec5325..2afcb42 100644
+--- a/sim/rx/gdb-if.c
++++ b/sim/rx/gdb-if.c
+@@ -854,3 +854,28 @@ sim_complete_command (SIM_DESC sd, const char *text, const char *word)
+ {
+ return NULL;
+ }
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/sh/interp.c b/sim/sh/interp.c
+index df29f96..ac8a200 100644
+--- a/sim/sh/interp.c
++++ b/sim/sh/interp.c
+@@ -2533,3 +2533,28 @@ sim_do_command (SIM_DESC sd, const char *cmd)
+ sim_io_printf (sd, "Error: \"%s\" is not a valid SH simulator command.\n", cmd);
+ }
+ }
++
++int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
++{
++ return -1;
++}
++
++int sim_stopped_by_watchpoint (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_watchpoint_address (SIM_DESC sd)
++{
++ return 0;
++}
++
++int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
++{
++ return 0;
++}
+diff --git a/sim/sh64/Makefile.in b/sim/sh64/Makefile.in
+index e9a13d9..c21a0c8 100644
+--- a/sim/sh64/Makefile.in
++++ b/sim/sh64/Makefile.in
+@@ -26,6 +26,7 @@ SIM_OBJS = \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o \
+ sim-if.o arch.o \
++ sim-watch-remote.o \
+ $(SH64_OBJS)
+
+ # Extra headers included by sim-main.h.
+diff --git a/sim/v850/Makefile.in b/sim/v850/Makefile.in
+index 00e560e..2e4cac6 100644
+--- a/sim/v850/Makefile.in
++++ b/sim/v850/Makefile.in
+@@ -23,6 +23,7 @@ SIM_OBJS = \
+ $(SIM_NEW_COMMON_OBJS) \
+ simops.o interp.o \
+ itable.o semantics.o idecode.o icache.o engine.o irun.o support.o \
++ sim-watch-remote.o \
+ sim-resume.o
+
+ # List of extra dependencies.
+--
+2.7.4
+
+From 3e95fa7e9dd8b2306e5fb936656c66142bba25ca Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri at gaisler.se>
+Date: Sun, 5 Jun 2016 23:22:31 +0200
+Subject: [PATCH 9/9] sim/erc32: Added back original run.c
+
+ * New file run.c
+ * New file run-sim.h
+---
+ sim/erc32/Makefile.in | 3 +-
+ sim/erc32/run-sim.h | 93 +++++++++++++
+ sim/erc32/run.c | 354 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 448 insertions(+), 2 deletions(-)
+ create mode 100644 sim/erc32/run-sim.h
+ create mode 100644 sim/erc32/run.c
+
+diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
+index 4fc54ca..7afeea6 100644
+--- a/sim/erc32/Makefile.in
++++ b/sim/erc32/Makefile.in
+@@ -25,7 +25,7 @@ READLINE_LIB = @READLINE@
+ SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o leon2.o
+
+ SIM_OBJS = $(SIS_OFILES) interf.o
+-SIM_RUN_OBJS = sis.o
++SIM_RUN_OBJS = run.o
+ SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
+ SIM_EXTRA_ALL = sis
+ SIM_EXTRA_INSTALL = install-sis
+@@ -56,4 +56,3 @@ configure:
+ srcdir=. ; export srcdir ; \
+ else true ; fi ; \
+ (cd $${srcdir}; autoconf --localdir=../common)
+-
+diff --git a/sim/erc32/run-sim.h b/sim/erc32/run-sim.h
+new file mode 100644
+index 0000000..8793472
+--- /dev/null
++++ b/sim/erc32/run-sim.h
+@@ -0,0 +1,93 @@
++/* This file defines the part of the interface between the standalone
++ simaulator program - run - and simulator library - libsim.a - that
++ is not used by GDB. The GDB part is described in include/remote-sim.h.
++
++ Copyright 2002-2015 Free Software Foundation, Inc.
++
++ This file is part of GDB.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>. */
++
++#ifndef RUN_SIM_H
++#define RUN_SIM_H
++
++#ifdef SIM_TARGET_SWITCHES
++ /* Parse the command line, extracting any target specific switches
++ before the generic simulator code gets a chance to complain
++ about them. Returns the adjusted value of argc. */
++int sim_target_parse_command_line (int, char **);
++
++ /* Display a list of target specific switches supported by this
++ target. */
++void sim_target_display_usage (int help);
++
++#endif
++
++/* Provide simulator with a default (global) host_callback_struct.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure does not take a SIM_DESC argument as it is
++ used before sim_open. */
++
++void sim_set_callbacks (struct host_callback_struct *);
++
++
++/* Set the size of the simulator memory array.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure does not take a SIM_DESC argument as it is
++ used before sim_open. */
++
++void sim_size (int i);
++
++
++/* Single-step simulator with tracing enabled.
++ THIS PROCEDURE IS DEPRECATED.
++ THIS PROCEDURE IS EVEN MORE DEPRECATED THAN SIM_SET_TRACE
++ GDB and NRUN do not use this interface.
++ This procedure returns: ``0'' indicating that the simulator should
++ be continued using sim_trace() calls; ``1'' indicating that the
++ simulation has finished. */
++
++int sim_trace (SIM_DESC sd);
++
++
++/* Enable tracing.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure returns: ``0'' indicating that the simulator should
++ be continued using sim_trace() calls; ``1'' indicating that the
++ simulation has finished. */
++
++void sim_set_trace (void);
++
++
++/* Configure the size of the profile buffer.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure does not take a SIM_DESC argument as it is
++ used before sim_open. */
++
++void sim_set_profile_size (int n);
++
++
++/* Kill the running program.
++ THIS PROCEDURE IS DEPRECATED.
++ GDB and NRUN do not use this interface.
++ This procedure will be replaced as part of the introduction of
++ multi-cpu simulators. */
++
++void sim_kill (SIM_DESC sd);
++
++#endif
+diff --git a/sim/erc32/run.c b/sim/erc32/run.c
+new file mode 100644
+index 0000000..70ae411
+--- /dev/null
++++ b/sim/erc32/run.c
+@@ -0,0 +1,354 @@
++/* run front end support for all the simulators.
++ Copyright (C) 1992-2015 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 3 of the License, or
++(at your option) any later version.
++
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with this program. If not, see <http://www.gnu.org/licenses/>. */
++
++/* Steve Chamberlain sac at cygnus.com,
++ and others at Cygnus. */
++
++#include "config.h"
++
++#include <signal.h>
++#include <stdio.h>
++#ifdef __STDC__
++#include <stdarg.h>
++#else
++#include <varargs.h>
++#endif
++
++#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
++
++#include "libiberty.h"
++#include "bfd.h"
++#include "gdb/callback.h"
++#include "gdb/remote-sim.h"
++#include "ansidecl.h"
++#include "run-sim.h"
++#include "version.h"
++
++static void usage (int help);
++static void print_version (void);
++extern int optind;
++extern char *optarg;
++
++extern host_callback default_callback;
++
++static char *myname;
++
++extern int getopt ();
++
++#ifdef NEED_UI_LOOP_HOOK
++/* Gdb foolery. This is only needed for gdb using a gui. */
++int (*deprecated_ui_loop_hook) (int signo);
++#endif
++
++static SIM_DESC sd;
++
++static RETSIGTYPE
++cntrl_c (int sig ATTRIBUTE_UNUSED)
++{
++ if (! sim_stop (sd))
++ {
++ fprintf (stderr, "Quit!\n");
++ exit (1);
++ }
++}
++
++int
++main (ac, av)
++ int ac;
++ char **av;
++{
++ RETSIGTYPE (*prev_sigint) ();
++ bfd *abfd;
++ int i;
++ int verbose = 0;
++ int trace = 0;
++#ifdef SIM_HAVE_ENVIRONMENT
++ int operating_p = 0;
++#endif
++ char *name;
++ static char *no_args[4];
++ char **sim_argv = &no_args[0];
++ char **prog_args;
++ enum sim_stop reason;
++ int sigrc;
++
++ myname = av[0] + strlen (av[0]);
++ while (myname > av[0] && myname[-1] != '/')
++ --myname;
++
++ /* The first element of sim_open's argv is the program name. */
++ no_args[0] = av[0];
++#ifdef SIM_HAVE_BIENDIAN
++ no_args[1] = "-E";
++ no_args[2] = "set-later";
++#endif
++
++ /* FIXME: This is currently being migrated into sim_open.
++ Simulators that use functions such as sim_size() still require
++ this. */
++ default_callback.init (&default_callback);
++ //sim_set_callbacks (&default_callback);
++
++#ifdef SIM_TARGET_SWITCHES
++ ac = sim_target_parse_command_line (ac, av);
++#endif
++
++ for (i = 1; av[i]; ++i)
++ {
++ if (strcmp (av[i], "--help") == 0)
++ {
++ usage (1);
++ }
++ else if (strcmp (av[i], "--version") == 0)
++ {
++ print_version ();
++ return 0;
++ }
++ }
++
++ /* FIXME: This is currently being rewritten to have each simulator
++ do all argv processing. */
++
++ while ((i = getopt (ac, av, "a:c:m:op:s:tv")) != EOF)
++ switch (i)
++ {
++ case 'a':
++ /* FIXME: Temporary hack. */
++ {
++ int len = strlen (av[0]) + strlen (optarg);
++ char *argbuf = (char *) alloca (len + 2 + 50);
++ sprintf (argbuf, "%s %s", av[0], optarg);
++#ifdef SIM_HAVE_BIENDIAN
++ /* The desired endianness must be passed to sim_open.
++ The value for "set-later" is set when we know what it is.
++ -E support isn't yet part of the published interface. */
++ strcat (argbuf, " -E set-later");
++#endif
++ sim_argv = buildargv (argbuf);
++ }
++ break;
++#ifdef SIM_HAVE_SIMCACHE
++ case 'c':
++ sim_set_simcache_size (atoi (optarg));
++ break;
++#endif
++ case 'm':
++ /* FIXME: Rename to sim_set_mem_size. */
++ //sim_size (atoi (optarg));
++ break;
++#ifdef SIM_HAVE_ENVIRONMENT
++ case 'o':
++ /* Operating enironment where any signals are delivered to the
++ target. */
++ operating_p = 1;
++ break;
++#endif
++#ifdef SIM_HAVE_PROFILE
++ case 'p':
++ sim_set_profile (atoi (optarg));
++ break;
++ case 's':
++ sim_set_profile_size (atoi (optarg));
++ break;
++#endif
++ case 't':
++ trace = 1;
++ break;
++ case 'v':
++ /* Things that are printed with -v are the kinds of things that
++ gcc -v prints. This is not meant to include detailed tracing
++ or debugging information, just summaries. */
++ verbose = 1;
++ /* sim_set_verbose (1); */
++ break;
++ /* FIXME: Quick hack, to be replaced by more general facility. */
++ default:
++ usage (0);
++ }
++
++ ac -= optind;
++ av += optind;
++ if (ac <= 0)
++ usage (0);
++
++ name = *av;
++ prog_args = av;
++
++ if (verbose)
++ {
++ printf ("%s %s\n", myname, name);
++ }
++
++ abfd = bfd_openr (name, 0);
++ if (!abfd)
++ {
++ fprintf (stderr, "%s: can't open %s: %s\n",
++ myname, name, bfd_errmsg (bfd_get_error ()));
++ exit (1);
++ }
++
++ if (!bfd_check_format (abfd, bfd_object))
++ {
++ fprintf (stderr, "%s: can't load %s: %s\n",
++ myname, name, bfd_errmsg (bfd_get_error ()));
++ exit (1);
++ }
++
++#ifdef SIM_HAVE_BIENDIAN
++ /* The endianness must be passed to sim_open because one may wish to
++ examine/set registers before calling sim_load [which is the other
++ place where one can determine endianness]. We previously passed the
++ endianness via global `target_byte_order' but that's not a clean
++ interface. */
++ for (i = 1; sim_argv[i + 1] != NULL; ++i)
++ continue;
++ if (bfd_big_endian (abfd))
++ sim_argv[i] = "big";
++ else
++ sim_argv[i] = "little";
++#endif
++
++ /* Ensure that any run-time initialisation that needs to be
++ performed by the simulator can occur. */
++ sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, abfd, sim_argv);
++ if (sd == 0)
++ exit (1);
++
++ if (sim_load (sd, name, abfd, 0) == SIM_RC_FAIL)
++ exit (1);
++
++ if (sim_create_inferior (sd, abfd, prog_args, NULL) == SIM_RC_FAIL)
++ exit (1);
++
++#ifdef SIM_HAVE_ENVIRONMENT
++ /* NOTE: An old simulator supporting the operating environment MUST
++ provide sim_set_trace() and not sim_trace(). That way
++ sim_stop_reason() can be used to determine any stop reason. */
++ if (trace)
++ sim_set_trace ();
++ sigrc = 0;
++ do
++ {
++ prev_sigint = signal (SIGINT, cntrl_c);
++ sim_resume (sd, 0, sigrc);
++ signal (SIGINT, prev_sigint);
++ sim_stop_reason (sd, &reason, &sigrc);
++ }
++ while (operating_p && reason == sim_stopped && sigrc != SIGINT);
++#else
++ if (trace)
++ {
++ int done = 0;
++ prev_sigint = signal (SIGINT, cntrl_c);
++ while (!done)
++ {
++ // done = sim_trace (sd);
++ }
++ signal (SIGINT, prev_sigint);
++ sim_stop_reason (sd, &reason, &sigrc);
++ }
++ else
++ {
++ prev_sigint = signal (SIGINT, cntrl_c);
++ sigrc = 0;
++ sim_resume (sd, 0, sigrc);
++ signal (SIGINT, prev_sigint);
++ sim_stop_reason (sd, &reason, &sigrc);
++ }
++#endif
++
++ if (verbose)
++ sim_info (sd, 0);
++ sim_close (sd, 0);
++
++ /* If reason is sim_exited, then sigrc holds the exit code which we want
++ to return. If reason is sim_stopped or sim_signalled, then sigrc holds
++ the signal that the simulator received; we want to return that to
++ indicate failure. */
++
++ /* Why did we stop? */
++ switch (reason)
++ {
++ case sim_signalled:
++ case sim_stopped:
++ if (sigrc != 0)
++ fprintf (stderr, "program stopped with signal %d.\n", sigrc);
++ break;
++
++ case sim_exited:
++ break;
++
++ case sim_running:
++ case sim_polling: /* These indicate a serious problem. */
++ abort ();
++ break;
++
++ }
++
++ return sigrc;
++}
++
++static void
++usage (int help)
++{
++ FILE *stream = help ? stdout : stderr;
++
++ fprintf (stream, "Usage: %s [options] program [program args]\n", myname);
++ fprintf (stream, "Options:\n");
++ fprintf (stream, "-a args Pass `args' to simulator.\n");
++#ifdef SIM_HAVE_SIMCACHE
++ fprintf (stream, "-c size Set simulator cache size to `size'.\n");
++#endif
++ fprintf (stream, "-m size Set memory size of simulator, in bytes.\n");
++#ifdef SIM_HAVE_ENVIRONMENT
++ fprintf (stream, "-o Select operating (kernel) environment.\n");
++#endif
++#ifdef SIM_HAVE_PROFILE
++ fprintf (stream, "-p freq Set profiling frequency.\n");
++ fprintf (stream, "-s size Set profiling size.\n");
++#endif
++ fprintf (stream, "-t Perform instruction tracing.\n");
++ fprintf (stream, " Note: Very few simulators support tracing.\n");
++ fprintf (stream, "-v Verbose output.\n");
++ fprintf (stream, "\n");
++ fprintf (stream, "program args Arguments to pass to simulated program.\n");
++ fprintf (stream, " Note: Very few simulators support this.\n");
++#ifdef SIM_TARGET_SWITCHES
++ fprintf (stream, "\nTarget specific options:\n");
++ sim_target_display_usage (help);
++#endif
++
++ if (help && REPORT_BUGS_TO[0])
++ printf ("Report bugs to %s\n", REPORT_BUGS_TO);
++
++ exit (help ? 0 : 1);
++}
++
++static void
++print_version ()
++{
++ printf ("GNU simulator %s%s\n", PKGVERSION, version);
++}
+--
+2.7.4
+
diff --git a/tools/5/gdb/patch-gdb-python-python-config.py b/tools/5/gdb/patch-gdb-python-python-config.py
new file mode 100644
index 0000000..2433240
--- /dev/null
+++ b/tools/5/gdb/patch-gdb-python-python-config.py
@@ -0,0 +1,11 @@
+--- gdb/python/python-config.py.orig 2013-10-17 11:24:52.000000000 +0200
++++ gdb/python/python-config.py 2013-10-17 11:25:04.000000000 +0200
+@@ -59,6 +59,8 @@
+
+ elif opt in ('--libs', '--ldflags'):
+ libs = []
++ if getvar('LDFLAGS') is not None:
++ libs.extend(getvar('LDFLAGS').split())
+ if getvar('LIBS') is not None:
+ libs.extend(getvar('LIBS').split())
+ if getvar('SYSLIBS') is not None:
More information about the vc
mailing list