summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@oarcorp.com>2015-03-26 13:20:45 -0500
committerJoel Sherrill <joel.sherrill@oarcorp.com>2015-03-27 08:32:47 -0500
commitbfd2b7d8f4b966d65e681f9b81749c10a8d83a47 (patch)
tree877146eab084b0ab4edf7b7e35dacf7bc98b5e50 /tools
parentd499e6df8977c1da66504a7e4120814ee2dfe3d3 (diff)
Add Jiri Gaisler SIS patch set for gdb 7.9
This patch set adds a lot of new capability including support for the leon2 and leon3. It also eliminates the difference between the initial state of the simulated erc32 and the real hardware.
Diffstat (limited to 'tools')
-rw-r--r--tools/4.11/gdb/sparc/7.9/0001-sim-erc32-Disassembly-in-stand-alone-mode-did-not-wo.patch61
-rw-r--r--tools/4.11/gdb/sparc/7.9/0002-sim-erc32-Corrected-wrong-CPU-implementation-and-ver.patch27
-rw-r--r--tools/4.11/gdb/sparc/7.9/0003-sim-erc32-Perform-pseudo-init-if-binary-linked-to-no.patch89
-rw-r--r--tools/4.11/gdb/sparc/7.9/0004-sim-erc32-Use-fenv.h-for-host-FPU-access.patch241
-rw-r--r--tools/4.11/gdb/sparc/7.9/0005-sim-erc32-Remove-unused-defines-in-Makefile-and-swit.patch27
-rw-r--r--tools/4.11/gdb/sparc/7.9/0006-sim-erc32-Fix-incorrect-simulator-performance-report.patch174
-rw-r--r--tools/4.11/gdb/sparc/7.9/0007-sim-erc32-File-loading-via-command-line-did-not-work.patch43
-rw-r--r--tools/4.11/gdb/sparc/7.9/0008-sim-erc32-Added-v-command-line-switch-for-verbose-ou.patch123
-rw-r--r--tools/4.11/gdb/sparc/7.9/0009-sim-erc32-Removed-type-mismatch-compiler-warnings.patch66
-rw-r--r--tools/4.11/gdb/sparc/7.9/0010-sim-erc32-Switched-emulated-memory-to-host-endian-or.patch564
-rw-r--r--tools/4.11/gdb/sparc/7.9/0011-sim-erc32-use-SIM_AC_OPTION_HOSTENDIAN-to-probe-for-.patch564
-rw-r--r--tools/4.11/gdb/sparc/7.9/0012-sim-erc32-Use-memory_iread-function-for-instruction-.patch119
-rw-r--r--tools/4.11/gdb/sparc/7.9/0013-sim-erc32-Fix-a-few-compiler-warnings.patch72
-rw-r--r--tools/4.11/gdb/sparc/7.9/0014-sim-erc32-Use-gdb-callback-for-UART-I-O-when-linked-.patch358
-rw-r--r--tools/4.11/gdb/sparc/7.9/0015-sim-erc32-Access-memory-subsystem-through-struct-mem.patch804
-rw-r--r--tools/4.11/gdb/sparc/7.9/0016-sim-erc32-Use-readline.h-for-readline-types-and-func.patch55
-rw-r--r--tools/4.11/gdb/sparc/7.9/0017-sim-erc32-Move-local-extern-declarations-into-sis.h.patch224
-rw-r--r--tools/4.11/gdb/sparc/7.9/0018-sim-erc32-Add-support-for-LEON3-processor-emulation.patch2434
-rw-r--r--tools/4.11/gdb/sparc/7.9/0019-sim-erc32-Add-support-for-LEON2-processor-emulation.patch1188
-rw-r--r--tools/4.11/gdb/sparc/7.9/0020-sim-erc32-Updated-documentation.patch516
-rw-r--r--tools/4.11/gdb/sparc/7.9/0021-sim-erc32-Add-data-watchpoint-support.patch377
-rw-r--r--tools/4.11/gdb/sparc/7.9/0022-Add-watchpoint-support-to-gdb-simulator-interface.patch1025
-rw-r--r--tools/4.11/gdb/sparc/7.9/0023-sim-erc32-ELF-loading-could-fail-on-unaligned-sectio.patch39
23 files changed, 9190 insertions, 0 deletions
diff --git a/tools/4.11/gdb/sparc/7.9/0001-sim-erc32-Disassembly-in-stand-alone-mode-did-not-wo.patch b/tools/4.11/gdb/sparc/7.9/0001-sim-erc32-Disassembly-in-stand-alone-mode-did-not-wo.patch
new file mode 100644
index 0000000..e48ff75
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0001-sim-erc32-Disassembly-in-stand-alone-mode-did-not-wo.patch
@@ -0,0 +1,61 @@
+From 723f3af6060ee39c89f2b79954a39c7bdee39f99 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 22:40:25 +0200
+Subject: [PATCH 01/23] sim/erc32: Disassembly in stand-alone mode did not
+ work.
+
+ The API to print_insn_sparc() has changed over the years ...
+
+ * func.c (print_insn_sparc_sis) Add helper function for disassembly.
+ (disp_ctrl) Use helper function.
+---
+ sim/erc32/func.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index d001c58..e6744ee 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -759,6 +759,17 @@ disp_regs(sregs,cwp)
+ }
+ }
+
++static void print_insn_sparc_sis(uint32 addr, struct disassemble_info *info)
++{
++ unsigned char i[4];
++
++ sis_memory_read(addr, i, 4);
++ dinfo.buffer_vma = addr;
++ dinfo.buffer_length = 4;
++ dinfo.buffer = i;
++ print_insn_sparc(addr, info);
++}
++
+ static void
+ disp_ctrl(sregs)
+ struct pstate *sregs;
+@@ -770,10 +781,10 @@ disp_ctrl(sregs)
+ sregs->psr, sregs->wim, sregs->tbr, sregs->y);
+ sis_memory_read(sregs->pc, i, 4);
+ printf("\n pc: %08X = %02X%02X%02X%02X ", sregs->pc,i[0],i[1],i[2],i[3]);
+- print_insn_sparc(sregs->pc, &dinfo);
++ print_insn_sparc_sis(sregs->pc, &dinfo);
+ sis_memory_read(sregs->npc, i, 4);
+ printf("\n npc: %08X = %02X%02X%02X%02X ",sregs->npc,i[0],i[1],i[2],i[3]);
+- print_insn_sparc(sregs->npc, &dinfo);
++ print_insn_sparc_sis(sregs->npc, &dinfo);
+ if (sregs->err_mode)
+ printf("\n IU in error mode");
+ printf("\n\n");
+@@ -821,7 +832,7 @@ dis_mem(addr, len, info)
+ for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) {
+ sis_memory_read(i, data, 4);
+ printf(" %08x %02x%02x%02x%02x ", i, data[0],data[1],data[2],data[3]);
+- print_insn_sparc(i, info);
++ print_insn_sparc_sis(i, info);
+ if (i >= 0xfffffffc) break;
+ printf("\n");
+ }
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0002-sim-erc32-Corrected-wrong-CPU-implementation-and-ver.patch b/tools/4.11/gdb/sparc/7.9/0002-sim-erc32-Corrected-wrong-CPU-implementation-and-ver.patch
new file mode 100644
index 0000000..9a93323
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0002-sim-erc32-Corrected-wrong-CPU-implementation-and-ver.patch
@@ -0,0 +1,27 @@
+From 7a40f4ae5b9e3a9078d445976c3557fae69c60e5 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 22:52:37 +0200
+Subject: [PATCH 02/23] sim/erc32: Corrected wrong CPU implementation and
+ version ID in psr
+
+ * exec.c (init_regs) erc32 has vendor ID 1 and version ID 1 in %psr
+---
+ sim/erc32/exec.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index dc86ba3..07f3586 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -2011,7 +2011,7 @@ init_regs(sregs)
+ sregs->npc = 4;
+ sregs->trap = 0;
+ sregs->psr &= 0x00f03fdf;
+- sregs->psr |= 0x080; /* Set supervisor bit */
++ sregs->psr |= 0x11000080; /* Set supervisor bit */
+ sregs->breakpoint = 0;
+ sregs->annul = 0;
+ sregs->fpstate = FP_EXE_MODE;
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0003-sim-erc32-Perform-pseudo-init-if-binary-linked-to-no.patch b/tools/4.11/gdb/sparc/7.9/0003-sim-erc32-Perform-pseudo-init-if-binary-linked-to-no.patch
new file mode 100644
index 0000000..dca67f4
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0003-sim-erc32-Perform-pseudo-init-if-binary-linked-to-no.patch
@@ -0,0 +1,89 @@
+From 78a59b9928b59065cbffca153db9620c0ff80036 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 22:53:56 +0200
+Subject: [PATCH 03/23] sim/erc32: Perform pseudo-init if binary linked to
+ non-zero address.
+
+Binaries produced by most erc32 tool-chains do not include
+system initialization. sis will detect this and initialize
+necessary registers for memory and timer control.
+
+ * erc32.c (mec_read) allow simulator memory size to be read
+ by application. (boot_init) initialize memory and timers if
+ start address is not 0.
+
+ * erc32,c (exe_cmd) call boot_init if start address not 0
+ * interf.c (run_sim) Likewise
+---
+ sim/erc32/erc32.c | 24 ++++++++++++++++++++++++
+ sim/erc32/func.c | 2 ++
+ sim/erc32/interf.c | 1 +
+ 3 files changed, 27 insertions(+)
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index 4d4177e..0f3e870 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -743,6 +743,14 @@ mec_read(addr, asi, data)
+ *data = read_uart(addr);
+ break;
+
++ case 0xF4: /* simulator RAM size in bytes */
++ *data = 4096*1024;
++ break;
++
++ case 0xF8: /* simulator ROM size in bytes */
++ *data = 1024*1024;
++ break;
++
+ default:
+ set_sfsr(MEC_ACC, addr, asi, 1);
+ return (1);
+@@ -1887,3 +1895,19 @@ sis_memory_read(addr, data, length)
+ memcpy(data, mem, length);
+ return (length);
+ }
++
++extern struct pstate sregs;
++
++void
++boot_init (void)
++{
++ mec_write(MEC_WCR, 0); /* zero waitstates */
++ mec_write(MEC_TRAPD, 0); /* turn off watch-dog */
++ mec_write(MEC_RTC_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
++ mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
++ sregs.wim = 2;
++ sregs.psr = 0x110010e0;
++ sregs.r[30] = RAM_END;
++ sregs.r[14] = sregs.r[30] - 96*4;
++ mec_mcr |= 1; /* power-down enabled */
++}
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index e6744ee..6526085 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -468,6 +468,8 @@ exec_cmd(sregs, cmd)
+ }
+ sregs->pc = len & ~3;
+ sregs->npc = sregs->pc + 4;
++ if ((sregs->pc != 0) && (ebase.simtime == 0))
++ 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);
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 63b3f38..9ac455f 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -78,6 +78,7 @@ run_sim(sregs, icount, dis)
+ init_stdio();
+ sregs->starttime = time(NULL);
+ irq = 0;
++ if ((sregs->pc != 0) && (ebase.simtime == 0)) boot_init();
+ while (!sregs->err_mode & (icount > 0)) {
+
+ sregs->fhold = 0;
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0004-sim-erc32-Use-fenv.h-for-host-FPU-access.patch b/tools/4.11/gdb/sparc/7.9/0004-sim-erc32-Use-fenv.h-for-host-FPU-access.patch
new file mode 100644
index 0000000..2ca90f6
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0004-sim-erc32-Use-fenv.h-for-host-FPU-access.patch
@@ -0,0 +1,241 @@
+From 7002592cb4072303c6a286e1c6479df99ae151b3 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Thu, 19 Feb 2015 22:14:36 +0100
+Subject: [PATCH 04/23] sim/erc32: Use fenv.h for host FPU access
+
+ * float.c (get_accex, clear_accex, set_fsr) Use functions from fenv.h
+ instead of custom assembly.
+---
+ sim/erc32/float.c | 191 +++++++++---------------------------------------------
+ 1 file changed, 30 insertions(+), 161 deletions(-)
+
+diff --git a/sim/erc32/float.c b/sim/erc32/float.c
+index 598b7cc..40c133b 100644
+--- a/sim/erc32/float.c
++++ b/sim/erc32/float.c
+@@ -28,53 +28,38 @@
+ * 4. Clear host exception bits
+ *
+ *
+- * This can also be done using ieee_flags() library routine on sun.
+ */
+
+ #include "config.h"
+ #include "sis.h"
++#include <fenv.h>
+
+-/* Forward declarations */
+-
+-extern uint32 _get_sw (void);
+-extern uint32 _get_cw (void);
+-static void __setfpucw (unsigned short fpu_control);
+-
+-/* This host dependent routine should return the accrued exceptions */
++/* This routine should return the accrued exceptions */
+ int
+ get_accex()
+ {
+-#ifdef sparc
+- return ((_get_fsr_raw() >> 5) & 0x1F);
+-#elif i386
+- uint32 accx;
+-
+- accx = _get_sw() & 0x3f;
+- accx = ((accx & 1) << 4) | ((accx & 2) >> 1) | ((accx & 4) >> 1) |
+- (accx & 8) | ((accx & 16) >> 2) | ((accx & 32) >> 5);
++ int fexc, accx;
++
++ fexc = fetestexcept(FE_ALL_EXCEPT);
++ accx = 0;
++ if (fexc & FE_INEXACT)
++ accx |= 1;
++ if (fexc & FE_DIVBYZERO)
++ accx |= 2;
++ if (fexc & FE_UNDERFLOW)
++ accx |= 4;
++ if (fexc & FE_OVERFLOW)
++ accx |= 8;
++ if (fexc & FE_INVALID)
++ accx |= 0x10;
+ return(accx);
+-#else
+- return(0);
+-#warning no fpu trap support for this target
+-#endif
+-
+ }
+
+ /* How to clear the accrued exceptions */
+ void
+ clear_accex()
+ {
+-#ifdef sparc
+- set_fsr((_get_fsr_raw() & ~0x3e0));
+-#elif i386
+- asm("\n"
+-".text\n"
+-" fnclex\n"
+-"\n"
+-" ");
+-#else
+-#warning no fpu trap support for this target
+-#endif
++ feclearexcept(FE_ALL_EXCEPT);
+ }
+
+ /* How to map SPARC FSR onto the host */
+@@ -82,138 +67,22 @@ void
+ set_fsr(fsr)
+ uint32 fsr;
+ {
+-#ifdef sparc
+- _set_fsr_raw(fsr & ~0x0f800000);
+-#elif i386
+- void __setfpucw(unsigned short fpu_control);
+- uint32 rawfsr;
++ int fround;
+
+- fsr >>= 30;
+- switch (fsr) {
++ fsr >>= 30;
++ switch (fsr) {
+ case 0:
+- case 2:
+- break;
+-
++ fround = FE_TONEAREST;
++ break;
+ case 1:
+- fsr = 3;
+- break;
+-
++ fround = FE_TOWARDZERO;
++ break;
++ case 2:
++ fround = FE_UPWARD;
++ break;
+ case 3:
+- fsr = 1;
+- break;
++ fround = FE_DOWNWARD;
++ break;
+ }
+- rawfsr = _get_cw();
+- rawfsr |= (fsr << 10) | 0x3ff;
+- __setfpucw(rawfsr);
+-#else
+-#warning no fpu trap support for this target
+-#endif
+-}
+-
+-
+-/* Host dependent support functions */
+-
+-#ifdef sparc
+-
+- asm("\n"
+-"\n"
+-".text\n"
+-" .align 4\n"
+-" .global __set_fsr_raw,_set_fsr_raw\n"
+-"__set_fsr_raw:\n"
+-"_set_fsr_raw:\n"
+-" save %sp,-104,%sp\n"
+-" st %i0,[%fp+68]\n"
+-" ld [%fp+68], %fsr\n"
+-" mov 0,%i0\n"
+-" ret\n"
+-" restore\n"
+-"\n"
+-" .align 4\n"
+-" .global __get_fsr_raw\n"
+-" .global _get_fsr_raw\n"
+-"__get_fsr_raw:\n"
+-"_get_fsr_raw:\n"
+-" save %sp,-104,%sp\n"
+-" st %fsr,[%fp+68]\n"
+-" ld [%fp+68], %i0\n"
+-" ret\n"
+-" restore\n"
+-"\n"
+-" ");
+-
+-#elif i386
+-
+- asm("\n"
+-"\n"
+-".text\n"
+-" .align 8\n"
+-".globl _get_sw,__get_sw\n"
+-"__get_sw:\n"
+-"_get_sw:\n"
+-" pushl %ebp\n"
+-" movl %esp,%ebp\n"
+-" movl $0,%eax\n"
+-" fnstsw %ax\n"
+-" movl %ebp,%esp\n"
+-" popl %ebp\n"
+-" ret\n"
+-"\n"
+-" .align 8\n"
+-".globl _get_cw,__get_cw\n"
+-"__get_cw:\n"
+-"_get_cw:\n"
+-" pushl %ebp\n"
+-" movl %esp,%ebp\n"
+-" subw $2,%esp\n"
+-" fnstcw -2(%ebp)\n"
+-" movw -2(%ebp),%eax\n"
+-" movl %ebp,%esp\n"
+-" popl %ebp\n"
+-" ret\n"
+-"\n"
+-"\n"
+-" ");
+-
+-
+-#else
+-#warning no fpu trap support for this target
+-#endif
+-
+-#if i386
+-/* #if defined _WIN32 || defined __GO32__ */
+-/* This is so floating exception handling works on NT
+- These definitions are from the linux fpu_control.h, which
+- doesn't exist on NT.
+-
+- default to:
+- - extended precision
+- - rounding to nearest
+- - exceptions on overflow, zero divide and NaN
+-*/
+-#define _FPU_DEFAULT 0x1372
+-#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */
+-
+-static void
+-__setfpucw(unsigned short fpu_control)
+-{
+- volatile unsigned short cw;
+-
+- /* If user supplied _fpu_control, use it ! */
+- if (!fpu_control)
+- {
+- /* use defaults */
+- fpu_control = _FPU_DEFAULT;
+- }
+- /* Get Control Word */
+- __asm__ volatile ("fnstcw %0" : "=m" (cw) : );
+-
+- /* mask in */
+- cw &= _FPU_RESERVED;
+- cw = cw | (fpu_control & ~_FPU_RESERVED);
+-
+- /* set cw */
+- __asm__ volatile ("fldcw %0" :: "m" (cw));
++ fesetround(fround);
+ }
+-/* #endif */
+-#endif
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0005-sim-erc32-Remove-unused-defines-in-Makefile-and-swit.patch b/tools/4.11/gdb/sparc/7.9/0005-sim-erc32-Remove-unused-defines-in-Makefile-and-swit.patch
new file mode 100644
index 0000000..94e71b0
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0005-sim-erc32-Remove-unused-defines-in-Makefile-and-swit.patch
@@ -0,0 +1,27 @@
+From 03166e64ac4eb1b6b89e80dd5a54d7193ffd9099 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 22:58:33 +0200
+Subject: [PATCH 05/23] sim/erc32: Remove unused defines in Makefile and switch
+ off statistics
+
+ * Makefile.in Remove unused defines
+---
+ sim/erc32/Makefile.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
+index 9c166ce..418e7e4 100644
+--- a/sim/erc32/Makefile.in
++++ b/sim/erc32/Makefile.in
+@@ -30,7 +30,7 @@ SIM_EXTRA_CLEAN = clean-sis
+ # UARTS run at about 115200 baud (simulator time). Add -DFAST_UART to
+ # CFLAGS if faster (infinite) UART speed is desired. Might affect the
+ # behaviour of UART interrupt routines ...
+-SIM_EXTRA_CFLAGS = -DSTAT -DFAST_UART -DIUREV0 -DMECREV0
++SIM_EXTRA_CFLAGS = -DFAST_UART
+
+ ## COMMON_POST_CONFIG_FRAG
+
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0006-sim-erc32-Fix-incorrect-simulator-performance-report.patch b/tools/4.11/gdb/sparc/7.9/0006-sim-erc32-Fix-incorrect-simulator-performance-report.patch
new file mode 100644
index 0000000..4244172
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0006-sim-erc32-Fix-incorrect-simulator-performance-report.patch
@@ -0,0 +1,174 @@
+From 623a6089a6202cc9fb40c0a7235fb7398ea3dfbe Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 23:00:05 +0200
+Subject: [PATCH 06/23] sim/erc32: Fix incorrect simulator performance report
+
+ * func.c (reset_stat, show_stat) switch to double in time keeping
+ (get_time) new function to get system time
+ * sis.h Likewise
+ * interf.c (run_sim) use get_time() for system time
+ * sis.c (run_sim) Likewise
+---
+ sim/erc32/func.c | 35 ++++++++++++++++++++++++++---------
+ sim/erc32/interf.c | 5 ++---
+ sim/erc32/sis.c | 5 ++---
+ sim/erc32/sis.h | 5 +++--
+ 4 files changed, 33 insertions(+), 17 deletions(-)
+
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index 6526085..06c00b4 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -613,7 +613,7 @@ void
+ reset_stat(sregs)
+ struct pstate *sregs;
+ {
+- sregs->tottime = 0;
++ sregs->tottime = 0.0;
+ sregs->pwdtime = 0;
+ sregs->ninst = 0;
+ sregs->fholdt = 0;
+@@ -632,9 +632,10 @@ show_stat(sregs)
+ struct pstate *sregs;
+ {
+ uint32 iinst;
+- uint32 stime, tottime;
++ uint32 stime;
+
+- if (sregs->tottime == 0) tottime = 1; else tottime = sregs->tottime;
++ if (sregs->tottime == 0.0)
++ sregs->tottime += 1E-6;
+ stime = ebase.simtime - sregs->simstart; /* Total simulated time */
+ #ifdef STAT
+
+@@ -669,12 +670,15 @@ show_stat(sregs)
+ sregs->freq * (float) (sregs->ninst - sregs->finst) /
+ (float) (stime - sregs->pwdtime),
+ sregs->freq * (float) sregs->finst / (float) (stime - sregs->pwdtime));
+- printf(" Simulated ERC32 time : %5.2f ms\n", (float) (ebase.simtime - sregs->simstart) / 1000.0 / sregs->freq);
+- printf(" Processor utilisation : %5.2f %%\n", 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime)));
+- printf(" Real-time / simulator-time : 1/%.2f \n",
+- ((float) sregs->tottime) / ((float) (stime) / (sregs->freq * 1.0E6)));
+- printf(" Simulator performance : %d KIPS\n",sregs->ninst/tottime/1000);
+- printf(" Used time (sys + user) : %3d s\n\n", sregs->tottime);
++ printf(" Simulated ERC32 time : %.2f s\n",
++ (float) (ebase.simtime - sregs->simstart) / 1000000.0 / sregs->freq);
++ printf(" Processor utilisation : %.2f %%\n",
++ 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime)));
++ printf(" Real-time performance : %.2f %%\n",
++ 100.0 / (sregs->tottime / ((double) (stime) / (sregs->freq * 1.0E6))));
++ printf(" Simulator performance : %.2f MIPS\n",
++ (double)(sregs->ninst) / sregs->tottime / 1E6);
++ printf(" Used time (sys + user) : %.2f s\n\n", sregs->tottime);
+ }
+
+
+@@ -1128,3 +1132,16 @@ bfd_load(fname)
+
+ return(bfd_get_start_address (pbfd));
+ }
++
++
++double get_time (void)
++{
++ double usec;
++
++ struct timeval tm;
++
++ gettimeofday (&tm, NULL);
++ usec = ((double) tm.tv_sec) * 1E6 + ((double) tm.tv_usec);
++ return (usec / 1E6);
++
++}
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 9ac455f..38a2a0d 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -24,7 +24,6 @@
+ #include <string.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+-#include <time.h>
+ #include <sys/fcntl.h>
+ #include "sis.h"
+ #include "libiberty.h"
+@@ -76,7 +75,7 @@ run_sim(sregs, icount, dis)
+ (*sim_callback->printf_filtered) (sim_callback, "resuming at %x\n",
+ sregs->pc);
+ init_stdio();
+- sregs->starttime = time(NULL);
++ sregs->starttime = get_time();
+ irq = 0;
+ if ((sregs->pc != 0) && (ebase.simtime == 0)) boot_init();
+ while (!sregs->err_mode & (icount > 0)) {
+@@ -142,7 +141,7 @@ run_sim(sregs, icount, dis)
+ }
+ }
+ sim_halt();
+- sregs->tottime += time(NULL) - sregs->starttime;
++ sregs->tottime += get_time() - sregs->starttime;
+ restore_stdio();
+ clearerr(stdin);
+ if (sregs->err_mode)
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index 89e6f02..f2aed78 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -26,7 +26,6 @@
+ #include <stdlib.h>
+ #endif
+ #include <stdio.h>
+-#include <time.h>
+ #include <sys/fcntl.h>
+ #include "sis.h"
+ #include <dis-asm.h>
+@@ -86,7 +85,7 @@ run_sim(sregs, icount, dis)
+ {
+ int irq, mexc, deb, asi;
+
+- sregs->starttime = time(NULL);
++ sregs->starttime = get_time();
+ init_stdio();
+ if (sregs->err_mode) icount = 0;
+ deb = dis || sregs->histlen || sregs->bptnum;
+@@ -146,7 +145,7 @@ run_sim(sregs, icount, dis)
+ if (sregs->tlimit <= ebase.simtime) sregs->tlimit = -1;
+ }
+ }
+- sregs->tottime += time(NULL) - sregs->starttime;
++ sregs->tottime += get_time() - sregs->starttime;
+ restore_stdio();
+ if (sregs->err_mode)
+ return (ERROR);
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index f49d45d..dc02c65 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -110,14 +110,14 @@ struct pstate {
+ float32 freq; /* Simulated processor frequency */
+
+
+- uint64 tottime;
++ double tottime;
+ uint64 ninst;
+ uint64 fholdt;
+ uint64 holdt;
+ uint64 icntt;
+ uint64 finst;
+ uint64 simstart;
+- uint64 starttime;
++ double starttime;
+ uint64 tlimit; /* Simulation time limit */
+ uint64 pwdtime; /* Cycles in power-down mode */
+ uint64 nstore; /* Number of load instructions */
+@@ -198,6 +198,7 @@ extern void reset_all (void);
+ extern void sys_reset (void);
+ extern void sys_halt (void);
+ extern int bfd_load (char *fname);
++extern double get_time (void);
+
+ /* exec.c */
+ extern int dispatch_instruction (struct pstate *sregs);
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0007-sim-erc32-File-loading-via-command-line-did-not-work.patch b/tools/4.11/gdb/sparc/7.9/0007-sim-erc32-File-loading-via-command-line-did-not-work.patch
new file mode 100644
index 0000000..e6b4364
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0007-sim-erc32-File-loading-via-command-line-did-not-work.patch
@@ -0,0 +1,43 @@
+From bdf71b87a2aff21de63accd86f8814b576f8a766 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 23:00:43 +0200
+Subject: [PATCH 07/23] sim/erc32: File loading via command line did not work
+
+ * sis.c (main) load binary file from argv parameters
+---
+ sim/erc32/sis.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index f2aed78..d7fa245 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -171,6 +171,7 @@ main(argc, argv)
+ char *cmdq[HIST_LEN];
+ int cmdi = 0;
+ int i;
++ int lfile = 0;
+
+ cfile = 0;
+ for (i = 0; i < 64; i++)
+@@ -219,7 +220,7 @@ main(argc, argv)
+ exit(1);
+ }
+ } else {
+- last_load_addr = bfd_load(argv[stat]);
++ lfile = stat;
+ }
+ stat++;
+ }
+@@ -241,6 +242,8 @@ main(argc, argv)
+ reset_all();
+ init_bpt(&sregs);
+ init_sim();
++ if (lfile)
++ last_load_addr = bfd_load(argv[lfile]);
+ #ifdef STAT
+ reset_stat(&sregs);
+ #endif
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0008-sim-erc32-Added-v-command-line-switch-for-verbose-ou.patch b/tools/4.11/gdb/sparc/7.9/0008-sim-erc32-Added-v-command-line-switch-for-verbose-ou.patch
new file mode 100644
index 0000000..92e6cdb
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0008-sim-erc32-Added-v-command-line-switch-for-verbose-ou.patch
@@ -0,0 +1,123 @@
+From f13f6b1731a63b0b79df7232f675f3f8d44be074 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 23:01:13 +0200
+Subject: [PATCH 08/23] sim/erc32: Added -v command line switch for verbose
+ output
+
+ * help.c (usage) update usage help print-out
+
+ * sis.c (run_sim) increase debug level with -v. Also print
+ simulation time in long long format.
+---
+ sim/erc32/func.c | 5 +++--
+ sim/erc32/help.c | 2 +-
+ sim/erc32/sis.c | 9 ++++++---
+ sim/erc32/sis.h | 5 +++++
+ 4 files changed, 15 insertions(+), 6 deletions(-)
+
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index 06c00b4..f1d5bd7 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -29,6 +29,7 @@
+ #include "end.h"
+ #include <dis-asm.h>
+ #include "sim-config.h"
++#include <inttypes.h>
+
+
+ #define VAL(x) strtoul(x,(char **)NULL,0)
+@@ -643,8 +644,8 @@ show_stat(sregs)
+ sregs->nbranch;
+ #endif
+
+- printf("\n Cycles : %9d\n\r", ebase.simtime - sregs->simstart);
+- printf(" Instructions : %9d\n", sregs->ninst);
++ printf("\n Cycles : %9" PRIu64 "\n\r", ebase.simtime - sregs->simstart);
++ printf(" Instructions : %9" PRIu64 "\n", sregs->ninst);
+
+ #ifdef STAT
+ printf(" integer : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst);
+diff --git a/sim/erc32/help.c b/sim/erc32/help.c
+index 21c2a77..9813bda 100644
+--- a/sim/erc32/help.c
++++ b/sim/erc32/help.c
+@@ -7,8 +7,8 @@ usage()
+ {
+
+ printf("usage: sis [-uart1 uart_device1] [-uart2 uart_device2]\n");
++ printf("[-sparclite] [-dumbio] [-v] \n");
+ printf("[-nfp] [-freq frequency] [-c batch_file] [files]\n");
+- printf("[-sparclite] [-dumbio]\n");
+ }
+
+ void
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index d7fa245..7c18c1e 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -30,6 +30,7 @@
+ #include "sis.h"
+ #include <dis-asm.h>
+ #include "sim-config.h"
++#include <inttypes.h>
+
+ #define VAL(x) strtol(x,(char **)NULL,0)
+
+@@ -122,7 +123,7 @@ run_sim(sregs, icount, dis)
+ sregs->histind = 0;
+ }
+ if (dis) {
+- printf(" %8u ", ebase.simtime);
++ printf(" %8" PRIu64 " ", ebase.simtime);
+ dis_mem(sregs->pc, 1, &dinfo);
+ }
+ }
+@@ -214,6 +215,8 @@ main(argc, argv)
+ #endif
+ } else if (strcmp(argv[stat], "-dumbio") == 0) {
+ dumbio = 1;
++ } else if (strcmp(argv[stat], "-v") == 0) {
++ sis_verbose += 1;
+ } else {
+ printf("unknown option %s\n", argv[stat]);
+ usage();
+@@ -280,7 +283,7 @@ main(argc, argv)
+ case CTRL_C:
+ printf("\b\bInterrupt!\n");
+ case TIME_OUT:
+- printf(" Stopped at time %d (%.3f ms)\n", ebase.simtime,
++ printf(" Stopped at time %" PRIu64 " (%.3f ms)\n", ebase.simtime,
+ ((double) ebase.simtime / (double) sregs.freq) / 1000.0);
+ break;
+ case BPT_HIT:
+@@ -290,7 +293,7 @@ main(argc, argv)
+ case ERROR:
+ printf("IU in error mode (%d)\n", sregs.trap);
+ stat = 0;
+- printf(" %8d ", ebase.simtime);
++ printf(" %8" PRIu64 " ", ebase.simtime);
+ dis_mem(sregs.pc, 1, &dinfo);
+ break;
+ default:
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index dc02c65..1ff6ced 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -52,8 +52,13 @@ typedef float float32; /* 32-bit float */
+ typedef double float64; /* 64-bit float */
+
+ /* FIXME: what about host compilers that don't support 64-bit ints? */
++#ifdef __LP64__
++typedef unsigned long uint64; /* 64-bit unsigned int */
++typedef long int64; /* 64-bit signed int */
++#else
+ typedef unsigned long long uint64; /* 64-bit unsigned int */
+ typedef long long int64; /* 64-bit signed int */
++#endif
+
+ #define UINT64_MAX 18446744073709551615ULL
+
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0009-sim-erc32-Removed-type-mismatch-compiler-warnings.patch b/tools/4.11/gdb/sparc/7.9/0009-sim-erc32-Removed-type-mismatch-compiler-warnings.patch
new file mode 100644
index 0000000..a10b8b7
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0009-sim-erc32-Removed-type-mismatch-compiler-warnings.patch
@@ -0,0 +1,66 @@
+From b65439074a4f4b2b6f5e5756124de49d4821656b Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 23:02:01 +0200
+Subject: [PATCH 09/23] sim/erc32: Removed type mismatch compiler warnings
+
+ * func.c (batch, exec_cmd) save return value to avoid warnings.
+ (batch) replace fgets() with getline().
+---
+ sim/erc32/func.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index f1d5bd7..a715f0f 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -81,20 +81,23 @@ batch(sregs, fname)
+ char *fname;
+ {
+ FILE *fp;
+- char lbuf[1024];
++ char *lbuf = NULL;
++ size_t len = 0;
++ ssize_t tmp;
+
+ if ((fp = fopen(fname, "r")) == NULL) {
+ fprintf(stderr, "couldn't open batch file %s\n", fname);
+ return (0);
+ }
+ while (!feof(fp)) {
+- lbuf[0] = 0;
+- fgets(lbuf, 1023, fp);
+- if ((strlen(lbuf) > 0) && (lbuf[strlen(lbuf) - 1] == '\n'))
++ tmp = getline(&lbuf, &len, fp);
++ if ((strlen(lbuf) > 0) && (lbuf[strlen(lbuf) - 1] == '\n')) {
+ lbuf[strlen(lbuf) - 1] = 0;
+- printf("sis> %s\n", lbuf);
+- exec_cmd(sregs, lbuf);
++ printf("sis> %s\n", lbuf);
++ exec_cmd(sregs, lbuf);
++ }
+ }
++ if (lbuf) free(lbuf);
+ fclose(fp);
+ return (1);
+ }
+@@ -383,7 +386,7 @@ exec_cmd(sregs, cmd)
+ {
+ char *cmd1, *cmd2;
+ int32 stat;
+- uint32 len, i, clen, j;
++ uint32 len, i, clen, j, tmp;
+ static uint32 daddr = 0;
+ char *cmdsave;
+
+@@ -555,7 +558,7 @@ exec_cmd(sregs, cmd)
+ sim_halt();
+ } else if (strncmp(cmd1, "shell", clen) == 0) {
+ if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+- system(&cmdsave[clen]);
++ tmp = system(&cmdsave[clen]);
+ }
+ } else if (strncmp(cmd1, "step", clen) == 0) {
+ stat = run_sim(sregs, 1, 1);
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0010-sim-erc32-Switched-emulated-memory-to-host-endian-or.patch b/tools/4.11/gdb/sparc/7.9/0010-sim-erc32-Switched-emulated-memory-to-host-endian-or.patch
new file mode 100644
index 0000000..04f5e90
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0010-sim-erc32-Switched-emulated-memory-to-host-endian-or.patch
@@ -0,0 +1,564 @@
+From 335799e56181cd0d1ff8128b20b01835e344ee43 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 23:39:33 +0200
+Subject: [PATCH 10/23] sim/erc32: Switched emulated memory to host endian
+ order.
+
+ Change data ordering in emulated memory from target order (big endian)
+ to host order. Improves performance and simplifies most memory
+ operations. Requires some byte twisting during stores on little
+ endian hosts (intel).
+
+ * erc32.c (fetch_bytes) Remove. (store_bytes) Remove byte twisting.
+ (memory_read) Access memory directly. (extract_short,
+ extract_short_signed, extract_byte, extract_byte_signed) New
+ function for for sub-word LD instructions.
+
+ * func.c (disp_ctrl, dis_mem) Ajust print-out to new data endian.
+
+ * interf.c (sim_open) Convert endian when gdb writes to memory.
+---
+ sim/erc32/erc32.c | 167 ++++++++++++-----------------------------------------
+ sim/erc32/exec.c | 58 ++++++++++++++++---
+ sim/erc32/func.c | 33 +++++++----
+ sim/erc32/interf.c | 29 ++++++++++
+ sim/erc32/sis.c | 4 ++
+ 5 files changed, 142 insertions(+), 149 deletions(-)
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index 0f3e870..7c80e13 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -297,11 +297,8 @@ static void gpt_reload_set (uint32 val);
+ static void timer_ctrl (uint32 val);
+ static unsigned char *
+ get_mem_ptr (uint32 addr, uint32 size);
+-
+-static void fetch_bytes (int asi, unsigned char *mem,
+- uint32 *data, int sz);
+-
+-static void store_bytes (unsigned char *mem, uint32 *data, int sz);
++static void store_bytes (unsigned char *mem, uint32 waddr,
++ uint32 *data, int sz, int32 *ws);
+
+ extern int ext_irl;
+
+@@ -1525,123 +1522,44 @@ timer_ctrl(val)
+ gpt_start();
+ }
+
+-
+-/* Retrieve data from target memory. MEM points to location from which
+- to read the data; DATA points to words where retrieved data will be
+- stored in host byte order. 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). */
++/* 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
+-fetch_bytes (asi, mem, data, sz)
+- int asi;
++store_bytes (mem, waddr, data, sz, ws)
+ unsigned char *mem;
++ uint32 waddr;
+ uint32 *data;
+- int sz;
++ int32 sz;
++ int32 *ws;
+ {
+- if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN
+- || asi == 8 || asi == 9) {
+- switch (sz) {
+- case 3:
+- data[1] = (((uint32) mem[7]) & 0xff) |
+- ((((uint32) mem[6]) & 0xff) << 8) |
+- ((((uint32) mem[5]) & 0xff) << 16) |
+- ((((uint32) mem[4]) & 0xff) << 24);
+- /* Fall through to 2 */
+- case 2:
+- data[0] = (((uint32) mem[3]) & 0xff) |
+- ((((uint32) mem[2]) & 0xff) << 8) |
+- ((((uint32) mem[1]) & 0xff) << 16) |
+- ((((uint32) mem[0]) & 0xff) << 24);
+- break;
+- case 1:
+- data[0] = (((uint32) mem[1]) & 0xff) |
+- ((((uint32) mem[0]) & 0xff) << 8);
+- break;
++ switch (sz) {
+ case 0:
+- data[0] = mem[0] & 0xff;
+- break;
+-
+- }
+- } else {
+- switch (sz) {
+- case 3:
+- data[1] = ((((uint32) mem[7]) & 0xff) << 24) |
+- ((((uint32) mem[6]) & 0xff) << 16) |
+- ((((uint32) mem[5]) & 0xff) << 8) |
+- (((uint32) mem[4]) & 0xff);
+- /* Fall through to 4 */
+- case 2:
+- data[0] = ((((uint32) mem[3]) & 0xff) << 24) |
+- ((((uint32) mem[2]) & 0xff) << 16) |
+- ((((uint32) mem[1]) & 0xff) << 8) |
+- (((uint32) mem[0]) & 0xff);
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= 3;
++#endif
++ mem[waddr] = *data & 0x0ff;
++ *ws = mem_ramw_ws + 3;
+ break;
+ case 1:
+- data[0] = ((((uint32) mem[1]) & 0xff) << 8) |
+- (((uint32) mem[0]) & 0xff);
+- break;
+- case 0:
+- data[0] = mem[0] & 0xff;
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= 2;
++#endif
++ *((unsigned short *) &(mem[waddr])) = *data & 0x0ffff;
++ *ws = mem_ramw_ws + 3;
+ break;
+- }
+- }
+-}
+-
+-
+-/* Store data in target byte order. MEM points to location to store data;
+- 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). */
+-
+-static void
+-store_bytes (mem, data, sz)
+- unsigned char *mem;
+- uint32 *data;
+- int sz;
+-{
+- if (CURRENT_TARGET_BYTE_ORDER == LITTLE_ENDIAN) {
+- switch (sz) {
+- case 3:
+- mem[7] = (data[1] >> 24) & 0xff;
+- mem[6] = (data[1] >> 16) & 0xff;
+- mem[5] = (data[1] >> 8) & 0xff;
+- mem[4] = data[1] & 0xff;
+- /* Fall through to 2 */
+ case 2:
+- mem[3] = (data[0] >> 24) & 0xff;
+- mem[2] = (data[0] >> 16) & 0xff;
+- /* Fall through to 1 */
+- case 1:
+- mem[1] = (data[0] >> 8) & 0xff;
+- /* Fall through to 0 */
+- case 0:
+- mem[0] = data[0] & 0xff;
++ *((uint32 *) &(mem[waddr])) = *data;
++ *ws = mem_ramw_ws;
+ break;
+- }
+- } else {
+- switch (sz) {
+ case 3:
+- mem[7] = data[1] & 0xff;
+- mem[6] = (data[1] >> 8) & 0xff;
+- mem[5] = (data[1] >> 16) & 0xff;
+- mem[4] = (data[1] >> 24) & 0xff;
+- /* Fall through to 2 */
+- case 2:
+- mem[3] = data[0] & 0xff;
+- mem[2] = (data[0] >> 8) & 0xff;
+- mem[1] = (data[0] >> 16) & 0xff;
+- mem[0] = (data[0] >> 24) & 0xff;
+- break;
+- case 1:
+- mem[1] = data[0] & 0xff;
+- mem[0] = (data[0] >> 8) & 0xff;
+- break;
+- case 0:
+- mem[0] = data[0] & 0xff;
++ *((uint32 *) &(mem[waddr])) = data[0];
++ *((uint32 *) &(mem[waddr + 4])) = data[1];
++ *ws = 2 * mem_ramw_ws + STD_WS;
+ break;
+-
+- }
+ }
+ }
+
+@@ -1671,7 +1589,7 @@ memory_read(asi, addr, data, sz, ws)
+ #endif
+
+ if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
+- fetch_bytes (asi, &ramb[addr & mem_rammask], data, sz);
++ *data = *((uint32 *) & (ramb[addr & mem_rammask & ~3]));
+ *ws = mem_ramr_ws;
+ return (0);
+ } else if ((addr >= MEC_START) && (addr < MEC_END)) {
+@@ -1689,7 +1607,7 @@ memory_read(asi, addr, data, sz, ws)
+ } else if (era) {
+ if ((addr < 0x100000) ||
+ ((addr>= 0x80000000) && (addr < 0x80100000))) {
+- fetch_bytes (asi, &romb[addr & ROM_MASK], data, sz);
++ *data = *((uint32 *) & (romb[addr & ROM_MASK & ~3]));
+ *ws = 4;
+ return (0);
+ } else if ((addr >= 0x10000000) &&
+@@ -1700,13 +1618,13 @@ memory_read(asi, addr, data, sz, ws)
+ }
+
+ } else if (addr < mem_romsz) {
+- fetch_bytes (asi, &romb[addr], data, sz);
++ *data = *((uint32 *) & (romb[addr & ~3]));
+ *ws = mem_romr_ws;
+ return (0);
+
+ #else
+ } else if (addr < mem_romsz) {
+- fetch_bytes (asi, &romb[addr], data, sz);
++ *data = *((uint32 *) & (romb[addr & ~3]));
+ *ws = mem_romr_ws;
+ return (0);
+ #endif
+@@ -1769,21 +1687,10 @@ memory_write(asi, addr, data, sz, ws)
+ }
+ }
+
+- store_bytes (&ramb[addr & mem_rammask], data, sz);
+-
+- switch (sz) {
+- case 0:
+- case 1:
+- *ws = mem_ramw_ws + 3;
+- break;
+- case 2:
+- *ws = mem_ramw_ws;
+- break;
+- case 3:
+- *ws = 2 * mem_ramw_ws + STD_WS;
+- break;
+- }
++ waddr = addr & mem_rammask;
++ store_bytes (ramb, waddr, data, sz, ws);
+ return (0);
++
+ } else if ((addr >= MEC_START) && (addr < MEC_END)) {
+ if ((sz != 2) || (asi != 0xb)) {
+ set_sfsr(MEC_ACC, addr, asi, 0);
+@@ -1806,7 +1713,7 @@ memory_write(asi, addr, data, sz, ws)
+ ((addr < 0x100000) || ((addr >= 0x80000000) && (addr < 0x80100000)))) {
+ addr &= ROM_MASK;
+ *ws = sz == 3 ? 8 : 4;
+- store_bytes (&romb[addr], data, sz);
++ store_bytes (romb, addr, data, sz, ws);
+ return (0);
+ } else if ((addr >= 0x10000000) &&
+ (addr < (0x10000000 + (512 << (mec_iocr & 0x0f)))) &&
+@@ -1822,7 +1729,7 @@ memory_write(asi, addr, data, sz, ws)
+ *ws = mem_romw_ws + 1;
+ if (sz == 3)
+ *ws += mem_romw_ws + STD_WS;
+- store_bytes (&romb[addr], data, sz);
++ store_bytes (romb, addr, data, sz, ws);
+ return (0);
+
+ #else
+@@ -1833,7 +1740,7 @@ memory_write(asi, addr, data, sz, ws)
+ *ws = mem_romw_ws + 1;
+ if (sz == 3)
+ *ws += mem_romw_ws + STD_WS;
+- store_bytes (&romb[addr], data, sz);
++ store_bytes (romb, addr, data, sz, ws);
+ return (0);
+
+ #endif
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index 07f3586..e80e02a 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -371,6 +371,36 @@ div64 (uint32 n1_hi, uint32 n1_low, uint32 n2, uint32 *result, int msigned)
+ }
+
+
++static int
++extract_short(uint32 data, uint32 address)
++{
++ return((data>>((2 - (address & 2))*8)) & 0xffff);
++}
++
++static int
++extract_short_signed(uint32 data, uint32 address)
++{
++ uint32 tmp;
++ tmp = ((data>>((2 - (address & 2))*8)) & 0xffff);
++ if (tmp & 0x8000) tmp |= 0xffff0000;
++ return(tmp);
++}
++
++static int
++extract_byte(uint32 data, uint32 address)
++{
++ return((data>>((3 - (address & 3))*8)) & 0xff);
++}
++
++static int
++extract_byte_signed(uint32 data, uint32 address)
++{
++ uint32 tmp;
++ tmp = ((data>>((3 - (address & 3))*8)) & 0xff);
++ if (tmp & 0x80) tmp |= 0xffffff00;
++ return(tmp);
++}
++
+ int
+ dispatch_instruction(sregs)
+ struct pstate *sregs;
+@@ -1078,7 +1108,8 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_PRIVI;
+ break;
+ }
+- sregs->psr = (rs1 ^ operand2) & 0x00f03fff;
++ sregs->psr = (sregs->psr & 0xff000000) |
++ (rs1 ^ operand2) & 0x00f03fff;
+ break;
+ case WRWIM:
+ if (!(sregs->psr & PSR_S)) {
+@@ -1214,8 +1245,10 @@ dispatch_instruction(sregs)
+ else
+ rdd = &(sregs->g[rd]);
+ }
+- mexc = memory_read(asi, address, ddata, 3, &ws);
+- sregs->hold += ws * 2;
++ mexc = memory_read(asi, address, ddata, 2, &ws);
++ sregs->hold += ws;
++ mexc |= memory_read(asi, address+4, &ddata[1], 2, &ws);
++ sregs->hold += ws;
+ sregs->icnt = T_LDD;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+@@ -1253,6 +1286,7 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_DEXC;
+ break;
+ }
++ data = extract_byte(data, address);
+ *rdd = data;
+ data = 0x0ff;
+ mexc = memory_write(asi, address, &data, 0, &ws);
+@@ -1275,8 +1309,10 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_DEXC;
+ break;
+ }
+- if ((op3 == LDSB) && (data & 0x80))
+- data |= 0xffffff00;
++ if (op3 == LDSB)
++ data = extract_byte_signed(data, address);
++ else
++ data = extract_byte(data, address);
+ *rdd = data;
+ break;
+ case LDSHA:
+@@ -1294,8 +1330,10 @@ dispatch_instruction(sregs)
+ sregs->trap = TRAP_DEXC;
+ break;
+ }
+- if ((op3 == LDSH) && (data & 0x8000))
+- data |= 0xffff0000;
++ if (op3 == LDSH)
++ data = extract_short_signed(data, address);
++ else
++ data = extract_short(data, address);
+ *rdd = data;
+ break;
+ case LDF:
+@@ -1338,8 +1376,10 @@ dispatch_instruction(sregs)
+ ((sregs->frs2 >> 1) == (rd >> 1)))
+ sregs->fhold += (sregs->ftime - ebase.simtime);
+ }
+- mexc = memory_read(asi, address, ddata, 3, &ws);
+- sregs->hold += ws * 2;
++ mexc = memory_read(asi, address, ddata, 2, &ws);
++ sregs->hold += ws;
++ mexc |= memory_read(asi, address+4, &ddata[1], 2, &ws);
++ sregs->hold += ws;
+ sregs->icnt = T_LDD;
+ if (mexc) {
+ sregs->trap = TRAP_DEXC;
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index a715f0f..bcccf6d 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -785,15 +785,15 @@ disp_ctrl(sregs)
+ struct pstate *sregs;
+ {
+
+- unsigned char i[4];
++ uint32 i;
+
+ printf("\n psr: %08X wim: %08X tbr: %08X y: %08X\n",
+ sregs->psr, sregs->wim, sregs->tbr, sregs->y);
+- sis_memory_read(sregs->pc, i, 4);
+- printf("\n pc: %08X = %02X%02X%02X%02X ", sregs->pc,i[0],i[1],i[2],i[3]);
++ 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, i, 4);
+- printf("\n npc: %08X = %02X%02X%02X%02X ",sregs->npc,i[0],i[1],i[2],i[3]);
++ 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)
+ printf("\n IU in error mode");
+@@ -808,21 +808,28 @@ disp_mem(addr, len)
+
+ uint32 i;
+ unsigned char data[4];
++ uint32 *wdata = (uint32 *) data;
+ uint32 mem[4], j;
+ char *p;
++ int end;
+
++#ifdef HOST_LITTLE_ENDIAN
++ end = 3;
++#else
++ end = 0;
++#endif
+ 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, 4);
+- printf("%02x%02x%02x%02x ", data[0],data[1],data[2],data[3]);
++ printf("%08x ", *wdata);
+ mem[j] = *((int *) &data);
+ }
+ printf(" ");
+ p = (char *) mem;
+ for (j = 0; j < 16; j++) {
+- if (isprint(p[j]))
+- putchar(p[j]);
++ if (isprint(p[j^end]))
++ putchar(p[j^end]);
+ else
+ putchar('.');
+ }
+@@ -838,10 +845,11 @@ dis_mem(addr, len, info)
+ {
+ uint32 i;
+ unsigned char data[4];
++ uint32 *wdata = (uint32 *) data;
+
+ for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) {
+ sis_memory_read(i, data, 4);
+- printf(" %08x %02x%02x%02x%02x ", i, data[0],data[1],data[2],data[3]);
++ printf(" %08x %08x ", i, *wdata);
+ print_insn_sparc_sis(i, info);
+ if (i >= 0xfffffffc) break;
+ printf("\n");
+@@ -1040,6 +1048,7 @@ bfd_load(fname)
+ asection *section;
+ bfd *pbfd;
+ const bfd_arch_info_type *arch;
++ int i;
+
+ pbfd = bfd_openr(fname, 0);
+
+@@ -1113,13 +1122,17 @@ bfd_load(fname)
+ fptr = 0;
+
+ while (section_size > 0) {
+- char buffer[1024];
+ int count;
++ char buffer[1024];
++ uint32 *wbuffer = (uint32 *) buffer;
+
+ count = min(section_size, 1024);
+
+ bfd_get_section_contents(pbfd, section, buffer, fptr, count);
+
++#ifdef HOST_LITTLE_ENDIAN
++ for (i=0;i<count/4;i++) wbuffer[i] = ntohl(wbuffer[i]); // endian swap
++#endif
+ sis_memory_write(section_address, buffer, count);
+
+ section_address += count;
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 38a2a0d..3a72e7f 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -265,7 +265,11 @@ sim_open (kind, callback, abfd, argv)
+ sregs.freq = freq ? freq : 15;
+ termsave = fcntl(0, F_GETFL, 0);
+ INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
++#ifdef HOST_LITTLE_ENDIAN
++ dinfo.endian = BFD_ENDIAN_LITTLE;
++#else
+ dinfo.endian = BFD_ENDIAN_BIG;
++#endif
+ reset_all();
+ ebase.simtime = 0;
+ init_sim();
+@@ -355,7 +359,19 @@ sim_write(sd, mem, buf, length)
+ const unsigned char *buf;
+ int length;
+ {
++#ifdef HOST_LITTLE_ENDIAN
++ int *ibufp = (int *) buf;
++ int ibuf[8192];
++ int i, len;
++
++ if (length >= 4)
++ for (i=0; i<length; i+=4) {
++ ibuf[i] = ntohl(ibufp[i]);
++ }
++ return (sis_memory_write(mem, (char *) ibuf, length));
++#else
+ return (sis_memory_write(mem, buf, length));
++#endif
+ }
+
+ int
+@@ -365,7 +381,20 @@ sim_read(sd, mem, buf, length)
+ unsigned char *buf;
+ int length;
+ {
++#ifdef HOST_LITTLE_ENDIAN
++ int *ibuf = (int *) buf;
++ int i, len;
++
++ len = sis_memory_read(mem, buf, length);
++ if (length >= 4)
++ for (i=0; i<length; i+=4) {
++ *ibuf = htonl(*ibuf);
++ ibuf++;
++ }
++ return (len);
++#else
+ return (sis_memory_read(mem, buf, length));
++#endif
+ }
+
+ void
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index 7c18c1e..523d8aa 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -236,7 +236,11 @@ main(argc, argv)
+ sregs.freq = freq;
+
+ INIT_DISASSEMBLE_INFO(dinfo, stdout, (fprintf_ftype) fprintf);
++#ifdef HOST_LITTLE_ENDIAN
++ dinfo.endian = BFD_ENDIAN_LITTLE;
++#else
+ dinfo.endian = BFD_ENDIAN_BIG;
++#endif
+
+ termsave = fcntl(0, F_GETFL, 0);
+ using_history();
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0011-sim-erc32-use-SIM_AC_OPTION_HOSTENDIAN-to-probe-for-.patch b/tools/4.11/gdb/sparc/7.9/0011-sim-erc32-use-SIM_AC_OPTION_HOSTENDIAN-to-probe-for-.patch
new file mode 100644
index 0000000..3632610
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0011-sim-erc32-use-SIM_AC_OPTION_HOSTENDIAN-to-probe-for-.patch
@@ -0,0 +1,564 @@
+From fb01b2350dd60d0ec99e5f1a3b262add609507f7 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Wed, 18 Feb 2015 16:50:55 +0100
+Subject: [PATCH 11/23] sim/erc32: use SIM_AC_OPTION_HOSTENDIAN to probe for
+ host endianess
+
+ * Makefile.in (end, end.h) Remove target rules.
+ * end.c Remove unnecessary local checks (end.c)
+ * configure, config.in : Regenerate.
+ * configure.ac : Use SIM_AC_OPTION_HOSTENDIAN
+ * erc32.c : Remove dependecy on end.h
+ * exec.c : Remove dependecy on end.h. Use HOST_LITTLE_ENDIAN.
+ * func.c : As above.
+ * sis.c : As above.
+---
+ sim/erc32/Makefile.in | 18 +---
+ sim/erc32/config.in | 15 +++
+ sim/erc32/configure | 260 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ sim/erc32/configure.ac | 1 +
+ sim/erc32/end.c | 27 -----
+ sim/erc32/erc32.c | 1 -
+ sim/erc32/exec.c | 7 +-
+ sim/erc32/func.c | 3 +-
+ sim/erc32/sis.h | 9 +-
+ 9 files changed, 284 insertions(+), 57 deletions(-)
+ delete mode 100644 sim/erc32/end.c
+
+diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
+index 418e7e4..e0860a0 100644
+--- a/sim/erc32/Makefile.in
++++ b/sim/erc32/Makefile.in
+@@ -41,21 +41,13 @@ sis: sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) -o sis \
+ sis.o $(SIS_OFILES) $(COMMON_OBJS) $(EXTRA_LIBS)
+
+-# FIXME: This computes the build host's endianness, doesn't it?
+-# There is AC_C_BIGENDIAN but it doesn't handle float endianness.
+-# [Are int/float endians every different on a sparc?]
+-end: $(srcdir)/end.c
+- $(CC_FOR_BUILD) -I. $(srcdir)/end.c -o end
+-end.h: end
+- ./end > end.h
+-
+ # Copy the files into directories where they will be run.
+ install-sis: installdirs
+ n=`echo sis | sed '$(program_transform_name)'`; \
+ $(INSTALL_PROGRAM) sis$(EXEEXT) $(DESTDIR)$(bindir)/$$n$(EXEEXT)
+
+ clean-sis:
+- rm -f sis end end.h
++ rm -f sis
+
+ configure:
+ @echo "Rebuilding configure..."
+@@ -64,11 +56,3 @@ configure:
+ else true ; fi ; \
+ (cd $${srcdir}; autoconf --localdir=../common)
+
+-# Circumvent Sun Make bug with VPATH.
+-erc32.o: erc32.c sis.h end.h
+-exec.o: exec.c sis.h end.h
+-float.o: float.c sis.h end.h
+-func.o: func.c sis.h end.h
+-help.o: help.c sis.h end.h
+-interf.o: interf.c sis.h end.h
+-sis.o: sis.c sis.h end.h
+diff --git a/sim/erc32/config.in b/sim/erc32/config.in
+index 5fed8c1..b367e14 100644
+--- a/sim/erc32/config.in
++++ b/sim/erc32/config.in
+@@ -1,5 +1,8 @@
+ /* config.in. Generated from configure.ac by autoheader. */
+
++/* Define if building universal (internal helper macro) */
++#undef AC_APPLE_UNIVERSAL_BUILD
++
+ /* Define to 1 if translation of program messages to the user's native
+ language is requested. */
+ #undef ENABLE_NLS
+@@ -135,6 +138,18 @@
+ #endif
+
+
++/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
++ significant byte first (like Motorola and SPARC, unlike Intel). */
++#if defined AC_APPLE_UNIVERSAL_BUILD
++# if defined __BIG_ENDIAN__
++# define WORDS_BIGENDIAN 1
++# endif
++#else
++# ifndef WORDS_BIGENDIAN
++# undef WORDS_BIGENDIAN
++# endif
++#endif
++
+ /* Define to 1 if on MINIX. */
+ #undef _MINIX
+
+diff --git a/sim/erc32/configure b/sim/erc32/configure
+index ba43717..cbdcea5 100755
+--- a/sim/erc32/configure
++++ b/sim/erc32/configure
+@@ -761,6 +761,7 @@ enable_sim_trace
+ enable_sim_profile
+ with_pkgversion
+ with_bugurl
++enable_sim_hostendian
+ '
+ ac_precious_vars='build_alias
+ host_alias
+@@ -1403,6 +1404,7 @@ Optional Features:
+ --enable-sim-stdio Specify whether to use stdio for console input/output.
+ --enable-sim-trace=opts Enable tracing flags
+ --enable-sim-profile=opts Enable profiling flags
++ --enable-sim-hostendian=end Specify host byte endian orientation.
+
+ Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+@@ -8121,7 +8123,7 @@ $as_echo "$lt_cv_ld_force_load" >&6; }
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+ 10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+- 10.[012]*)
++ 10.[012][,.]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+@@ -10144,7 +10146,7 @@ _LT_EOF
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test "$tmp_diet" = no
+ then
+- tmp_addflag=
++ tmp_addflag=' $pic_flag'
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+@@ -12354,7 +12356,7 @@ else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+-#line 12357 "configure"
++#line 12359 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -12460,7 +12462,7 @@ else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+-#line 12463 "configure"
++#line 12465 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -13111,6 +13113,255 @@ fi
+ fi
+
+
++# Check whether --enable-sim-hostendian was given.
++if test "${enable_sim_hostendian+set}" = set; then :
++ enableval=$enable_sim_hostendian; case "${enableval}" in
++ no) sim_hostendian="-DWITH_HOST_BYTE_ORDER=0";;
++ b*|B*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN";;
++ l*|L*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN";;
++ *) as_fn_error "\"Unknown value $enableval for --enable-sim-hostendian\"" "$LINENO" 5; sim_hostendian="";;
++esac
++if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then
++ echo "Setting hostendian flags = $sim_hostendian" 6>&1
++fi
++else
++
++if test "x$cross_compiling" = "xno"; then
++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
++$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
++if test "${ac_cv_c_bigendian+set}" = set; then :
++ $as_echo_n "(cached) " >&6
++else
++ ac_cv_c_bigendian=unknown
++ # See if we're dealing with a universal compiler.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#ifndef __APPLE_CC__
++ not a universal capable compiler
++ #endif
++ typedef int dummy;
++
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++
++ # Check for potential -arch flags. It is not universal unless
++ # there are at least two -arch flags with different values.
++ ac_arch=
++ ac_prev=
++ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
++ if test -n "$ac_prev"; then
++ case $ac_word in
++ i?86 | x86_64 | ppc | ppc64)
++ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
++ ac_arch=$ac_word
++ else
++ ac_cv_c_bigendian=universal
++ break
++ fi
++ ;;
++ esac
++ ac_prev=
++ elif test "x$ac_word" = "x-arch"; then
++ ac_prev=arch
++ fi
++ done
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++ if test $ac_cv_c_bigendian = unknown; then
++ # See if sys/param.h defines the BYTE_ORDER macro.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include <sys/types.h>
++ #include <sys/param.h>
++
++int
++main ()
++{
++#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
++ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
++ && LITTLE_ENDIAN)
++ bogus endian macros
++ #endif
++
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++ # It does; now see whether it defined to BIG_ENDIAN or not.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include <sys/types.h>
++ #include <sys/param.h>
++
++int
++main ()
++{
++#if BYTE_ORDER != BIG_ENDIAN
++ not big endian
++ #endif
++
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++ ac_cv_c_bigendian=yes
++else
++ ac_cv_c_bigendian=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++ fi
++ if test $ac_cv_c_bigendian = unknown; then
++ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include <limits.h>
++
++int
++main ()
++{
++#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
++ bogus endian macros
++ #endif
++
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++ # It does; now see whether it defined to _BIG_ENDIAN or not.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#include <limits.h>
++
++int
++main ()
++{
++#ifndef _BIG_ENDIAN
++ not big endian
++ #endif
++
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++ ac_cv_c_bigendian=yes
++else
++ ac_cv_c_bigendian=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++ fi
++ if test $ac_cv_c_bigendian = unknown; then
++ # Compile a test program.
++ if test "$cross_compiling" = yes; then :
++ # Try to guess by grepping values from an object file.
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++short int ascii_mm[] =
++ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
++ short int ascii_ii[] =
++ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
++ int use_ascii (int i) {
++ return ascii_mm[i] + ascii_ii[i];
++ }
++ short int ebcdic_ii[] =
++ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
++ short int ebcdic_mm[] =
++ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
++ int use_ebcdic (int i) {
++ return ebcdic_mm[i] + ebcdic_ii[i];
++ }
++ extern int foo;
++
++int
++main ()
++{
++return use_ascii (foo) == use_ebcdic (foo);
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
++ ac_cv_c_bigendian=yes
++ fi
++ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
++ if test "$ac_cv_c_bigendian" = unknown; then
++ ac_cv_c_bigendian=no
++ else
++ # finding both strings is unlikely to happen, but who knows?
++ ac_cv_c_bigendian=unknown
++ fi
++ fi
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++else
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++$ac_includes_default
++int
++main ()
++{
++
++ /* Are we little or big endian? From Harbison&Steele. */
++ union
++ {
++ long int l;
++ char c[sizeof (long int)];
++ } u;
++ u.l = 1;
++ return u.c[sizeof (long int) - 1] == 1;
++
++ ;
++ return 0;
++}
++_ACEOF
++if ac_fn_c_try_run "$LINENO"; then :
++ ac_cv_c_bigendian=no
++else
++ ac_cv_c_bigendian=yes
++fi
++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
++ conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++
++ fi
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
++$as_echo "$ac_cv_c_bigendian" >&6; }
++ case $ac_cv_c_bigendian in #(
++ yes)
++ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
++;; #(
++ no)
++ ;; #(
++ universal)
++
++$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
++
++ ;; #(
++ *)
++ as_fn_error "unknown endianness
++ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
++ esac
++
++ if test $ac_cv_c_bigendian = yes; then
++ sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN"
++ else
++ sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN"
++ fi
++else
++ sim_hostendian="-DWITH_HOST_BYTE_ORDER=0"
++fi
++fi
++
++
+ ac_sources="$sim_link_files"
+ ac_dests="$sim_link_links"
+ while test -n "$ac_sources"; do
+@@ -13245,6 +13496,7 @@ if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+ fi
+
++
+ : ${CONFIG_STATUS=./config.status}
+ ac_write_fail=0
+ ac_clean_files_save=$ac_clean_files
+diff --git a/sim/erc32/configure.ac b/sim/erc32/configure.ac
+index bc46091..854845c 100644
+--- a/sim/erc32/configure.ac
++++ b/sim/erc32/configure.ac
+@@ -32,4 +32,5 @@ else
+ AC_ERROR([the required "readline" library is missing]), $TERMCAP)
+ fi
+ AC_SUBST(READLINE)
++SIM_AC_OPTION_HOSTENDIAN
+ SIM_AC_OUTPUT
+diff --git a/sim/erc32/end.c b/sim/erc32/end.c
+deleted file mode 100644
+index 9337198..0000000
+--- a/sim/erc32/end.c
++++ /dev/null
+@@ -1,27 +0,0 @@
+-#include "config.h"
+-#include <stdio.h>
+-
+-int
+-main()
+-{
+-
+- unsigned int u1;
+- char *c;
+- double d1;
+- float *f1;
+-
+- c = (char *) &u1;
+- u1 = 0x0F;
+- if (c[0] == 0x0F)
+- puts("#define HOST_LITTLE_ENDIAN\n");
+- else
+- puts("#define HOST_BIG_ENDIAN\n");
+-
+- d1 = 1.0;
+- f1 = (float *) &d1;
+- if (*((int *) f1) != 0x3ff00000)
+- puts("#define HOST_LITTLE_ENDIAN_FLOAT\n");
+- else
+- puts("#define HOST_BIG_ENDIAN_FLOAT\n");
+- return 0;
+-}
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index 7c80e13..eac49f7 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -30,7 +30,6 @@
+ #include <sys/file.h>
+ #include <unistd.h>
+ #include "sis.h"
+-#include "end.h"
+ #include "sim-config.h"
+
+ extern int ctrl_c;
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index e80e02a..237bb53 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -21,7 +21,6 @@
+
+ #include "config.h"
+ #include "sis.h"
+-#include "end.h"
+ #include <math.h>
+ #include <stdio.h>
+
+@@ -1736,7 +1735,7 @@ fpexec(op3, rd, rs1, rs2, sregs)
+ but what about machines where float values are different endianness
+ from integer values? */
+
+-#ifdef HOST_LITTLE_ENDIAN_FLOAT
++#ifdef HOST_LITTLE_ENDIAN
+ rs1 &= 0x1f;
+ switch (opf) {
+ case FADDd:
+@@ -1914,7 +1913,7 @@ fpexec(op3, rd, rs1, rs2, sregs)
+
+ accex = get_accex();
+
+-#ifdef HOST_LITTLE_ENDIAN_FLOAT
++#ifdef HOST_LITTLE_ENDIAN
+ switch (opf) {
+ case FADDd:
+ case FDIVd:
+@@ -2061,7 +2060,7 @@ init_regs(sregs)
+ sregs->err_mode = 0;
+ ext_irl = 0;
+ sregs->g[0] = 0;
+-#ifdef HOST_LITTLE_ENDIAN_FLOAT
++#ifdef HOST_LITTLE_ENDIAN
+ sregs->fdp = (float32 *) sregs->fd;
+ sregs->fsi = (int32 *) sregs->fs;
+ #else
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index bcccf6d..ab21e3c 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -26,7 +26,6 @@
+ #include <stdlib.h>
+ #include <ctype.h>
+ #include "sis.h"
+-#include "end.h"
+ #include <dis-asm.h>
+ #include "sim-config.h"
+ #include <inttypes.h>
+@@ -734,7 +733,7 @@ disp_fpu(sregs)
+
+ printf("\n fsr: %08X\n\n", sregs->fsr);
+
+-#ifdef HOST_LITTLE_ENDIAN_FLOAT
++#ifdef HOST_LITTLE_ENDIAN
+ for (i = 0; i < 32; i++)
+ sregs->fdp[i ^ 1] = sregs->fs[i];
+ #endif
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index 1ff6ced..ef5b149 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -23,8 +23,13 @@
+ #include "ansidecl.h"
+ #include "gdb/callback.h"
+ #include "gdb/remote-sim.h"
++#include <sim-config.h>
+
+-#include "end.h"
++#if WITH_HOST_BYTE_ORDER==BIG_ENDIAN
++#define HOST_BIG_ENDIAN
++#else
++#define HOST_LITTLE_ENDIAN
++#endif
+
+ #define I_ACC_EXC 1
+
+@@ -65,7 +70,7 @@ typedef long long int64; /* 64-bit signed int */
+ struct pstate {
+
+ float64 fd[16]; /* FPU registers */
+-#ifdef HOST_LITTLE_ENDIAN_FLOAT
++#ifdef HOST_LITTLE_ENDIAN
+ float32 fs[32];
+ float32 *fdp;
+ #else
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0012-sim-erc32-Use-memory_iread-function-for-instruction-.patch b/tools/4.11/gdb/sparc/7.9/0012-sim-erc32-Use-memory_iread-function-for-instruction-.patch
new file mode 100644
index 0000000..73aa065
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0012-sim-erc32-Use-memory_iread-function-for-instruction-.patch
@@ -0,0 +1,119 @@
+From d468feaaf511b29880faa297476ff98a9ef81b32 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 30 Aug 2014 23:47:46 +0200
+Subject: [PATCH 12/23] sim/erc32: Use memory_iread() function for instruction
+ fetching.
+
+ Use separate memory_iread() function for instruction fetching.
+ Speeds up execution and allows addition of an MMU at a later stage.
+
+ * erc32.c (memory_iread) New function to fetch instructions.
+ * interf.c (run_sim) Use memory_iread.
+ * sis.c (run_sim) As above.
+---
+ sim/erc32/erc32.c | 24 ++++++++++++++++++++++++
+ sim/erc32/interf.c | 5 ++---
+ sim/erc32/sis.c | 8 ++------
+ sim/erc32/sis.h | 2 ++
+ 4 files changed, 30 insertions(+), 9 deletions(-)
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index eac49f7..03b40dc 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -1566,6 +1566,30 @@ store_bytes (mem, waddr, data, sz, ws)
+ /* Memory emulation */
+
+ int
++memory_iread(addr, data, ws)
++ uint32 addr;
++ uint32 *data;
++ int32 *ws;
++{
++ uint32 asi;
++ if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
++ *data = *((uint32 *) & (ramb[addr & mem_rammask & ~3]));
++ *ws = mem_ramr_ws;
++ return (0);
++ } else if (addr < mem_romsz) {
++ *data = *((uint32 *) & (romb[addr & ~3]));
++ *ws = mem_romr_ws;
++ return (0);
++ }
++
++ printf("Memory exception at %x (illegal address)\n", addr);
++ if (sregs.psr & 0x080) asi = 9; else asi = 8;
++ set_sfsr(UIMP_ACC, addr, asi, 1);
++ *ws = MEM_EX_WS;
++ return (1);
++}
++
++int
+ memory_read(asi, addr, data, sz, ws)
+ int32 asi;
+ uint32 addr;
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 3a72e7f..981aa11 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -94,9 +94,8 @@ run_sim(sregs, icount, dis)
+ if (sregs->pc == 0 || sregs->npc == 0)
+ printf ("bogus pc or npc\n");
+ #endif
+- mexc = memory_read(sregs->asi, sregs->pc, &sregs->inst,
+- 2, &sregs->hold);
+-#if 1 /* DELETE ME! for debugging purposes only */
++ 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",
+ sregs->pc, sregs->npc,
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index 523d8aa..e109874 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -84,7 +84,7 @@ run_sim(sregs, icount, dis)
+ uint64 icount;
+ int dis;
+ {
+- int irq, mexc, deb, asi;
++ int irq, mexc, deb;
+
+ sregs->starttime = get_time();
+ init_stdio();
+@@ -93,11 +93,7 @@ run_sim(sregs, icount, dis)
+ irq = 0;
+ while (icount > 0) {
+
+- if (sregs->psr & 0x080)
+- asi = 9;
+- else
+- asi = 8;
+- mexc = memory_read(asi, sregs->pc, &sregs->inst, 2, &sregs->hold);
++ mexc = memory_iread(sregs->pc, &sregs->inst, &sregs->hold);
+ sregs->icnt = 1;
+ if (sregs->annul) {
+ sregs->annul = 0;
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index ef5b149..fb733de 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -176,6 +176,7 @@ 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,
+@@ -186,6 +187,7 @@ extern int sis_memory_read (uint32 addr, char *data,
+ uint32 length);
+
+ /* func.c */
++extern struct pstate sregs;
+ extern void set_regi (struct pstate *sregs, int32 reg,
+ uint32 rval);
+ extern void get_regi (struct pstate *sregs, int32 reg, char *buf);
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0013-sim-erc32-Fix-a-few-compiler-warnings.patch b/tools/4.11/gdb/sparc/7.9/0013-sim-erc32-Fix-a-few-compiler-warnings.patch
new file mode 100644
index 0000000..6e0fd1d
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0013-sim-erc32-Fix-a-few-compiler-warnings.patch
@@ -0,0 +1,72 @@
+From e254c756b852c82ee705ff42f921e6dd9ba509e6 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sun, 31 Aug 2014 23:31:52 +0200
+Subject: [PATCH 13/23] sim/erc32: Fix a few compiler warnings
+
+ * func.c Minor edits to remove compiler warnings.
+ * func.c, sis.h (exec_cmd) make second argument const char.
+---
+ sim/erc32/func.c | 9 ++++++---
+ sim/erc32/sis.h | 3 +--
+ 2 files changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index ab21e3c..70b42c9 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -380,18 +380,19 @@ limcalc (freq)
+
+ int
+ exec_cmd(sregs, cmd)
+- char *cmd;
++ const char *cmd;
+ struct pstate *sregs;
+ {
+ char *cmd1, *cmd2;
+ int32 stat;
+ uint32 len, i, clen, j, tmp;
+ static uint32 daddr = 0;
+- char *cmdsave;
++ char *cmdsave, *cmdsave2 = NULL;
+
+ stat = OK;
+ cmdsave = strdup(cmd);
+- if ((cmd1 = strtok(cmd, " \t")) != NULL) {
++ cmdsave2 = strdup(cmd);
++ if ((cmd1 = strtok(cmdsave2, " \t")) != NULL) {
+ clen = strlen(cmd1);
+ if (strncmp(cmd1, "bp", clen) == 0) {
+ for (i = 0; i < sregs->bptnum; i++) {
+@@ -606,6 +607,8 @@ exec_cmd(sregs, cmd)
+ } else
+ printf("syntax error\n");
+ }
++ if (cmdsave2 != NULL)
++ free(cmdsave2);
+ if (cmdsave != NULL)
+ free(cmdsave);
+ return (stat);
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index fb733de..4ecf885 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -191,7 +191,7 @@ extern struct pstate sregs;
+ extern void set_regi (struct pstate *sregs, int32 reg,
+ uint32 rval);
+ extern void get_regi (struct pstate *sregs, int32 reg, char *buf);
+-extern int exec_cmd (struct pstate *sregs, char *cmd);
++extern int exec_cmd (struct pstate *sregs, const char *cmd);
+ extern void reset_stat (struct pstate *sregs);
+ extern void show_stat (struct pstate *sregs);
+ extern void init_bpt (struct pstate *sregs);
+@@ -209,7 +209,6 @@ extern int check_bpt (struct pstate *sregs);
+ extern void reset_all (void);
+ extern void sys_reset (void);
+ extern void sys_halt (void);
+-extern int bfd_load (char *fname);
+ extern double get_time (void);
+
+ /* exec.c */
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0014-sim-erc32-Use-gdb-callback-for-UART-I-O-when-linked-.patch b/tools/4.11/gdb/sparc/7.9/0014-sim-erc32-Use-gdb-callback-for-UART-I-O-when-linked-.patch
new file mode 100644
index 0000000..cddb450
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0014-sim-erc32-Use-gdb-callback-for-UART-I-O-when-linked-.patch
@@ -0,0 +1,358 @@
+From edd201819d2399e2a7dc87e328aa6c5cf3088104 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Wed, 18 Feb 2015 19:14:55 +0100
+Subject: [PATCH 14/23] sim/erc32: Use gdb callback for UART I/O when linked
+ with gdb.
+
+ Use the host_callback feature for printing when linked with gdb.
+---
+ sim/erc32/erc32.c | 97 +++++++++++++++++++++++++++++++++++++++++++++---------
+ sim/erc32/func.c | 2 ++
+ sim/erc32/interf.c | 5 +--
+ sim/erc32/sis.c | 2 ++
+ sim/erc32/sis.h | 4 ++-
+ 5 files changed, 92 insertions(+), 18 deletions(-)
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index 03b40dc..c1ee435 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -22,6 +22,7 @@
+ /* The control space devices */
+
+ #include "config.h"
++#include <errno.h>
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -39,6 +40,7 @@ extern int rom8,wrp,uben;
+ 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
+@@ -301,12 +303,15 @@ static void store_bytes (unsigned char *mem, uint32 waddr,
+
+ extern int ext_irl;
+
++static host_callback *callback;
++
+
+ /* One-time init */
+
+ void
+ init_sim()
+ {
++ callback = sim_callback;
+ port_init();
+ }
+
+@@ -944,10 +949,14 @@ init_stdio()
+ {
+ 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
+@@ -955,16 +964,18 @@ restore_stdio()
+ {
+ 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
+@@ -994,21 +1005,26 @@ port_init()
+ }
+ 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 && ofd1 == 1) setbuf(f1out, NULL);
++ if (!dumbio && tty_setup && ofd1 == 1) setbuf(f1out, NULL);
+ }
+
+ if (uart_dev2[0] != 0)
+@@ -1027,17 +1043,19 @@ port_init()
+ printf("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;
+@@ -1066,6 +1084,9 @@ read_uart(addr)
+ if (f1open) {
+ anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
+ }
++ else {
++ anum = 0;
++ }
+ if (anum > 0) {
+ aind = 0;
+ if ((aind + 1) < anum)
+@@ -1098,6 +1119,9 @@ read_uart(addr)
+ if (f2open) {
+ bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
+ }
++ else {
++ bnum = 0;
++ }
+ if (bnum > 0) {
+ bind = 0;
+ if ((bind + 1) < bnum)
+@@ -1130,6 +1154,9 @@ read_uart(addr)
+ if (f1open) {
+ anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
+ }
++ else {
++ anum = 0;
++ }
+ if (anum > 0) {
+ Ucontrol |= 0x00000001;
+ aind = 0;
+@@ -1142,6 +1169,9 @@ read_uart(addr)
+ if (f2open) {
+ bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
+ }
++ else {
++ bnum = 0;
++ }
+ if (bnum > 0) {
+ Ucontrol |= 0x00010000;
+ bind = 0;
+@@ -1182,8 +1212,12 @@ write_uart(addr, data)
+ 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;
+ }
+ }
+@@ -1206,8 +1240,12 @@ write_uart(addr, data)
+ 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;
+ }
+ }
+@@ -1245,19 +1283,37 @@ write_uart(addr, data)
+ 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 {
+@@ -1271,7 +1327,14 @@ uarta_tx()
+ 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 {
+@@ -1293,6 +1356,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)
+@@ -1309,6 +1374,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 70b42c9..440bff1 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -52,6 +52,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 981aa11..004d0bb 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -61,8 +61,6 @@ extern char uart_dev1[], uart_dev2[];
+
+ int sis_gdb_break = 1;
+
+-host_callback *sim_callback;
+-
+ int
+ run_sim(sregs, icount, dis)
+ struct pstate *sregs;
+@@ -209,6 +207,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 e109874..1f834a0 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -211,6 +211,8 @@ main(argc, argv)
+ #endif
+ } else if (strcmp(argv[stat], "-dumbio") == 0) {
+ dumbio = 1;
++ } else if (strcmp(argv[stat], "-nouartrx") == 0) {
++ nouartrx = 1;
+ } else if (strcmp(argv[stat], "-v") == 0) {
+ sis_verbose += 1;
+ } else {
+diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
+index 4ecf885..5226666 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -169,7 +169,7 @@ struct irqcell {
+ /* 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);
+@@ -210,6 +210,8 @@ extern void reset_all (void);
+ extern void sys_reset (void);
+ extern void sys_halt (void);
+ extern double get_time (void);
++extern int nouartrx;
++extern host_callback *sim_callback;
+
+ /* exec.c */
+ extern int dispatch_instruction (struct pstate *sregs);
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0015-sim-erc32-Access-memory-subsystem-through-struct-mem.patch b/tools/4.11/gdb/sparc/7.9/0015-sim-erc32-Access-memory-subsystem-through-struct-mem.patch
new file mode 100644
index 0000000..c925b22
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0015-sim-erc32-Access-memory-subsystem-through-struct-mem.patch
@@ -0,0 +1,804 @@
+From 02c87814c10d896ae4946ef7c0358448b4d4eb61 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Wed, 18 Feb 2015 21:48:10 +0100
+Subject: [PATCH 15/23] 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 : Export memory operations through struct memsys erc32sys.
+ * exec.c (dispatch_instruction) Access memory through common API.
+ * func.c, interf.c, sis.c : As above.
+ * sis.h : Define struct memsys as common memory API
+---
+ sim/erc32/erc32.c | 54 ++++++++++++++++++++++++++++--------------------------
+ sim/erc32/exec.c | 42 +++++++++++++++++++++---------------------
+ sim/erc32/func.c | 37 +++++++++++++++++++++----------------
+ sim/erc32/interf.c | 39 +++++++++++++++++++++------------------
+ sim/erc32/sis.c | 15 ++++++---------
+ sim/erc32/sis.h | 46 ++++++++++++++++++++++++++++------------------
+ 6 files changed, 125 insertions(+), 108 deletions(-)
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index c1ee435..d0cacf9 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -39,8 +39,7 @@ 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 */
+-int tty_setup = 1; /* default setup if not a tty */
++static int tty_setup = 1; /* default setup if not a tty */
+
+ /* MEC registers */
+ #define MEC_START 0x01f80000
+@@ -56,11 +55,6 @@ int tty_setup = 1; /* default setup if not a tty */
+ extern int errmec;
+ #endif
+
+-/* The target's byte order is big-endian by default until we load a
+- little-endian program. */
+-
+-int current_target_byte_order = BIG_ENDIAN;
+-
+ #define MEC_WS 0 /* Waitstates per MEC access (0 ws) */
+ #define MOK 0
+
+@@ -308,7 +302,7 @@ static host_callback *callback;
+
+ /* One-time init */
+
+-void
++static void
+ init_sim()
+ {
+ callback = sim_callback;
+@@ -317,7 +311,7 @@ init_sim()
+
+ /* Power-on reset init */
+
+-void
++static void
+ reset()
+ {
+ mec_reset();
+@@ -397,7 +391,7 @@ mecparerror()
+
+ /* IU error mode manager */
+
+-void
++static void
+ error_mode(pc)
+ uint32 pc;
+ {
+@@ -468,7 +462,7 @@ decode_mcr()
+
+ /* Flush ports when simulator stops */
+
+-void
++static void
+ sim_halt()
+ {
+ #ifdef FAST_UART
+@@ -476,13 +470,6 @@ sim_halt()
+ #endif
+ }
+
+-int
+-sim_stop(SIM_DESC sd)
+-{
+- ctrl_c = 1;
+- return 1;
+-}
+-
+ static void
+ close_port()
+ {
+@@ -492,7 +479,7 @@ close_port()
+ fclose(f2in);
+ }
+
+-void
++static void
+ exit_sim()
+ {
+ close_port();
+@@ -944,7 +931,7 @@ mec_write(addr, data)
+
+ static int ifd1 = -1, ifd2 = -1, ofd1 = -1, ofd2 = -1;
+
+-void
++static void
+ init_stdio()
+ {
+ if (dumbio)
+@@ -959,7 +946,7 @@ init_stdio()
+ }
+ }
+
+-void
++static void
+ restore_stdio()
+ {
+ if (dumbio)
+@@ -1632,7 +1619,7 @@ store_bytes (mem, waddr, data, sz, ws)
+
+ /* Memory emulation */
+
+-int
++static int
+ memory_iread(addr, data, ws)
+ uint32 addr;
+ uint32 *data;
+@@ -1656,7 +1643,7 @@ memory_iread(addr, data, ws)
+ return (1);
+ }
+
+-int
++static int
+ memory_read(asi, addr, data, sz, ws)
+ int32 asi;
+ uint32 addr;
+@@ -1727,7 +1714,7 @@ memory_read(asi, addr, data, sz, ws)
+ return (1);
+ }
+
+-int
++static int
+ memory_write(asi, addr, data, sz, ws)
+ int32 asi;
+ uint32 addr;
+@@ -1863,7 +1850,7 @@ get_mem_ptr(addr, size)
+ return ((char *) -1);
+ }
+
+-int
++static int
+ sis_memory_write(addr, data, length)
+ uint32 addr;
+ const unsigned char *data;
+@@ -1878,7 +1865,7 @@ sis_memory_write(addr, data, length)
+ return (length);
+ }
+
+-int
++static int
+ sis_memory_read(addr, data, length)
+ uint32 addr;
+ char *data;
+@@ -1908,3 +1895,18 @@ boot_init (void)
+ sregs.r[14] = sregs.r[30] - 96*4;
+ mec_mcr |= 1; /* power-down enabled */
+ }
++
++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 237bb53..65e10bf 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -1244,9 +1244,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) {
+@@ -1267,7 +1267,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;
+@@ -1278,7 +1278,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) {
+@@ -1288,7 +1288,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;
+@@ -1302,7 +1302,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;
+@@ -1323,7 +1323,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;
+@@ -1349,7 +1349,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 +
+@@ -1375,9 +1375,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) {
+@@ -1406,7 +1406,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;
+@@ -1428,7 +1428,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;
+@@ -1442,7 +1442,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;
+@@ -1451,7 +1451,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;
+@@ -1471,7 +1471,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
+@@ -1500,7 +1500,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
+@@ -1521,7 +1521,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;
+@@ -1540,7 +1540,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;
+@@ -1560,7 +1560,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
+@@ -1577,13 +1577,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 440bff1..e789099 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -33,7 +33,11 @@
+
+ #define VAL(x) strtoul(x,(char **)NULL,0)
+
+-extern int current_target_byte_order;
++/* The target's byte order is big-endian by default until we load a
++ little-endian program. */
++int current_target_byte_order = BIG_ENDIAN;
++
++int dumbio = 0; /* normal, smart, terminal oriented IO by default */
+ struct disassemble_info dinfo;
+ struct pstate sregs;
+ extern struct estate ebase;
+@@ -54,6 +58,7 @@ extern int ext_irl;
+ uint32 last_load_addr = 0;
+ int nouartrx = 0;
+ host_callback *sim_callback;
++struct memsys *ms = &erc32sys;
+
+ #ifdef ERRINJ
+ uint32 errcnt = 0;
+@@ -432,7 +437,7 @@ exec_cmd(sregs, 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);
+@@ -483,7 +488,7 @@ exec_cmd(sregs, 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) {
+@@ -557,7 +562,7 @@ exec_cmd(sregs, 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) {
+ tmp = system(&cmdsave[clen]);
+@@ -565,12 +570,12 @@ exec_cmd(sregs, 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;
+@@ -583,7 +588,7 @@ exec_cmd(sregs, 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)
+@@ -597,7 +602,7 @@ exec_cmd(sregs, cmd)
+ }
+ printf("\n");
+ daddr = sregs->pc;
+- sim_halt();
++ ms->sim_halt();
+ } else if (strncmp(cmd1, "trun", clen) == 0) {
+ ebase.simtime = 0;
+ reset_all();
+@@ -605,7 +610,7 @@ exec_cmd(sregs, 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");
+ }
+@@ -777,7 +782,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;
+@@ -793,10 +798,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)
+@@ -825,7 +830,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, 4);
++ ms->sis_memory_read((i + (j * 4)), data, 4);
+ printf("%08x ", *wdata);
+ mem[j] = *((int *) &data);
+ }
+@@ -852,7 +857,7 @@ dis_mem(addr, len, info)
+ uint32 *wdata = (uint32 *) data;
+
+ for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) {
+- sis_memory_read(i, data, 4);
++ ms->sis_memory_read(i, data, 4);
+ printf(" %08x %08x ", i, *wdata);
+ print_insn_sparc_sis(i, info);
+ if (i >= 0xfffffffc) break;
+@@ -1016,7 +1021,7 @@ reset_all()
+ {
+ init_event(); /* Clear event queue */
+ init_regs(&sregs);
+- reset();
++ ms->reset();
+ #ifdef ERRINJ
+ errinjstart();
+ #endif
+@@ -1137,7 +1142,7 @@ bfd_load(fname)
+ #ifdef HOST_LITTLE_ENDIAN
+ for (i=0;i<count/4;i++) wbuffer[i] = ntohl(wbuffer[i]); // endian swap
+ #endif
+- sis_memory_write(section_address, buffer, count);
++ ms->sis_memory_write(section_address, buffer, count);
+
+ section_address += count;
+ fptr += count;
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 004d0bb..3f937f3 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -37,17 +37,13 @@
+ #define PSR_CWP 0x7
+
+ extern struct disassemble_info dinfo;
+-extern struct pstate sregs;
+ extern struct estate ebase;
+
+-extern int current_target_byte_order;
+-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[];
+@@ -72,7 +68,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)) boot_init();
+@@ -92,7 +88,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",
+@@ -118,8 +114,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
+@@ -137,12 +133,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) {
+@@ -272,7 +268,7 @@ sim_open (kind, callback, abfd, argv)
+ #endif
+ reset_all();
+ ebase.simtime = 0;
+- init_sim();
++ ms->init_sim();
+ init_bpt(&sregs);
+ reset_stat(&sregs);
+
+@@ -286,7 +282,7 @@ sim_close(sd, quitting)
+ int quitting;
+ {
+
+- exit_sim();
++ ms->exit_sim();
+ fcntl(0, F_SETFL, termsave);
+
+ };
+@@ -368,9 +364,9 @@ sim_write(sd, mem, buf, length)
+ for (i=0; i<length; i+=4) {
+ ibuf[i] = ntohl(ibufp[i]);
+ }
+- return (sis_memory_write(mem, (char *) ibuf, length));
++ return (ms->sis_memory_write(mem, (char *) ibuf, length));
+ #else
+- return (sis_memory_write(mem, buf, length));
++ return (ms->sis_memory_write(mem, buf, length));
+ #endif
+ }
+
+@@ -385,7 +381,7 @@ sim_read(sd, mem, buf, length)
+ int *ibuf = (int *) buf;
+ int i, len;
+
+- len = sis_memory_read(mem, buf, length);
++ len = ms->sis_memory_read(mem, buf, length);
+ if (length >= 4)
+ for (i=0; i<length; i+=4) {
+ *ibuf = htonl(*ibuf);
+@@ -393,7 +389,7 @@ sim_read(sd, mem, buf, length)
+ }
+ return (len);
+ #else
+- return (sis_memory_read(mem, buf, length));
++ return (ms->sis_memory_read(mem, buf, length));
+ #endif
+ }
+
+@@ -480,7 +476,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)
+@@ -519,6 +515,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 1f834a0..8c89166 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -52,16 +52,13 @@ extern HIST_ENTRY *remove_history (int which);
+ #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[];
+@@ -87,13 +84,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;
+@@ -108,7 +105,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) {
+@@ -131,7 +128,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;
+ }
+ }
+@@ -143,7 +140,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) {
+@@ -246,7 +243,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 5226666..e0390e6 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -169,25 +169,12 @@ struct irqcell {
+ /* Prototypes */
+
+ /* erc32.c */
+-extern void init_sim ();
+-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 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);
+@@ -211,7 +198,9 @@ extern void sys_reset (void);
+ extern void sys_halt (void);
+ extern double get_time (void);
+ extern int nouartrx;
+-extern host_callback *sim_callback;
++extern host_callback *sim_callback;
++extern int current_target_byte_order;
++extern int dumbio;
+
+ /* exec.c */
+ extern int dispatch_instruction (struct pstate *sregs);
+@@ -231,3 +220,24 @@ extern void set_fsr (uint32 fsr);
+ /* help.c */
+ extern void usage (void);
+ extern void gen_help (void);
++
++struct memsys {
++ void (*init_sim) ();
++ 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 struct memsys *ms;
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0016-sim-erc32-Use-readline.h-for-readline-types-and-func.patch b/tools/4.11/gdb/sparc/7.9/0016-sim-erc32-Use-readline.h-for-readline-types-and-func.patch
new file mode 100644
index 0000000..a21bd14
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0016-sim-erc32-Use-readline.h-for-readline-types-and-func.patch
@@ -0,0 +1,55 @@
+From 8907865aa0256164fd732c795ce8c9c3c42621a8 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 18 Oct 2014 23:38:02 +0200
+Subject: [PATCH 16/23] sim/erc32: Use readline.h for readline types and
+ functions.
+
+ Use gdb's readline.h for readline types.
+
+ * Makefile.in : Add include path to readline.h
+ sis.c : Remove locally define readline types.
+---
+ sim/erc32/Makefile.in | 2 +-
+ sim/erc32/sis.c | 13 ++-----------
+ 2 files changed, 3 insertions(+), 12 deletions(-)
+
+diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
+index e0860a0..4f86017 100644
+--- a/sim/erc32/Makefile.in
++++ b/sim/erc32/Makefile.in
+@@ -30,7 +30,7 @@ SIM_EXTRA_CLEAN = clean-sis
+ # UARTS run at about 115200 baud (simulator time). Add -DFAST_UART to
+ # CFLAGS if faster (infinite) UART speed is desired. Might affect the
+ # behaviour of UART interrupt routines ...
+-SIM_EXTRA_CFLAGS = -DFAST_UART
++SIM_EXTRA_CFLAGS = -DFAST_UART -I$(srcroot)
+
+ ## COMMON_POST_CONFIG_FRAG
+
+diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
+index 8c89166..79757ae 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -36,17 +36,8 @@
+
+ /* Structures and functions from readline library */
+
+-typedef struct {
+- char *line;
+- char *data;
+-} HIST_ENTRY;
+-
+-extern char * readline (char *prompt);
+-extern void using_history (void);
+-extern void add_history (char *string);
+-extern HIST_ENTRY *remove_history (int which);
+-
+-
++#include "readline/readline.h"
++#include "readline/history.h"
+
+ /* Command history buffer length - MUST be binary */
+ #define HIST_LEN 64
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0017-sim-erc32-Move-local-extern-declarations-into-sis.h.patch b/tools/4.11/gdb/sparc/7.9/0017-sim-erc32-Move-local-extern-declarations-into-sis.h.patch
new file mode 100644
index 0000000..efd6636
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0017-sim-erc32-Move-local-extern-declarations-into-sis.h.patch
@@ -0,0 +1,224 @@
+From 82bbac32bcd1c2c65930f13daa9de7b327c310ea Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Wed, 18 Feb 2015 21:58:00 +0100
+Subject: [PATCH 17/23] sim/erc32: Move local extern declarations into sis.h
+
+ * erc32.c : Move extern declarations to sis.h
+ * exec.c, func.c, interf.c, sis.c : As above.
+---
+ sim/erc32/erc32.c | 10 ----------
+ sim/erc32/exec.c | 7 -------
+ sim/erc32/func.c | 12 ++++--------
+ sim/erc32/interf.c | 19 -------------------
+ sim/erc32/sis.c | 20 --------------------
+ sim/erc32/sis.h | 20 ++++++++++++++++++++
+ 6 files changed, 24 insertions(+), 64 deletions(-)
+
+diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
+index d0cacf9..89c745a 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -33,12 +33,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[];
+-
+ static int tty_setup = 1; /* default setup if not a tty */
+
+ /* MEC registers */
+@@ -295,8 +289,6 @@ static unsigned char *
+ static void store_bytes (unsigned char *mem, uint32 waddr,
+ uint32 *data, int sz, int32 *ws);
+
+-extern int ext_irl;
+-
+ static host_callback *callback;
+
+
+@@ -1880,8 +1872,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 65e10bf..6d80306 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -24,7 +24,6 @@
+ #include <math.h>
+ #include <stdio.h>
+
+-extern int32 sis_verbose, sparclite;
+ int ext_irl = 0;
+
+ /* Load/store interlock delay */
+@@ -228,10 +227,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
+@@ -2017,8 +2012,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 e789099..0d00f48 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -40,7 +40,10 @@ int current_target_byte_order = BIG_ENDIAN;
+ int dumbio = 0; /* normal, smart, terminal oriented IO by default */
+ 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";
+@@ -54,7 +57,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;
+@@ -727,12 +729,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 3f937f3..ab1a38c 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -36,25 +36,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 dumbio;
+-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 79757ae..d833da3 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -42,26 +42,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 e0390e6..8a48f29 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -173,8 +173,27 @@ extern 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 int dumbio;
++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);
+@@ -185,6 +204,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);
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0018-sim-erc32-Add-support-for-LEON3-processor-emulation.patch b/tools/4.11/gdb/sparc/7.9/0018-sim-erc32-Add-support-for-LEON3-processor-emulation.patch
new file mode 100644
index 0000000..8a20bff
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0018-sim-erc32-Add-support-for-LEON3-processor-emulation.patch
@@ -0,0 +1,2434 @@
+From d3e77f683adc96e3fc8395f21b8e440ee923a092 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Wed, 18 Feb 2015 22:47:49 +0100
+Subject: [PATCH 18/23] sim/erc32: 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.
+---
+ sim/erc32/Makefile.in | 4 +-
+ sim/erc32/README.leon3 | 53 +++
+ sim/erc32/README.sis | 81 ++--
+ sim/erc32/erc32.c | 48 ++-
+ sim/erc32/exec.c | 228 +++++++++--
+ sim/erc32/func.c | 57 +--
+ sim/erc32/grlib.c | 98 +++++
+ sim/erc32/grlib.h | 57 +++
+ sim/erc32/interf.c | 26 +-
+ sim/erc32/leon3.c | 1066 ++++++++++++++++++++++++++++++++++++++++++++++++
+ sim/erc32/sis.c | 22 +-
+ sim/erc32/sis.h | 49 ++-
+ 12 files changed, 1660 insertions(+), 129 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 4f86017..e40eb79 100644
+--- a/sim/erc32/Makefile.in
++++ b/sim/erc32/Makefile.in
+@@ -21,7 +21,7 @@
+ TERMCAP_LIB = @TERMCAP@
+ READLINE_LIB = @READLINE@
+
+-SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o
++SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o leon3.o grlib.o
+ SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
+ SIM_EXTRA_ALL = sis
+ SIM_EXTRA_INSTALL = install-sis
+@@ -35,7 +35,7 @@ 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_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o
+
+ sis: sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) -o sis \
+diff --git a/sim/erc32/README.leon3 b/sim/erc32/README.leon3
+new file mode 100644
+index 0000000..f6701a5
+--- /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 implemeted:
++
++- 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..124e577 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
+
+@@ -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 true, 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 89c745a..0e1a2ed 100644
+--- a/sim/erc32/erc32.c
++++ b/sim/erc32/erc32.c
+@@ -1636,19 +1636,20 @@ memory_iread(addr, data, ws)
+ }
+
+ static int
+-memory_read(asi, addr, data, sz, ws)
+- int32 asi;
++memory_read(addr, data, sz, ws)
+ 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);
++ if (sregs.psr & 0x080) asi = 11; else asi = 10;
+ set_sfsr(errmec, addr, asi, 1);
+ if (errmec == 5) mecparerror();
+ if (errmec == 6) iucomperr();
+@@ -1662,6 +1663,7 @@ memory_read(asi, addr, data, sz, ws)
+ *ws = mem_ramr_ws;
+ return (0);
+ } else if ((addr >= MEC_START) && (addr < MEC_END)) {
++ if (sregs.psr & 0x080) asi = 11; else asi = 10;
+ mexc = mec_read(addr, asi, data);
+ if (mexc) {
+ set_sfsr(MEC_ACC, addr, asi, 1);
+@@ -1701,19 +1703,30 @@ memory_read(asi, addr, data, sz, ws)
+ }
+
+ printf("Memory exception at %x (illegal address)\n", addr);
++ if (sregs.psr & 0x080) asi = 11; else asi = 10;
+ set_sfsr(UIMP_ACC, addr, asi, 1);
+ *ws = MEM_EX_WS;
+ return (1);
+ }
+
+ static int
+-memory_write(asi, addr, data, sz, ws)
++memory_read_asi(asi, addr, data, sz, ws)
+ int32 asi;
+ uint32 addr;
+ uint32 *data;
+ int32 sz;
+ int32 *ws;
+ {
++ return(memory_read(addr, data, sz, ws));
++}
++
++static int
++memory_write(addr, data, sz, ws)
++ uint32 addr;
++ uint32 *data;
++ int32 sz;
++ int32 *ws;
++{
+ uint32 byte_addr;
+ uint32 byte_mask;
+ uint32 waddr;
+@@ -1721,11 +1734,13 @@ memory_write(asi, addr, data, sz, ws)
+ int32 mexc;
+ int i;
+ int wphit[2];
++ int32 asi;
+
+ #ifdef ERRINJ
+ if (errmec) {
+ if (sis_verbose)
+ printf("Inserted MEC error %d\n",errmec);
++ if (sregs.psr & 0x080) asi = 11; else asi = 10;
+ set_sfsr(errmec, addr, asi, 0);
+ if (errmec == 5) mecparerror();
+ if (errmec == 6) iucomperr();
+@@ -1738,6 +1753,7 @@ memory_write(asi, addr, data, sz, ws)
+ if (mem_accprot) {
+
+ waddr = (addr & 0x7fffff) >> 2;
++ if (sregs.psr & 0x080) asi = 11; else asi = 10;
+ for (i = 0; i < 2; i++)
+ wphit[i] =
+ (((asi == 0xa) && (mec_wpr[i] & 1)) ||
+@@ -1761,6 +1777,7 @@ memory_write(asi, addr, data, sz, ws)
+ return (0);
+
+ } else if ((addr >= MEC_START) && (addr < MEC_END)) {
++ if (sregs.psr & 0x080) asi = 11; else asi = 10;
+ if ((sz != 2) || (asi != 0xb)) {
+ set_sfsr(MEC_ACC, addr, asi, 0);
+ *ws = MEM_EX_WS;
+@@ -1817,10 +1834,22 @@ memory_write(asi, addr, data, sz, ws)
+ }
+
+ *ws = MEM_EX_WS;
++ if (sregs.psr & 0x080) asi = 11; else asi = 10;
+ set_sfsr(UIMP_ACC, addr, asi, 0);
+ return (1);
+ }
+
++static int
++memory_write_asi(asi, addr, data, sz, ws)
++ 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;
+@@ -1864,6 +1893,12 @@ sis_memory_read(addr, data, length)
+ uint32 length;
+ {
+ char *mem;
++ int ws;
++
++ if (length == 4) {
++ memory_read(addr, data, length, &ws);
++ return(4);
++ }
+
+ if ((mem = get_mem_ptr(addr, length)) == ((char *) -1))
+ return (0);
+@@ -1872,7 +1907,7 @@ sis_memory_read(addr, data, length)
+ return (length);
+ }
+
+-void
++static void
+ boot_init (void)
+ {
+ mec_write(MEC_WCR, 0); /* zero waitstates */
+@@ -1896,7 +1931,10 @@ 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 6d80306..6292998 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -1065,17 +1065,17 @@ 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;
+@@ -1121,13 +1121,19 @@ 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 if ( 17 == rd ) {
++ if (sparclite)
++ sregs->asr17 = (rs1 ^ operand2);
++ }
++ else if ( 19 == rd ) {
++ if (cputype == CPU_LEON3)
++ wait_for_irq();
++ }
+ else {
+ sregs->trap = TRAP_UNIMP;
+ break;
+@@ -1227,6 +1233,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;
+@@ -1239,9 +1271,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) {
+@@ -1257,12 +1289,24 @@ 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;
+@@ -1272,8 +1316,27 @@ 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) {
+@@ -1283,7 +1346,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;
+@@ -1295,9 +1358,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;
+@@ -1312,13 +1387,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;
+@@ -1344,7 +1435,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 +
+@@ -1370,9 +1461,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) {
+@@ -1401,7 +1492,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;
+@@ -1423,7 +1514,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;
+@@ -1432,12 +1523,22 @@ 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;
+@@ -1445,8 +1546,14 @@ 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;
+@@ -1454,6 +1561,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;
+@@ -1466,7 +1595,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
+@@ -1495,7 +1624,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
+@@ -1511,12 +1640,22 @@ 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;
+@@ -1535,7 +1674,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;
+@@ -1555,7 +1694,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
+@@ -1567,18 +1706,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) {
+@@ -1814,7 +1975,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;
+@@ -1996,7 +2157,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;
+@@ -2043,7 +2204,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;
+@@ -2072,4 +2236,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 0d00f48..a22e800 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -46,7 +46,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;
+@@ -61,6 +61,7 @@ uint32 last_load_addr = 0;
+ int nouartrx = 0;
+ host_callback *sim_callback;
+ struct memsys *ms = &erc32sys;
++int cputype = 0; /* 0 = erc32, 3 = leon3 */
+
+ #ifdef ERRINJ
+ uint32 errcnt = 0;
+@@ -482,7 +483,7 @@ exec_cmd(sregs, 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);
+@@ -558,6 +559,11 @@ exec_cmd(sregs, 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 {
+@@ -609,6 +615,11 @@ exec_cmd(sregs, 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;
+@@ -646,8 +657,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;
+@@ -662,37 +673,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..edb304e
+--- /dev/null
++++ b/sim/erc32/grlib.c
+@@ -0,0 +1,98 @@
++/*
++ * 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..1c03329
+--- /dev/null
++++ b/sim/erc32/grlib.h
+@@ -0,0 +1,57 @@
++/*
++ * 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
++
++int grlib_apbpp_add(uint32 id, uint32 addr);
++int grlib_ahbmpp_add(uint32 id);
++int grlib_ahbspp_add(uint32 id, uint32 addr1, uint32 addr2,
++ uint32 addr3, uint32 addr4);
++uint32 grlib_ahbpnp_read(uint32 addr);
++uint32 grlib_apbpnp_read(uint32 addr);
++void grlib_init();
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index ab1a38c..8f3b27d 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -52,7 +52,7 @@ run_sim(sregs, icount, dis)
+ ms->init_stdio();
+ sregs->starttime = get_time();
+ irq = 0;
+- if ((sregs->pc != 0) && (ebase.simtime == 0)) boot_init();
++ if ((sregs->pc != 0) && (ebase.simtime == 0)) ms->boot_init();
+ while (!sregs->err_mode & (icount > 0)) {
+
+ sregs->fhold = 0;
+@@ -187,6 +187,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
+@@ -224,9 +228,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@wd.estec.esa.nl)\n");
++ (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jiri@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)
+@@ -235,11 +251,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
+@@ -457,7 +471,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..26ea2b2
+--- /dev/null
++++ b/sim/erc32/leon3.c
+@@ -0,0 +1,1066 @@
++/*
++ * 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"
++
++static int tty_setup = 1; /* default setup if not a tty */
++
++/* 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 */
++
++static int32 fd1, fd2; /* file descriptor for input file */
++static int32 Ucontrol; /* UART status register */
++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()
++{
++ callback = sim_callback;
++ grlib_init();
++ mem_init();
++ port_init();
++ gpt_init();
++}
++
++/* Power-on reset init */
++
++static void
++reset()
++{
++ leon3_reset();
++ uart_irq_start();
++ gpt_reset();
++}
++
++/* IU error mode manager */
++
++static void
++error_mode(pc)
++ uint32 pc;
++{
++
++}
++
++
++/* Memory init */
++
++static void
++mem_init()
++{
++
++/* 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()
++{
++#ifdef FAST_UART
++ flush_uart();
++#endif
++}
++
++static void
++close_port()
++{
++ if (f1open && f1in != stdin)
++ fclose(f1in);
++}
++
++static void
++exit_sim()
++{
++ close_port();
++}
++
++static void
++leon3_reset()
++{
++ 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(level)
++ 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()
++{
++ 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(level)
++ int32 level;
++{
++ irqmp_ipr |= (1 << level);
++ chk_irq();
++}
++
++static int32
++apb_read(addr, data)
++ 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(addr, data)
++ 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()
++{
++ if (dumbio)
++ return; /* do nothing */
++ if (ifd1 == 0 && f1open) {
++ tcsetattr(0, TCSANOW, &ioc1);
++ tcflush(ifd1, TCIFLUSH);
++ }
++}
++
++static void
++restore_stdio()
++{
++ if (dumbio)
++ return; /* do nothing */
++ 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()
++{
++
++ 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(addr)
++ uint32 addr;
++{
++
++ unsigned tmp;
++
++ 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 MEC register (%x)\n", addr);
++
++ }
++ return (0);
++}
++
++static void
++grlib_write_uart(addr, data)
++ 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 APB register (%x)\n", addr);
++
++ }
++}
++
++static void
++flush_uart()
++{
++ 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()
++{
++ 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 {
++ uarta_sreg = uarta_hreg;
++ uart_stat_reg |= UARTA_HRE;
++ event(uarta_tx, 0, UART_TX_TIME);
++ }
++ set_irq(3);
++}
++
++static void
++uart_rx(arg)
++ caddr_t arg;
++{
++ int32 rsize;
++ char rxd;
++
++
++ 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(arg)
++ caddr_t arg;
++{
++ grlib_read_uart(APBUART_STATUS); /* Check for UART interrupts every 1000 clk */
++ flush_uart(); /* Flush UART ports */
++ event(uart_intr, 0, UART_FLUSH_TIME);
++}
++
++
++static void
++uart_irq_start()
++{
++#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(arg)
++ 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()
++{
++ 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()
++{
++ event(gpt_intr, 0, gpt_scaler + 1);
++ gpt_scaler_start = now();
++}
++
++static void
++gpt_scaler_set(val)
++ uint32 val;
++{
++ gpt_scaler = val & 0x0ffff; /* 16-bit scaler */
++}
++
++static void
++timer_ctrl(val, i)
++ 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 (mem, waddr, data, sz, ws)
++ unsigned char *mem;
++ uint32 waddr;
++ uint32 *data;
++ int32 sz;
++ int32 *ws;
++{
++ switch (sz) {
++ case 0:
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= 3;
++#endif
++ mem[waddr] = *data & 0x0ff;
++ *ws = 0;
++ break;
++ case 1:
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= 2;
++#endif
++ *((unsigned short *) &(mem[waddr])) = *data & 0x0ffff;
++ *ws = 0;
++ break;
++ case 2:
++ *((uint32 *) &(mem[waddr])) = *data;
++ *ws = 0;
++ break;
++ case 3:
++ *((uint32 *) &(mem[waddr])) = data[0];
++ *((uint32 *) &(mem[waddr + 4])) = data[1];
++ *ws = 0;
++ break;
++ }
++}
++
++
++/* Memory emulation */
++
++static int
++memory_iread(addr, data, ws)
++ uint32 addr;
++ uint32 *data;
++ int32 *ws;
++{
++ if ((addr >= RAM_START) && (addr < RAM_END)) {
++ *data = *((uint32 *) & (ramb[addr & RAM_MASK]));
++ *ws = 0;
++ return (0);
++ } else if (addr < ROM_END) {
++ *data = *((uint32 *) & (romb[addr]));
++ *ws = 0;
++ return (0);
++ }
++
++ printf("Memory exception at %x (illegal address)\n", addr);
++ *ws = MEM_EX_WS;
++ return (1);
++}
++
++static int
++memory_read(addr, data, sz, ws)
++ uint32 addr;
++ uint32 *data;
++ int32 sz;
++ int32 *ws;
++{
++ int32 mexc;
++
++ if ((addr >= RAM_START) && (addr < RAM_END)) {
++ *data = *((uint32 *) & (ramb[addr & RAM_MASK & ~3]));
++ *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) {
++ *data = *((uint32 *) & (romb[addr & ~3]));
++ *ws = 0;
++ return (0);
++ }
++
++ printf("Memory exception at %x (illegal address)\n", addr);
++ *ws = MEM_EX_WS;
++ return (1);
++}
++
++static int
++memory_read_asi(asi, addr, data, sz, ws)
++ 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(addr, data, sz, ws)
++ 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) {
++// return (1);
++ *ws = 0;
++ store_bytes (romb, addr, data, sz, ws);
++ return (0);
++ }
++
++ *ws = MEM_EX_WS;
++ return (1);
++}
++
++static int
++memory_write_asi(asi, addr, data, sz, ws)
++ 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(addr, size)
++ 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(addr, data, length)
++ 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(addr, data, length)
++ uint32 addr;
++ char *data;
++ uint32 length;
++{
++ char *mem;
++ int ws;
++
++ if (length == 4) {
++ memory_read(addr, 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 ()
++{
++// mec_write(MEC_WCR, 0); /* zero waitstates */
++// mec_write(MEC_TRAPD, 0); /* turn off watch-dog */
++ apb_write(GPTIMER_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
++ apb_write(GPTIMER_SCLOAD, sregs.freq-1);
++ apb_write(GPTIMER_TIMER1, -1);
++ apb_write(GPTIMER_RELOAD1, -1);
++ apb_write(GPTIMER_CTRL1, 0x7);
++// mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
++ sregs.wim = 2;
++ sregs.psr = 0xF30010e0;
++ sregs.r[30] = RAM_END;
++ sregs.r[14] = sregs.r[30] - 96*4;
++ cache_ctrl = 0x81000f;
++}
++
++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 d833da3..0e19270 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -142,7 +142,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@wd.estec.esa.nl\n\n");
++ printf(" Bug-reports to jiri@gaisler.se\n\n");
+ while (stat < argc) {
+ if (argv[stat][0] == '-') {
+ if (strcmp(argv[stat], "-v") == 0) {
+@@ -181,6 +181,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 if (strcmp(argv[stat], "-v") == 0) {
+ sis_verbose += 1;
+ } else {
+@@ -193,13 +197,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 8a48f29..a551b4a 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -159,6 +159,30 @@ struct irqcell {
+ int32 arg;
+ };
+
++struct memsys {
++ void (*init_sim) ();
++ 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) (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 (*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);
++};
++
+
+ #define OK 0
+ #define TIME_OUT 1
+@@ -166,6 +190,8 @@ struct irqcell {
+ #define ERROR 3
+ #define CTRL_C 4
+
++#define CPU_LEON3 3
++
+ /* Prototypes */
+
+ /* erc32.c */
+@@ -221,6 +247,7 @@ extern int nouartrx;
+ extern host_callback *sim_callback;
+ extern int current_target_byte_order;
+ extern int dumbio;
++extern int cputype;
+
+ /* exec.c */
+ extern int dispatch_instruction (struct pstate *sregs);
+@@ -241,23 +268,7 @@ extern void set_fsr (uint32 fsr);
+ extern void usage (void);
+ extern void gen_help (void);
+
+-struct memsys {
+- void (*init_sim) ();
+- 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 struct memsys *ms;
++
++/* leon3.c */
++extern struct memsys leon3;
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0019-sim-erc32-Add-support-for-LEON2-processor-emulation.patch b/tools/4.11/gdb/sparc/7.9/0019-sim-erc32-Add-support-for-LEON2-processor-emulation.patch
new file mode 100644
index 0000000..7076933
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0019-sim-erc32-Add-support-for-LEON2-processor-emulation.patch
@@ -0,0 +1,1188 @@
+From 2c2afb029df432bd32f72789944cec2717861f7e Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Wed, 18 Feb 2015 22:54:34 +0100
+Subject: [PATCH 19/23] 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 leon3.c and modified to emulate the
+ LEON2 address space and peripheral operations.
+---
+ sim/erc32/Makefile.in | 4 +-
+ sim/erc32/exec.c | 3 +
+ sim/erc32/interf.c | 11 +-
+ sim/erc32/leon2.c | 1041 +++++++++++++++++++++++++++++++++++++++++++++++++
+ sim/erc32/sis.c | 7 +
+ sim/erc32/sis.h | 4 +
+ 6 files changed, 1066 insertions(+), 4 deletions(-)
+ create mode 100644 sim/erc32/leon2.c
+
+diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
+index e40eb79..bee357b 100644
+--- a/sim/erc32/Makefile.in
++++ b/sim/erc32/Makefile.in
+@@ -21,7 +21,7 @@
+ TERMCAP_LIB = @TERMCAP@
+ READLINE_LIB = @READLINE@
+
+-SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o leon3.o grlib.o
++SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o leon2.o leon3.o grlib.o
+ SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
+ SIM_EXTRA_ALL = sis
+ SIM_EXTRA_INSTALL = install-sis
+@@ -35,7 +35,7 @@ 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 grlib.o leon3.o
++SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon2.o leon3.o
+
+ sis: sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) -o sis \
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index 6292998..f4a0124 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -2207,6 +2207,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 8f3b27d..8988f23 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -187,6 +187,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;
+@@ -228,15 +232,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@gaisler.se)\n\n");
++ (*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler (jiri@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..cf86167
+--- /dev/null
++++ b/sim/erc32/leon2.c
+@@ -0,0 +1,1041 @@
++/*
++ * 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/>.
++ *
++ * Leon2 emulation, based on leon3.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 "sim-config.h"
++
++static int tty_setup = 1; /* default setup if not a tty */
++
++/* 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 */
++
++static int32 fd1, fd2; /* file descriptor for input file */
++static int32 Ucontrol; /* UART status register */
++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()
++{
++ callback = sim_callback;
++ grlib_init();
++ mem_init();
++ port_init();
++ gpt_init();
++}
++
++/* Power-on reset init */
++
++static void
++reset()
++{
++ leon2_reset();
++ uart_irq_start();
++ gpt_reset();
++}
++
++/* IU error mode manager */
++
++static void
++error_mode(pc)
++ uint32 pc;
++{
++
++}
++
++
++/* Memory init */
++
++static void
++mem_init()
++{
++
++ 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()
++{
++#ifdef FAST_UART
++ flush_uart();
++#endif
++}
++
++static void
++close_port()
++{
++ if (f1open && f1in != stdin)
++ fclose(f1in);
++}
++
++static void
++exit_sim()
++{
++ close_port();
++}
++
++static void
++leon2_reset()
++{
++ 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(level)
++ 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()
++{
++ 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(level)
++ int32 level;
++{
++ irqctrl_ipr |= (1 << level);
++ chk_irq();
++}
++
++static int32
++apb_read(addr, data)
++ 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(addr, data)
++ 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()
++{
++ if (dumbio)
++ return; /* do nothing */
++ if (ifd1 == 0 && f1open) {
++ tcsetattr(0, TCSANOW, &ioc1);
++ tcflush(ifd1, TCIFLUSH);
++ }
++}
++
++static void
++restore_stdio()
++{
++ if (dumbio)
++ return; /* do nothing */
++ 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()
++{
++
++ 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(addr)
++ uint32 addr;
++{
++
++ unsigned tmp;
++
++ 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(addr, data)
++ 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()
++{
++ 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()
++{
++ 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 {
++ uarta_sreg = uarta_hreg;
++ uart_stat_reg |= UARTA_HRE;
++ event(uarta_tx, 0, UART_TX_TIME);
++ }
++ set_irq(3);
++}
++
++static void
++uart_rx(arg)
++ caddr_t arg;
++{
++ int32 rsize;
++ char rxd;
++
++
++ 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(arg)
++ caddr_t arg;
++{
++ grlib_read_uart(APBUART_STATUS); /* Check for UART interrupts every 1000 clk */
++ flush_uart(); /* Flush UART ports */
++ event(uart_intr, 0, UART_FLUSH_TIME);
++}
++
++
++static void
++uart_irq_start()
++{
++#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(arg)
++ 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()
++{
++ if (sis_verbose)
++ printf("GPT started (period %d)\n\r", gpt_scaler + 1);
++}
++
++static void
++gpt_reset()
++{
++ event(gpt_intr, 0, gpt_scaler + 1);
++ gpt_scaler_start = now();
++}
++
++static void
++gpt_scaler_set(val)
++ uint32 val;
++{
++ gpt_scaler = val & 0x0ffff; /* 16-bit scaler */
++}
++
++static void
++timer_ctrl(val, i)
++ 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 (mem, waddr, data, sz, ws)
++ unsigned char *mem;
++ uint32 waddr;
++ uint32 *data;
++ int32 sz;
++ int32 *ws;
++{
++ switch (sz) {
++ case 0:
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= 3;
++#endif
++ mem[waddr] = *data & 0x0ff;
++ *ws = 0;
++ break;
++ case 1:
++#ifdef HOST_LITTLE_ENDIAN
++ waddr ^= 2;
++#endif
++ *((unsigned short *) &(mem[waddr])) = *data & 0x0ffff;
++ *ws = 0;
++ break;
++ case 2:
++ *((uint32 *) &(mem[waddr])) = *data;
++ *ws = 0;
++ break;
++ case 3:
++ *((uint32 *) &(mem[waddr])) = data[0];
++ *((uint32 *) &(mem[waddr + 4])) = data[1];
++ *ws = 0;
++ break;
++ }
++}
++
++
++/* Memory emulation */
++
++static int
++memory_iread(addr, data, ws)
++ uint32 addr;
++ uint32 *data;
++ int32 *ws;
++{
++ if ((addr >= RAM_START) && (addr < RAM_END)) {
++ *data = *((uint32 *) & (ramb[addr & RAM_MASK]));
++ *ws = 0;
++ return (0);
++ } else if (addr < ROM_END) {
++ *data = *((uint32 *) & (romb[addr]));
++ *ws = 0;
++ return (0);
++ }
++
++ printf("Memory exception at %x (illegal address)\n", addr);
++ *ws = MEM_EX_WS;
++ return (1);
++}
++
++static int
++memory_read(addr, data, sz, ws)
++ uint32 addr;
++ uint32 *data;
++ int32 sz;
++ int32 *ws;
++{
++ int32 mexc;
++
++ if ((addr >= RAM_START) && (addr < RAM_END)) {
++ *data = *((uint32 *) & (ramb[addr & RAM_MASK & ~3]));
++ *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) {
++ *data = *((uint32 *) & (romb[addr & ~3]));
++ *ws = 0;
++ return (0);
++ }
++
++ printf("Memory exception at %x (illegal address)\n", addr);
++ *ws = MEM_EX_WS;
++ return (1);
++}
++
++static int
++memory_read_asi(asi, addr, data, sz, ws)
++ int32 asi;
++ uint32 addr;
++ uint32 *data;
++ int32 sz;
++ int32 *ws;
++{
++ return(memory_read(addr, data, sz, ws));
++}
++
++static int
++memory_write(addr, data, sz, ws)
++ 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) {
++// return (1);
++ *ws = 0;
++ store_bytes (romb, addr, data, sz, ws);
++ return (0);
++ }
++
++ *ws = MEM_EX_WS;
++ return (1);
++}
++
++static int
++memory_write_asi(asi, addr, data, sz, ws)
++ 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;
++ 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(addr, data, length)
++ 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(addr, data, length)
++ uint32 addr;
++ char *data;
++ uint32 length;
++{
++ char *mem;
++ int ws;
++
++ if (length == 4) {
++ memory_read(addr, 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 ()
++{
++// mec_write(MEC_WCR, 0); /* zero waitstates */
++// mec_write(MEC_TRAPD, 0); /* turn off watch-dog */
++ apb_write(TIMER_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
++ apb_write(TIMER_SCLOAD, sregs.freq-1);
++ apb_write(TIMER_TIMER1, -1);
++ apb_write(TIMER_RELOAD1, -1);
++ apb_write(TIMER_CTRL1, 0x7);
++// mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
++ sregs.wim = 2;
++ sregs.psr = 0x000010e0;
++ sregs.r[30] = RAM_END;
++ sregs.r[14] = sregs.r[30] - 96*4;
++ cache_ctrl = 0x01000f;
++
++}
++
++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 0e19270..99d5286 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -181,6 +181,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;
+@@ -199,6 +203,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 a551b4a..c043504 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -190,6 +190,7 @@ struct memsys {
+ #define ERROR 3
+ #define CTRL_C 4
+
++#define CPU_LEON2 2
+ #define CPU_LEON3 3
+
+ /* Prototypes */
+@@ -270,5 +271,8 @@ extern void gen_help (void);
+
+ extern struct memsys *ms;
+
++/* leon2.c */
++extern struct memsys leon2;
++
+ /* leon3.c */
+ extern struct memsys leon3;
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0020-sim-erc32-Updated-documentation.patch b/tools/4.11/gdb/sparc/7.9/0020-sim-erc32-Updated-documentation.patch
new file mode 100644
index 0000000..3676f6b
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0020-sim-erc32-Updated-documentation.patch
@@ -0,0 +1,516 @@
+From f2694ee29b6f598d1361d59a3858f46b0a495450 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Wed, 18 Feb 2015 23:10:51 +0100
+Subject: [PATCH 20/23] 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 | 4 -
+ 5 files changed, 117 insertions(+), 308 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@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 124e577..27e6ede 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 @@ 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 1b9b41c..0000000
+--- a/sim/erc32/startsim
++++ /dev/null
+@@ -1,4 +0,0 @@
+-#
+-xterm -e sis $* &
+-xterm -e tip /dev/ttypc &
+-
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0021-sim-erc32-Add-data-watchpoint-support.patch b/tools/4.11/gdb/sparc/7.9/0021-sim-erc32-Add-data-watchpoint-support.patch
new file mode 100644
index 0000000..7078cc3
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0021-sim-erc32-Add-data-watchpoint-support.patch
@@ -0,0 +1,377 @@
+From 933b0b5f256713f50959cd1f1c6ad565f40b12ab Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Thu, 19 Feb 2015 23:21:02 +0100
+Subject: [PATCH 21/23] sim/erc32: Add data watchpoint support
+
+ Add watchpoint to all processor targets (erc32, leon2, leon3).
+---
+ sim/erc32/exec.c | 54 +++++++++++++++++++++++++++-------
+ sim/erc32/func.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ sim/erc32/sis.c | 32 +++++++++++++++-----
+ sim/erc32/sis.h | 23 ++++++++++++++-
+ 4 files changed, 179 insertions(+), 20 deletions(-)
+
+diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
+index f4a0124..134e789 100644
+--- a/sim/erc32/exec.c
++++ b/sim/erc32/exec.c
+@@ -395,6 +395,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;
+@@ -698,6 +712,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;
+
+@@ -1211,18 +1231,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
+@@ -2133,12 +2160,18 @@ execute_trap(sregs)
+ {
+ int32 cwp;
+
+- if (sregs->trap == 256) {
+- sregs->pc = 0;
+- sregs->npc = 4;
+- sregs->trap = 0;
+- } else if (sregs->trap == 257) {
++ 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)
+@@ -2231,6 +2264,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 a22e800..7a8a4e4 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -61,7 +61,8 @@ uint32 last_load_addr = 0;
+ int nouartrx = 0;
+ host_callback *sim_callback;
+ 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;
+@@ -624,6 +625,53 @@ exec_cmd(sregs, 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");
+ }
+@@ -714,6 +762,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;
+@@ -1023,6 +1073,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/sis.c b/sim/erc32/sis.c
+index 99d5286..7c984bc 100644
+--- a/sim/erc32/sis.c
++++ b/sim/erc32/sis.c
+@@ -75,11 +75,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++;
+@@ -90,14 +86,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;
+@@ -118,6 +125,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);
+ }
+
+@@ -283,6 +294,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 c043504..fda5f01 100644
+--- a/sim/erc32/sis.h
++++ b/sim/erc32/sis.h
+@@ -39,8 +39,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;
+@@ -108,6 +110,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 */
+@@ -184,12 +194,19 @@ struct memsys {
+ };
+
+
++/* 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
+
+@@ -240,6 +257,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);
+@@ -249,6 +269,7 @@ extern host_callback *sim_callback;
+ extern int current_target_byte_order;
+ extern int dumbio;
+ extern int cputype;
++extern int sis_gdb_break;
+
+ /* exec.c */
+ extern int dispatch_instruction (struct pstate *sregs);
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0022-Add-watchpoint-support-to-gdb-simulator-interface.patch b/tools/4.11/gdb/sparc/7.9/0022-Add-watchpoint-support-to-gdb-simulator-interface.patch
new file mode 100644
index 0000000..6a1e0ee
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0022-Add-watchpoint-support-to-gdb-simulator-interface.patch
@@ -0,0 +1,1025 @@
+From b2a82dcd2f4779119cc1a87591a7ab9eebc3ea61 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Mon, 8 Dec 2014 23:06:17 +0100
+Subject: [PATCH 22/23] 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/cr16/interp.c | 25 +++++
+ sim/cris/Makefile.in | 1 +
+ sim/erc32/interf.c | 235 ++++++++++++++++++++++++++++++++----------
+ sim/frv/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 | 2 +-
+ sim/mips/Makefile.in | 1 +
+ 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 | 3 +-
+ 28 files changed, 568 insertions(+), 54 deletions(-)
+ create mode 100644 sim/common/sim-watch-remote.c
+
+diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
+index fd2fd58..af17e85 100644
+--- a/gdb/remote-sim.c
++++ b/gdb/remote-sim.c
+@@ -1294,6 +1294,70 @@ gdbsim_has_memory (struct target_ops *ops)
+ return 1;
+ }
+
++static int
++gdbsim_insert_watchpoint (struct target_ops *self,
++ CORE_ADDR addr, int len, int 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, int 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,
++ int 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;
+@@ -1316,6 +1380,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 3dca380..36fef3c 100644
+--- a/include/gdb/remote-sim.h
++++ b/include/gdb/remote-sim.h
+@@ -280,6 +280,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 0ccc7fb..a6871ad 100644
+--- a/sim/arm/wrapper.c
++++ b/sim/arm/wrapper.c
+@@ -1016,3 +1016,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/avr/interp.c b/sim/avr/interp.c
+index 8ae4887..c9f944c 100644
+--- a/sim/avr/interp.c
++++ b/sim/avr/interp.c
+@@ -1859,3 +1859,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/bfin/Makefile.in b/sim/bfin/Makefile.in
+index b6cfeb5..d3fa401 100644
+--- a/sim/bfin/Makefile.in
++++ b/sim/bfin/Makefile.in
+@@ -39,6 +39,7 @@ SIM_OBJS = \
+ sim-reg.o \
+ sim-resume.o \
+ sim-stop.o \
++ sim-watch-remote.o \
+ @BFIN_SIM_EXTRA_OBJS@ \
+ $(SIM_EXTRA_OBJS)
+
+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/cr16/interp.c b/sim/cr16/interp.c
+index 9c85948..1c79258 100644
+--- a/sim/cr16/interp.c
++++ b/sim/cr16/interp.c
+@@ -1584,3 +1584,28 @@ sim_load (SIM_DESC sd, const char *prog, struct bfd *abfd, int from_tty)
+ prog_bfd_was_opened_p = abfd == NULL;
+ 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/cris/Makefile.in b/sim/cris/Makefile.in
+index a4332c8..6607c32 100644
+--- a/sim/cris/Makefile.in
++++ b/sim/cris/Makefile.in
+@@ -30,6 +30,7 @@ SIM_OBJS = \
+ sim-hrw.o \
+ sim-model.o \
+ sim-reg.o \
++ sim-watch-remote.o \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o sim-reason.o sim-engine.o sim-stop.o \
+ sim-if.o arch.o \
+diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
+index 8988f23..b2f81c5 100644
+--- a/sim/erc32/interf.c
++++ b/sim/erc32/interf.c
+@@ -36,8 +36,6 @@
+
+ #define PSR_CWP 0x7
+
+-int sis_gdb_break = 1;
+-
+ int
+ run_sim(sregs, icount, dis)
+ struct pstate *sregs;
+@@ -52,37 +50,14 @@ 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 {
+@@ -91,47 +66,40 @@ 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);
+ }
+
+@@ -161,6 +129,7 @@ sim_open (kind, callback, abfd, argv)
+ int freq = 0;
+
+ sim_callback = callback;
++ sis_gdb_break = 1;
+
+ while (argv[argc])
+ argc++;
+@@ -413,12 +382,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;
+@@ -427,8 +399,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
+@@ -489,7 +463,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 ();
+ }
+@@ -524,6 +516,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 ea34bf2..1e1398d 100644
+--- a/sim/frv/Makefile.in
++++ b/sim/frv/Makefile.in
+@@ -26,6 +26,7 @@ SIM_OBJS = \
+ sim-hrw.o \
+ sim-model.o \
+ sim-reg.o \
++ sim-watch-remote.o \
+ cgen-utils.o cgen-trace.o cgen-scache.o cgen-fpu.o cgen-accfp.o \
+ cgen-run.o sim-reason.o sim-engine.o sim-stop.o \
+ sim-if.o arch.o \
+diff --git a/sim/h8300/Makefile.in b/sim/h8300/Makefile.in
+index 7a569bd..3337b89 100644
+--- a/sim/h8300/Makefile.in
++++ b/sim/h8300/Makefile.in
+@@ -25,6 +25,7 @@ SIM_OBJS = compile.o \
+ sim-cpu.o \
+ sim-engine.o \
+ sim-load.o \
++ sim-watch-remote.o \
+ $(SIM_EXTRA_OBJS)
+
+ ## COMMON_POST_CONFIG_FRAG
+diff --git a/sim/iq2000/Makefile.in b/sim/iq2000/Makefile.in
+index 7606b26..c079248 100644
+--- a/sim/iq2000/Makefile.in
++++ b/sim/iq2000/Makefile.in
+@@ -32,6 +32,7 @@ SIM_OBJS = \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o sim-reason.o sim-engine.o sim-stop.o \
+ sim-if.o arch.o \
++ sim-watch-remote.o \
+ $(IQ2000_OBJS) \
+ $(CONFIG_DEVICES)
+
+diff --git a/sim/lm32/Makefile.in b/sim/lm32/Makefile.in
+index 05cf53b..d8d5a2a 100644
+--- a/sim/lm32/Makefile.in
++++ b/sim/lm32/Makefile.in
+@@ -15,6 +15,7 @@ SIM_OBJS = \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o sim-reason.o sim-engine.o sim-stop.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 62ec28c..b8560d5 100644
+--- a/sim/m32c/gdb-if.c
++++ b/sim/m32c/gdb-if.c
+@@ -710,3 +710,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/m32r/Makefile.in b/sim/m32r/Makefile.in
+index 12a6a8d..dfa7bd0 100644
+--- a/sim/m32r/Makefile.in
++++ b/sim/m32r/Makefile.in
+@@ -34,6 +34,7 @@ SIM_OBJS = \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o sim-reason.o sim-engine.o sim-stop.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 fac0b24..62915d1 100644
+--- a/sim/m68hc11/Makefile.in
++++ b/sim/m68hc11/Makefile.in
+@@ -31,6 +31,7 @@ SIM_OBJS = $(M68HC11_OBJS) \
+ sim-stop.o \
+ sim-hrw.o \
+ sim-reason.o \
++ sim-watch-remote.o \
+ $(SIM_EXTRA_OBJS)
+
+ SIM_PROFILE= -DPROFILE=1 -DWITH_PROFILE=-1
+diff --git a/sim/mcore/interp.c b/sim/mcore/interp.c
+index d2edd12..003bb80 100644
+--- a/sim/mcore/interp.c
++++ b/sim/mcore/interp.c
+@@ -2204,3 +2204,28 @@ sim_set_callbacks (ptr)
+ {
+ callback = ptr;
+ }
++
++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 dda4650..49be635 100644
+--- a/sim/microblaze/Makefile.in
++++ b/sim/microblaze/Makefile.in
+@@ -17,7 +17,7 @@
+
+ ## COMMON_PRE_CONFIG_FRAG
+
+-SIM_OBJS = interp.o sim-load.o
++SIM_OBJS = interp.o sim-load.o sim-watch-remote.o
+ SIM_EXTRA_LIBS = -lm
+ SIM_EXTRA_CLEAN = microblaze-clean
+
+diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
+index 985f4e5..22b4714 100644
+--- a/sim/mips/Makefile.in
++++ b/sim/mips/Makefile.in
+@@ -54,6 +54,7 @@ SIM_OBJS = \
+ sim-stop.o \
+ sim-resume.o \
+ sim-reason.o \
++ sim-watch-remote.o
+
+
+ # List of flags to always pass to $(CC).
+diff --git a/sim/mn10300/Makefile.in b/sim/mn10300/Makefile.in
+index c94e531..0a8cd86 100644
+--- a/sim/mn10300/Makefile.in
++++ b/sim/mn10300/Makefile.in
+@@ -27,6 +27,7 @@ MN10300_OBJS = \
+ sim-resume.o \
+ sim-reason.o \
+ sim-stop.o \
++ sim-watch-remote.o \
+ dv-sockser.o
+
+ SIM_OBJS = $(MN10300_OBJS) interp.o
+diff --git a/sim/moxie/interp.c b/sim/moxie/interp.c
+index 5f449af..3e86b41 100644
+--- a/sim/moxie/interp.c
++++ b/sim/moxie/interp.c
+@@ -1475,3 +1475,28 @@ sim_set_callbacks (ptr)
+ {
+ callback = ptr;
+ }
++
++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 e398d0d..5982f4b 100644
+--- a/sim/msp430/Makefile.in
++++ b/sim/msp430/Makefile.in
+@@ -36,6 +36,7 @@ SIM_OBJS = \
+ sim-reg.o \
+ sim-resume.o \
+ sim-stop.o \
++ sim-watch-remote.o \
+ $(SIM_EXTRA_OBJS)
+
+ # List of extra dependencies.
+diff --git a/sim/ppc/gdb-sim.c b/sim/ppc/gdb-sim.c
+index 0269458..3ce3016 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 6317a73..262e3e1 100644
+--- a/sim/rl78/gdb-if.c
++++ b/sim/rl78/gdb-if.c
+@@ -571,3 +571,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 762c3d2..8140a8b 100644
+--- a/sim/rx/gdb-if.c
++++ b/sim/rx/gdb-if.c
+@@ -853,3 +853,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 c854174..24f03ed 100644
+--- a/sim/sh/interp.c
++++ b/sim/sh/interp.c
+@@ -2780,3 +2780,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/sh64/Makefile.in b/sim/sh64/Makefile.in
+index 0022d8e..a9cf62a 100644
+--- a/sim/sh64/Makefile.in
++++ b/sim/sh64/Makefile.in
+@@ -34,6 +34,7 @@ SIM_OBJS = \
+ cgen-utils.o cgen-trace.o cgen-scache.o \
+ cgen-run.o sim-reason.o sim-engine.o sim-stop.o \
+ sim-if.o arch.o \
++ sim-watch-remote.o \
+ $(SH64_OBJS) \
+ $(CONFIG_DEVICES)
+
+diff --git a/sim/v850/Makefile.in b/sim/v850/Makefile.in
+index 067158f..ad24cd8 100644
+--- a/sim/v850/Makefile.in
++++ b/sim/v850/Makefile.in
+@@ -28,7 +28,8 @@ SIM_OBJS = \
+ sim-hrw.o \
+ sim-resume.o \
+ sim-reason.o \
+- sim-stop.o
++ sim-stop.o \
++ sim-watch-remote.o
+
+ SIM_RUN_OBJS = nrun.o
+
+--
+1.9.1
+
diff --git a/tools/4.11/gdb/sparc/7.9/0023-sim-erc32-ELF-loading-could-fail-on-unaligned-sectio.patch b/tools/4.11/gdb/sparc/7.9/0023-sim-erc32-ELF-loading-could-fail-on-unaligned-sectio.patch
new file mode 100644
index 0000000..4a80399
--- /dev/null
+++ b/tools/4.11/gdb/sparc/7.9/0023-sim-erc32-ELF-loading-could-fail-on-unaligned-sectio.patch
@@ -0,0 +1,39 @@
+From 7cecef8c4569896ec7c16c6fc51ef0c5ce7aa7f1 Mon Sep 17 00:00:00 2001
+From: Jiri Gaisler <jiri@gaisler.se>
+Date: Sat, 21 Mar 2015 18:31:15 +0100
+Subject: [PATCH 23/23] sim/erc32: ELF loading could fail on unaligned
+ sections.
+
+Endian swapping on little-endian hosts could fail if ELF section
+length not a multiple of 4.
+
+ func.c (bfd_load): Pad section buffers with zeros and round
+ section size upwards towards nearest 4-multiple.
+---
+ sim/erc32/func.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sim/erc32/func.c b/sim/erc32/func.c
+index 7a8a4e4..31948a6 100644
+--- a/sim/erc32/func.c
++++ b/sim/erc32/func.c
+@@ -1231,13 +1231,13 @@ bfd_load(fname)
+ uint32 *wbuffer = (uint32 *) buffer;
+
+ count = min(section_size, 1024);
+-
++ wbuffer[(count - 1) / 4] = 0; /* clear last word in buffer */
+ bfd_get_section_contents(pbfd, section, buffer, fptr, count);
+
+ #ifdef HOST_LITTLE_ENDIAN
+- for (i=0;i<count/4;i++) wbuffer[i] = ntohl(wbuffer[i]); // endian swap
++ for (i=0;i<(count+3)/4;i++) wbuffer[i] = ntohl(wbuffer[i]); // endian swap
+ #endif
+- ms->sis_memory_write(section_address, buffer, count);
++ ms->sis_memory_write(section_address, buffer, (count + 3) & ~3);
+
+ section_address += count;
+ fptr += count;
+--
+1.9.1
+