diff options
Diffstat (limited to 'tools/4.11/gdb/sparc/7.9/0018-sim-erc32-Add-support-for-LEON3-processor-emulation.patch')
-rw-r--r-- | tools/4.11/gdb/sparc/7.9/0018-sim-erc32-Add-support-for-LEON3-processor-emulation.patch | 2434 |
1 files changed, 2434 insertions, 0 deletions
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 + |