summaryrefslogtreecommitdiff
path: root/tools/4.11/gdb/sparc/7.9/0019-sim-erc32-Add-support-for-LEON2-processor-emulation.patch
diff options
context:
space:
mode:
Diffstat (limited to 'tools/4.11/gdb/sparc/7.9/0019-sim-erc32-Add-support-for-LEON2-processor-emulation.patch')
-rw-r--r--tools/4.11/gdb/sparc/7.9/0019-sim-erc32-Add-support-for-LEON2-processor-emulation.patch1188
1 files changed, 1188 insertions, 0 deletions
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
+