Rewrite the MIPS simulator's memory model so that it uses the generic

common/sim-core.

Add support for 3, 5, 6, 7 byte transfers to sim core.
This commit is contained in:
Andrew Cagney 1997-11-05 08:17:26 +00:00
parent 22de994d0e
commit 63be8febf7
8 changed files with 445 additions and 649 deletions

View File

@ -1,3 +1,28 @@
Wed Nov 5 13:40:31 1997 Andrew Cagney <cagney@b1.cygnus.com>
* sim-core.h (DECLARE_SIM_CORE_WRITE_N. DECLARE_SIM_CORE_READ_N):
Add argument M, size of data type.
(sim_core_read_misaligned_3, sim_core_write_misaligned_3):
Declare, ditto for 5, 6 & 7 byte transfers.
(sim_core_write_unaligned_1, sim_core_write_unaligned_1): Define
as aligned variant.
* sim-n-core.h (sim_core_trace_M): Rename from
sim_core_trace_N. Add nr_bytes argument. Replace transfer argument
with transfer type. Print transfer direction. Handle 1 and 2 byte
transfers.
(sim_core_read_unaligned_N, sim_core_write_unaligned_N): Trace
unaligned accesses.
(unsigned_M, T2H_M, H2T_M): Rename from unsigned_N, T2H_N, H2T_N.
Update all functions.
* sim-core.c: Generate functions starting with 16 not 1.
(sim_core_read_unaligned_3): Generate. Ditto for 3 byte write and
all 5, 6 & 7 byte transfers.
* sim-n-core.h (sim_core_read_misaligned_N,
sim_core_write_misaligned_N): Implement.
Mon Nov 3 15:03:04 1997 Andrew Cagney <cagney@b1.cygnus.com>
* sim-endian.h (U16_8): Implement

View File

@ -755,24 +755,35 @@ sim_core_xor_write_buffer (SIM_DESC sd,
/* define the read/write 1/2/4/8/16/word functions */
#define N 1
#define N 16
#include "sim-n-core.h"
#undef N
#define N 2
#include "sim-n-core.h"
#undef N
#define N 4
#include "sim-n-core.h"
#undef N
#define N 8
#include "sim-n-core.h"
#undef N
#define N 16
#define N 7
#define M 8
#include "sim-n-core.h"
#define N 6
#define M 8
#include "sim-n-core.h"
#define N 5
#define M 8
#include "sim-n-core.h"
#define N 4
#include "sim-n-core.h"
#define N 3
#define M 4
#include "sim-n-core.h"
#define N 2
#include "sim-n-core.h"
#define N 1
#include "sim-n-core.h"
#undef N
#endif

View File

@ -22,74 +22,113 @@
#ifndef N
#error "N must be #defined"
#endif
#ifndef M
#define M N
#endif
#include "sim-xcat.h"
/* NOTE: see end of file for #undef of these macros */
#define unsigned_N XCONCAT2(unsigned_,N)
#define T2H_N XCONCAT2(T2H_,N)
#define H2T_N XCONCAT2(H2T_,N)
#define unsigned_M XCONCAT2(unsigned_,M)
#define T2H_M XCONCAT2(T2H_,M)
#define H2T_M XCONCAT2(H2T_,M)
#define SWAP_M XCONCAT2(SWAP_,M)
#define sim_core_read_aligned_N XCONCAT2(sim_core_read_aligned_,N)
#define sim_core_write_aligned_N XCONCAT2(sim_core_write_aligned_,N)
#define sim_core_read_unaligned_N XCONCAT2(sim_core_read_unaligned_,N)
#define sim_core_read_misaligned_N XCONCAT2(sim_core_read_misaligned_,N)
#define sim_core_write_aligned_N XCONCAT2(sim_core_write_aligned_,N)
#define sim_core_write_unaligned_N XCONCAT2(sim_core_write_unaligned_,N)
#define sim_core_trace_N XCONCAT2(sim_core_trace_,N)
#define sim_core_write_misaligned_N XCONCAT2(sim_core_write_misaligned_,N)
#define sim_core_trace_M XCONCAT2(sim_core_trace_,M)
/* TAGS: sim_core_trace_1 sim_core_trace_2 */
/* TAGS: sim_core_trace_4 sim_core_trace_8 */
/* TAGS: sim_core_trace_16 sim_core_trace_word */
/* TAGS: sim_core_trace_16 */
#if (M == N)
STATIC_SIM_CORE(void)
sim_core_trace_N (sim_cpu *cpu,
sim_core_trace_M (sim_cpu *cpu,
sim_cia cia,
int line_nr,
char *transfer,
transfer_type type,
sim_core_maps map,
address_word addr,
unsigned_N val)
unsigned_M val,
int nr_bytes)
{
#if (N == 16)
char *transfer = (type == read_transfer ? "read" : "write");
char *direction = (type == read_transfer ? "->" : "<-");
#if (M == 16)
trace_printf (CPU_STATE (cpu), cpu,
"sim-n-core.h:%d: %s-%d %s:0x%08lx -> 0x%08lx%08lx%08lx%08lx\n",
"sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%08lx%08lx%08lx%08lx\n",
line_nr,
transfer, sizeof (unsigned_N),
transfer, nr_bytes,
sim_core_map_to_str (map),
(unsigned long) addr,
direction,
(unsigned long) V4_16 (val, 0),
(unsigned long) V4_16 (val, 1),
(unsigned long) V4_16 (val, 2),
(unsigned long) V4_16 (val, 3));
#endif
#if (N == 8)
#if (M == 8)
trace_printf (CPU_STATE (cpu), cpu,
"sim-n-core.h:%d: %s-%d %s:0x%08lx -> 0x%08lx%08lx\n",
"sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%08lx%08lx\n",
line_nr,
transfer, sizeof (unsigned_N),
transfer, nr_bytes,
sim_core_map_to_str (map),
(unsigned long) addr,
direction,
(unsigned long) V4_8 (val, 0),
(unsigned long) V4_8 (val, 1));
#endif
#if (N == 4)
#if (M == 4)
trace_printf (CPU_STATE (cpu), cpu,
"sim-n-core.h:%d: %s-%d %s:0x%08lx -> 0x%0*lx\n",
"sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%08lx\n",
line_nr,
transfer, sizeof (unsigned_N),
transfer,
nr_bytes,
sim_core_map_to_str (map),
(unsigned long) addr,
sizeof (unsigned_N) * 2,
direction,
(unsigned long) val);
#endif
#if (M == 2)
trace_printf (CPU_STATE (cpu), cpu,
"sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%04lx\n",
line_nr,
transfer,
nr_bytes,
sim_core_map_to_str (map),
(unsigned long) addr,
direction,
(unsigned long) val);
#endif
#if (M == 1)
trace_printf (CPU_STATE (cpu), cpu,
"sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%02lx\n",
line_nr,
transfer,
nr_bytes,
sim_core_map_to_str (map),
(unsigned long) addr,
direction,
(unsigned long) val);
#endif
}
#endif
/* TAGS: sim_core_read_aligned_1 sim_core_read_aligned_2 */
/* TAGS: sim_core_read_aligned_4 sim_core_read_aligned_8 */
/* TAGS: sim_core_read_aligned_16 sim_core_read_aligned_word */
/* TAGS: sim_core_read_aligned_16 */
INLINE_SIM_CORE(unsigned_N)
#if (M == N)
INLINE_SIM_CORE(unsigned_M)
sim_core_read_aligned_N(sim_cpu *cpu,
sim_cia cia,
sim_core_maps map,
@ -97,52 +136,46 @@ sim_core_read_aligned_N(sim_cpu *cpu,
{
sim_cpu_core *cpu_core = CPU_CORE (cpu);
sim_core_common *core = &cpu_core->common;
unsigned_N val;
unsigned_M val;
sim_core_mapping *mapping;
address_word addr;
#if WITH_XOR_ENDIAN != 0
if (WITH_XOR_ENDIAN)
addr = xaddr ^ cpu_core->xor[(sizeof(unsigned_N) - 1) % WITH_XOR_ENDIAN];
addr = xaddr ^ cpu_core->xor[(N - 1) % WITH_XOR_ENDIAN];
else
#endif
addr = xaddr;
mapping = sim_core_find_mapping (core, map,
addr,
sizeof (unsigned_N),
read_transfer,
1 /*abort*/, cpu, cia);
mapping = sim_core_find_mapping (core, map, addr, N, read_transfer, 1 /*abort*/, cpu, cia);
#if (WITH_DEVICES)
if (WITH_CALLBACK_MEMORY && mapping->device != NULL) {
unsigned_N data;
if (device_io_read_buffer (mapping->device,
&data,
mapping->space,
addr,
sizeof (unsigned_N)) != sizeof (unsigned_N))
unsigned_M data;
if (device_io_read_buffer (mapping->device, &data, mapping->space, addr, N) != N)
device_error (mapping->device, "internal error - %s - io_read_buffer should not fail",
XSTRING (sim_core_read_aligned_N));
val = T2H_N (data);
val = T2H_M (data);
}
else
#endif
val = T2H_N (*(unsigned_N*) sim_core_translate (mapping, addr));
PROFILE_COUNT_CORE (cpu, addr, sizeof (unsigned_N), map);
val = T2H_M (*(unsigned_M*) sim_core_translate (mapping, addr));
PROFILE_COUNT_CORE (cpu, addr, N, map);
if (TRACE_P (cpu, TRACE_CORE_IDX))
sim_core_trace_N (cpu, cia, __LINE__, "read", map, addr, val);
sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N);
return val;
}
#endif
/* TAGS: sim_core_read_unaligned_1 sim_core_read_unaligned_2 */
/* TAGS: sim_core_read_unaligned_4 sim_core_read_unaligned_8 */
/* TAGS: sim_core_read_unaligned_16 sim_core_read_unaligned_word */
/* TAGS: sim_core_read_unaligned_16 */
INLINE_SIM_CORE(unsigned_N)
#if (M == N && N > 1)
INLINE_SIM_CORE(unsigned_M)
sim_core_read_unaligned_N(sim_cpu *cpu,
sim_cia cia,
sim_core_maps map,
address_word addr)
{
int alignment = sizeof (unsigned_N) - 1;
int alignment = N - 1;
/* if hardwired to forced alignment just do it */
if (WITH_ALIGNMENT == FORCED_ALIGNMENT)
return sim_core_read_aligned_N (cpu, cia, map, addr & ~alignment);
@ -152,20 +185,18 @@ sim_core_read_unaligned_N(sim_cpu *cpu,
switch (CURRENT_ALIGNMENT)
{
case STRICT_ALIGNMENT:
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map,
sizeof (unsigned_N), addr,
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
read_transfer, sim_core_unaligned_signal);
case NONSTRICT_ALIGNMENT:
{
unsigned_N val;
if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr,
sizeof(unsigned_N))
!= sizeof(unsigned_N))
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map,
sizeof (unsigned_N), addr,
unsigned_M val;
if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N)
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
read_transfer, sim_core_unaligned_signal);
val = T2H_N(val);
PROFILE_COUNT_CORE (cpu, addr, sizeof (unsigned_N), map);
val = T2H_M(val);
PROFILE_COUNT_CORE (cpu, addr, N, map);
if (TRACE_P (cpu, TRACE_CORE_IDX))
sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N);
return val;
}
case FORCED_ALIGNMENT:
@ -180,22 +211,49 @@ sim_core_read_unaligned_N(sim_cpu *cpu,
XSTRING (sim_core_read_unaligned_N));
/* to keep some compilers happy, we return a dummy */
{
unsigned_N val[1] = { };
unsigned_M val[1] = { };
return val[0];
}
}
}
#endif
/* TAGS: sim_core_read_misaligned_3 sim_core_read_misaligned_5 */
/* TAGS: sim_core_read_misaligned_6 sim_core_read_misaligned_7 */
#if (M != N)
INLINE_SIM_CORE(unsigned_M)
sim_core_read_misaligned_N(sim_cpu *cpu,
sim_cia cia,
sim_core_maps map,
address_word addr)
{
unsigned_M val = 0;
if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N)
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
read_transfer, sim_core_unaligned_signal);
if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
val = SWAP_M (val);
if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
val >>= (M - N) * 8;
PROFILE_COUNT_CORE (cpu, addr, N, map);
if (TRACE_P (cpu, TRACE_CORE_IDX))
sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N);
return val;
}
#endif
/* TAGS: sim_core_write_aligned_1 sim_core_write_aligned_2 */
/* TAGS: sim_core_write_aligned_4 sim_core_write_aligned_8 */
/* TAGS: sim_core_write_aligned_16 sim_core_write_aligned_word */
/* TAGS: sim_core_write_aligned_16 */
#if (M == N)
INLINE_SIM_CORE(void)
sim_core_write_aligned_N(sim_cpu *cpu,
sim_cia cia,
sim_core_maps map,
address_word xaddr,
unsigned_N val)
unsigned_M val)
{
sim_cpu_core *cpu_core = CPU_CORE (cpu);
sim_core_common *core = &cpu_core->common;
@ -203,48 +261,40 @@ sim_core_write_aligned_N(sim_cpu *cpu,
address_word addr;
#if WITH_XOR_ENDIAN != 0
if (WITH_XOR_ENDIAN)
addr = xaddr ^ cpu_core->xor[(sizeof(unsigned_N) - 1) % WITH_XOR_ENDIAN];
addr = xaddr ^ cpu_core->xor[(N - 1) % WITH_XOR_ENDIAN];
else
#endif
addr = xaddr;
mapping = sim_core_find_mapping(core, map,
addr,
sizeof (unsigned_N),
write_transfer,
1 /*abort*/, cpu, cia);
mapping = sim_core_find_mapping (core, map, addr, N, write_transfer, 1 /*abort*/, cpu, cia);
#if (WITH_DEVICES)
if (WITH_CALLBACK_MEMORY && mapping->device != NULL) {
unsigned_N data = H2T_N (val);
if (device_io_write_buffer (mapping->device,
&data,
mapping->space,
addr,
sizeof (unsigned_N), /* nr_bytes */
cpu,
cia) != sizeof (unsigned_N))
unsigned_M data = H2T_M (val);
if (device_io_write_buffer (mapping->device, &data, mapping->space, addr, N, cpu, cia) != N)
device_error (mapping->device, "internal error - %s - io_write_buffer should not fail",
XSTRING (sim_core_write_aligned_N));
}
else
#endif
*(unsigned_N*) sim_core_translate (mapping, addr) = H2T_N (val);
PROFILE_COUNT_CORE (cpu, addr, sizeof (unsigned_N), map);
*(unsigned_M*) sim_core_translate (mapping, addr) = H2T_M (val);
PROFILE_COUNT_CORE (cpu, addr, N, map);
if (TRACE_P (cpu, TRACE_CORE_IDX))
sim_core_trace_N (cpu, cia, __LINE__, "write", map, addr, val);
sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N);
}
#endif
/* TAGS: sim_core_write_unaligned_1 sim_core_write_unaligned_2 */
/* TAGS: sim_core_write_unaligned_4 sim_core_write_unaligned_8 */
/* TAGS: sim_core_write_unaligned_16 sim_core_write_unaligned_word */
/* TAGS: sim_core_write_unaligned_16 */
#if (M == N && N > 1)
INLINE_SIM_CORE(void)
sim_core_write_unaligned_N(sim_cpu *cpu,
sim_cia cia,
sim_core_maps map,
address_word addr,
unsigned_N val)
unsigned_M val)
{
int alignment = sizeof (unsigned_N) - 1;
int alignment = N - 1;
/* if hardwired to forced alignment just do it */
if (WITH_ALIGNMENT == FORCED_ALIGNMENT)
sim_core_write_aligned_N (cpu, cia, map, addr & ~alignment, val);
@ -254,20 +304,18 @@ sim_core_write_unaligned_N(sim_cpu *cpu,
switch (CURRENT_ALIGNMENT)
{
case STRICT_ALIGNMENT:
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map,
sizeof (unsigned_N), addr,
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
write_transfer, sim_core_unaligned_signal);
break;
case NONSTRICT_ALIGNMENT:
{
unsigned_N val = H2T_N (val);
if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &val, addr,
sizeof(unsigned_N))
!= sizeof(unsigned_N))
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map,
sizeof (unsigned_N), addr,
unsigned_M data = H2T_M (val);
if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N)
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
write_transfer, sim_core_unaligned_signal);
PROFILE_COUNT_CORE (cpu, addr, sizeof (unsigned_N), map);
PROFILE_COUNT_CORE (cpu, addr, N, map);
if (TRACE_P (cpu, TRACE_CORE_IDX))
sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N);
break;
}
case FORCED_ALIGNMENT:
@ -285,14 +333,45 @@ sim_core_write_unaligned_N(sim_cpu *cpu,
break;
}
}
#endif
/* TAGS: sim_core_write_misaligned_3 sim_core_write_misaligned_5 */
/* TAGS: sim_core_write_misaligned_6 sim_core_write_misaligned_7 */
#if (M != N)
INLINE_SIM_CORE(void)
sim_core_write_misaligned_N(sim_cpu *cpu,
sim_cia cia,
sim_core_maps map,
address_word addr,
unsigned_M val)
{
unsigned_M data = val;
if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
data <<= (M - N) * 8;
if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
data = SWAP_M (data);
if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N)
SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
write_transfer, sim_core_unaligned_signal);
PROFILE_COUNT_CORE (cpu, addr, N, map);
if (TRACE_P (cpu, TRACE_CORE_IDX))
sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N);
}
#endif
/* NOTE: see start of file for #define of these macros */
#undef unsigned_N
#undef T2H_N
#undef H2T_N
#undef unsigned_M
#undef T2H_M
#undef H2T_M
#undef SWAP_M
#undef sim_core_read_aligned_N
#undef sim_core_write_aligned_N
#undef sim_core_read_unaligned_N
#undef sim_core_read_misaligned_N
#undef sim_core_write_aligned_N
#undef sim_core_write_unaligned_N
#undef sim_core_trace_N
#undef sim_core_write_misaligned_N
#undef sim_core_trace_M
#undef M
#undef N

View File

@ -1,3 +1,34 @@
Wed Nov 5 12:19:56 1997 Andrew Cagney <cagney@b1.cygnus.com>
* sim-main.h (MAX_INSNS, INSN_NAME): Define.
* interp.c (load_memory, store_memory): Delete parameter RAW.
(sim_read, sim_write): Use sim_core_{read,write}_buffer directly
bypassing {load,store}_memory.
* sim-main.h (ByteSwapMem): Delete definition.
* Makefile.in (SIM_OBJS): Add sim-memopt module.
* interp.c (sim_do_command, sim_commands): Delete mips specific
commands. Handled by module sim-options.
* sim-main.h (SIM_HAVE_FLATMEM): Undefine, use sim-core.o module.
(WITH_MODULO_MEMORY): Define.
* interp.c (sim_info): Delete code printing memory size.
* interp.c (mips_size): Nee sim_size, delete function.
(power2): Delete.
(monitor, monitor_base, monitor_size): Delete global variables.
(sim_open, sim_close): Delete code creating monitor and other
memory regions. Use sim-memopts module, via sim_do_commandf, to
manage memory regions.
(load_memory, store_memory): Use sim-core for memory model.
* interp.c (address_translation): Delete all memory map code
except line forcing 32 bit addresses.
Wed Nov 5 11:21:11 1997 Andrew Cagney <cagney@b1.cygnus.com>
* sim-main.h (WITH_TRACE): Delete definition. Enables common

View File

@ -38,6 +38,7 @@ SIM_OBJS = \
sim-config.o \
sim-endian.o \
sim-engine.o \
sim-memopt.o \
sim-stop.o \
sim-resume.o \
sim-reason.o \

View File

@ -19,11 +19,6 @@
NOTEs:
We only need to take account of the target endianness when moving data
between the simulator and the host. We do not need to worry about the
endianness of the host, since this sim code and GDB are executing in
the same process.
The IDT monitor (found on the VR4300 board), seems to lie about
register contents. It seems to treat the registers as sign-extended
32-bit values. This cause *REAL* problems when single-stepping 64-bit
@ -110,9 +105,6 @@ char* pr_uword64 PARAMS ((uword64 addr));
static void dotrace PARAMS((SIM_DESC sd,FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...));
static void ColdReset PARAMS((SIM_DESC sd));
static long getnum PARAMS((SIM_DESC sd, char *value));
static unsigned int power2 PARAMS((unsigned int value));
static void mips_size PARAMS((SIM_DESC sd, int n));
/*---------------------------------------------------------------------------*/
@ -150,11 +142,6 @@ static void mips_size PARAMS((SIM_DESC sd, int n));
#define MONITOR_SIZE (1 << 11)
#define MEM_SIZE (2 << 20)
/* Simple run-time monitor support */
static unsigned char *monitor = NULL;
static ut_reg monitor_base = MONITOR_BASE;
static unsigned monitor_size = MONITOR_SIZE; /* power-of-2 */
#if defined(TRACE)
static char *tracefile = "trace.din"; /* default filename for trace log */
static FILE *tracefh = NULL;
@ -274,17 +261,24 @@ sim_open (kind, cb, abfd, argv)
STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event;
/* memory defaults (unless sim_size was here first) */
if (STATE_MEM_SIZE (sd) == 0)
STATE_MEM_SIZE (sd) = MEM_SIZE;
STATE_MEM_BASE (sd) = K1BASE;
STATE = 0;
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
return 0;
sim_add_option_table (sd, mips_options);
/* Allocate core managed memory */
/* the monitor */
sim_do_commandf (sd, "memory region 0x%lx,0x%lx", MONITOR_BASE, MONITOR_SIZE);
/* For compatibility with the old code - under this (at level one)
are the kernel spaces K0 & K1. Both of these map to a single
smaller sub region */
sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
K1BASE, K0SIZE,
MEM_SIZE, /* actual size */
K0BASE);
/* getopt will print the error message so we just have to exit if this fails.
FIXME: Hmmm... in the case of gdb we need getopt to call
print_filtered. */
@ -382,24 +376,6 @@ sim_open (kind, cb, abfd, argv)
/* end-sanitize-r5900 */
}
/* FIXME: In the future both of these malloc's can be replaced by
calls to sim-core. */
/* If the host has "mmap" available we could use it to provide a
very large virtual address space for the simulator, since memory
would only be allocated within the "mmap" space as it is
accessed. This can also be linked to the architecture specific
support, required to simulate the MMU. */
mips_size(sd, STATE_MEM_SIZE (sd));
/* NOTE: The above will also have enabled any profiling state! */
/* Create the monitor address space as well */
monitor = (unsigned char *)calloc(1,monitor_size);
if (!monitor)
fprintf(stderr,"Not enough VM for monitor simulation (%d bytes)\n",
monitor_size);
#if defined(TRACE)
if (STATE & simTRACE)
open_trace(sd);
@ -505,10 +481,6 @@ sim_close (sd, quitting)
STATE &= ~simTRACE;
#endif /* TRACE */
if (STATE_MEMORY (sd) != NULL)
free(STATE_MEMORY (sd)); /* cfree not available on all hosts */
STATE_MEMORY (sd) = NULL;
return;
}
@ -537,7 +509,8 @@ sim_write (sd,addr,buffer,size)
int cca;
if (!AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &cca, isTARGET, isRAW))
break;
StoreMemory (cca, AccessLength_BYTE, buffer[index], 0, paddr, vaddr, isRAW);
if (sim_core_write_buffer (sd, NULL, sim_core_read_map, buffer + index, paddr, 1) != 1)
break;
}
return(index);
@ -561,12 +534,11 @@ sim_read (sd,addr,buffer,size)
{
address_word vaddr = (address_word)addr + index;
address_word paddr;
unsigned64 value;
int cca;
if (!AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &cca, isTARGET, isRAW))
break;
LoadMemory (&value, NULL, cca, AccessLength_BYTE, paddr, vaddr, isDATA, isRAW);
buffer[index] = (unsigned char)(value&0xFF);
if (sim_core_read_buffer (sd, NULL, sim_core_read_map, buffer + index, paddr, 1) != 1)
break;
}
return(index);
@ -648,10 +620,6 @@ sim_info (sd,verbose)
(PROCESSOR_64BIT ? 64 : 32),
(CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN ? "Big" : "Little"));
sim_io_printf (sd, "0x%08X bytes of memory at 0x%s\n",
STATE_MEM_SIZE (sd),
pr_addr (STATE_MEM_BASE (sd)));
#if !defined(FASTSIM)
/* It would be a useful feature, if when performing multi-cycle
simulations (rather than single-stepping) we keep the start and
@ -712,110 +680,16 @@ sim_create_inferior (sd, abfd, argv,env)
return SIM_RC_OK;
}
typedef enum {e_terminate,e_help,e_setmemsize,e_reset} e_cmds;
static struct t_sim_command {
e_cmds id;
const char *name;
const char *help;
} sim_commands[] = {
{e_help, "help", ": Show MIPS simulator private commands"},
{e_setmemsize,"set-memory-size","<n> : Specify amount of memory simulated"},
{e_reset, "reset-system", ": Reset the simulated processor"},
{e_terminate, NULL}
};
void
sim_do_command (sd,cmd)
SIM_DESC sd;
char *cmd;
{
struct t_sim_command *cptr;
if (!(cmd && *cmd != '\0'))
cmd = "help";
/* NOTE: Accessed from the GDB "sim" commmand: */
for (cptr = sim_commands; cptr && cptr->name; cptr++)
if (strncmp (cmd, cptr->name, strlen(cptr->name)) == 0)
{
cmd += strlen(cptr->name);
switch (cptr->id) {
case e_help: /* no arguments */
{ /* no arguments */
struct t_sim_command *lptr;
sim_io_printf(sd,"List of MIPS simulator commands:\n");
for (lptr = sim_commands; lptr->name; lptr++)
sim_io_printf(sd,"%s %s\n",lptr->name,lptr->help);
sim_args_command (sd, "help");
}
break;
case e_setmemsize: /* memory size argument */
{
unsigned int newsize = (unsigned int)getnum(sd, cmd);
mips_size(sd, newsize);
}
break;
case e_reset: /* no arguments */
ColdReset(sd);
/* NOTE: See the comments in sim_open() relating to device
initialisation. */
break;
default:
sim_io_printf(sd,"FATAL: Matched \"%s\", but failed to match command id %d.\n",cmd,cptr->id);
break;
}
break;
}
if (!(cptr->name))
{
/* try for a common command when the sim specific lookup fails */
if (sim_args_command (sd, cmd) != SIM_RC_OK)
sim_io_printf(sd,"Error: \"%s\" is not a valid MIPS simulator command.\n",cmd);
}
return;
if (sim_args_command (sd, cmd) != SIM_RC_OK)
sim_io_printf (sd, "Error: \"%s\" is not a valid MIPS simulator command.\n",
cmd);
}
/*---------------------------------------------------------------------------*/
/* NOTE: The following routines do not seem to be used by GDB at the
moment. However, they may be useful to the standalone simulator
world. */
static void
mips_size(sd, newsize)
SIM_DESC sd;
int newsize;
{
char *new;
/* Used by "run", and internally, to set the simulated memory size */
if (newsize == 0) {
sim_io_printf(sd,"Zero not valid: Memory size still 0x%08X bytes\n",STATE_MEM_SIZE (sd));
return;
}
newsize = power2(newsize);
if (STATE_MEMORY (sd) == NULL)
new = (char *)calloc(64,(STATE_MEM_SIZE (sd) / 64));
else
new = (char *)realloc(STATE_MEMORY (sd),newsize);
if (new == NULL) {
if (STATE_MEMORY (sd) == NULL)
sim_io_error(sd,"Not enough VM for simulation memory of 0x%08X bytes",STATE_MEM_SIZE (sd));
else
sim_io_eprintf(sd,"Failed to resize memory (still 0x%08X bytes)\n",STATE_MEM_SIZE (sd));
} else {
STATE_MEM_SIZE (sd) = (unsigned)newsize;
STATE_MEMORY (sd) = new;
}
return;
}
/*---------------------------------------------------------------------------*/
/*-- Private simulator support interface ------------------------------------*/
/*---------------------------------------------------------------------------*/
@ -1215,48 +1089,6 @@ mips16_entry (sd,insn)
}
}
static unsigned int
power2(value)
unsigned int value;
{
int loop,tmp;
/* Round *UP* to the nearest power-of-2 if not already one */
if (value != (value & ~(value - 1))) {
for (tmp = value, loop = 0; (tmp != 0); loop++)
tmp >>= 1;
value = (1 << loop);
}
return(value);
}
static long
getnum(sd,value)
SIM_DESC sd;
char *value;
{
long num;
char *end;
num = strtol(value,&end,10);
if (end == value)
sim_io_printf(sd,"Warning: Invalid number \"%s\" ignored, using zero\n",value);
else {
if (*end && ((tolower(*end) == 'k') || (tolower(*end) == 'm'))) {
if (tolower(*end) == 'k')
num *= (1 << 10);
else
num *= (1 << 20);
end++;
}
if (*end)
sim_io_printf(sd,"Warning: Spurious characters \"%s\" at end of number ignored\n",end);
}
return(num);
}
/*-- trace support ----------------------------------------------------------*/
/* The TRACE support is provided (if required) in the memory accessing
@ -1408,57 +1240,14 @@ address_translation(sd,vAddr,IorD,LorS,pAddr,CCA,raw)
addressess through (mostly) unchanged. */
vAddr &= 0xFFFFFFFF;
/* Treat the kernel memory spaces identically for the moment: */
if ((STATE_MEM_BASE (sd) == K1BASE) && (vAddr >= K0BASE) && (vAddr < (K0BASE + K0SIZE)))
vAddr += (K1BASE - K0BASE);
/* Also assume that the K1BASE memory wraps. This is required to
allow the PMON run-time __sizemem() routine to function (without
having to provide exception simulation). NOTE: A kludge to work
around the fact that the monitor memory is currently held in the
K1BASE space. */
if (((vAddr < monitor_base) || (vAddr >= (monitor_base + monitor_size))) && (vAddr >= K1BASE && vAddr < (K1BASE + K1SIZE)))
vAddr = (K1BASE | (vAddr & (STATE_MEM_SIZE (sd) - 1)));
*pAddr = vAddr; /* default for isTARGET */
*CCA = Uncached; /* not used for isHOST */
/* NOTE: This is a duplicate of the code that appears in the
LoadMemory and StoreMemory functions. They should be merged into
a single function (that can be in-lined if required). */
if ((vAddr >= STATE_MEM_BASE (sd)) && (vAddr < (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)))) {
/* do nothing */
} else if ((vAddr >= monitor_base) && (vAddr < (monitor_base + monitor_size))) {
/* do nothing */
} else {
#ifdef DEBUG
sim_io_eprintf(sd,"Failed: AddressTranslation(0x%s,%s,%s,...) IPC = 0x%s\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "isSTORE" : "isLOAD"),pr_addr(IPC));
#endif /* DEBUG */
res = 0; /* AddressTranslation has failed */
*pAddr = (SIM_ADDR)-1;
if (!raw) /* only generate exceptions on real memory transfers */
{
if (IorD == isINSTRUCTION)
SignalExceptionInstructionFetch ();
else if (LorS == isSTORE)
SignalExceptionAddressStore ();
else
SignalExceptionAddressLoad ();
}
#ifdef DEBUG
else
/* This is a normal occurance during gdb operation, for instance
trying to print parameters at function start before they have
been setup, and hence we should not print a warning except
when debugging the simulator. */
sim_io_eprintf(sd,"AddressTranslation for %s %s from 0x%s failed\n",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),pr_addr(vAddr));
#endif
}
return(res);
}
/* Description from page A-23 of the "MIPS IV Instruction Set" manual (revision 3.1) */
/* Description from page A-23 of the "MIPS IV Instruction Set" manual
(revision 3.1) */
/* Prefetch data from memory. Prefetch is an advisory instruction for
which an implementation specific action is taken. The action taken
may increase performance, but must not change the meaning of the
@ -1481,7 +1270,8 @@ prefetch(sd,CCA,pAddr,vAddr,DATA,hint)
return;
}
/* Description from page A-22 of the "MIPS IV Instruction Set" manual (revision 3.1) */
/* Description from page A-22 of the "MIPS IV Instruction Set" manual
(revision 3.1) */
/* Load a value from memory. Use the cache and main memory as
specified in the Cache Coherence Algorithm (CCA) and the sort of
access (IorD) to find the contents of AccessLength memory bytes
@ -1497,7 +1287,7 @@ prefetch(sd,CCA,pAddr,vAddr,DATA,hint)
satisfy a load reference. At a minimum, the block is the entire
memory element. */
void
load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw)
load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD)
SIM_DESC sd;
uword64* memvalp;
uword64* memval1p;
@ -1506,173 +1296,108 @@ load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw)
address_word pAddr;
address_word vAddr;
int IorD;
int raw;
{
uword64 value = 0;
uword64 value1 = 0;
#ifdef DEBUG
if (STATE_MEMORY (sd) == NULL)
sim_io_printf(sd,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(raw ? "isRAW" : "isREAL"));
sim_io_printf(sd,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"));
#endif /* DEBUG */
#if defined(WARN_MEM)
if (CCA != uncached)
sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) {
/* In reality this should be a Bus Error */
sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
}
sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
#endif /* WARN_MEM */
/* Decide which physical memory locations are being dealt with. At
this point we should be able to split the pAddr bits into the
relevant address map being simulated. */
/* If the "raw" variable is set, the memory read being performed
should *NOT* update any I/O state or affect the CPU state
(including statistics gathering). The parameter MEMVALP is least
significant byte justified. */
/* If instruction fetch then we need to check that the two lo-order
bits are zero, otherwise raise a InstructionFetch exception: */
if ((IorD == isINSTRUCTION)
&& ((pAddr & 0x3) != 0)
&& (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
SignalExceptionInstructionFetch ();
else {
unsigned int index = 0;
unsigned char *mem = NULL;
SignalExceptionInstructionFetch ();
if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
{
/* In reality this should be a Bus Error */
sim_io_error (sd, "AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",
AccessLength,
(LOADDRMASK + 1) << 2,
pr_addr (pAddr));
}
#if defined(TRACE)
if (!raw)
dotrace(sd,tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
dotrace(sd,tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
#endif /* TRACE */
/* Read the specified number of bytes from memory. Adjust for
host/target byte ordering/ Align the least significant byte
read. */
/* NOTE: Quicker methods of decoding the address space can be used
when a real memory map is being simulated (i.e. using hi-order
address bits to select device). */
if ((pAddr >= STATE_MEM_BASE (sd)) && (pAddr < (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)))) {
index = ((unsigned int)(pAddr - STATE_MEM_BASE (sd)) & (STATE_MEM_SIZE (sd) - 1));
mem = STATE_MEMORY (sd);
} else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) {
index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1));
mem = monitor;
switch (AccessLength)
{
case AccessLength_QUADWORD :
{
unsigned_16 val = sim_core_read_aligned_16 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_read_map, pAddr);
value1 = VH8_16 (val);
value = VL8_16 (val);
break;
}
case AccessLength_DOUBLEWORD :
value = sim_core_read_aligned_8 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_read_map, pAddr);
break;
case AccessLength_SEPTIBYTE :
value = sim_core_read_misaligned_7 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_read_map, pAddr);
case AccessLength_SEXTIBYTE :
value = sim_core_read_misaligned_6 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_read_map, pAddr);
case AccessLength_QUINTIBYTE :
value = sim_core_read_misaligned_5 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_read_map, pAddr);
case AccessLength_WORD :
value = sim_core_read_aligned_4 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_read_map, pAddr);
break;
case AccessLength_TRIPLEBYTE :
value = sim_core_read_misaligned_3 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_read_map, pAddr);
case AccessLength_HALFWORD :
value = sim_core_read_aligned_2 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_read_map, pAddr);
break;
case AccessLength_BYTE :
value = sim_core_read_aligned_1 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_read_map, pAddr);
break;
default:
abort ();
}
if (mem == NULL)
sim_io_error(sd,"Simulator memory not found for physical address 0x%s\n",pr_addr(pAddr));
else {
/* If we obtained the endianness of the host, and it is the same
as the target memory system we can optimise the memory
accesses. However, without that information we must perform
slow transfer, and hope that the compiler optimisation will
merge successive loads. */
/* In reality we should always be loading a doubleword value (or
word value in 32bit memory worlds). The external code then
extracts the required bytes. However, to keep performance
high we only load the required bytes into the relevant
slots. */
#ifdef DEBUG
printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
(int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
#endif /* DEBUG */
/* See also store_memory. */
if (AccessLength <= AccessLength_DOUBLEWORD)
{
if (BigEndianMem)
switch (AccessLength) { /* big-endian memory */
case AccessLength_QUADWORD :
value1 |= ((uword64)mem[index++] << 56);
case 14: /* AccessLength is one less than datalen */
value1 |= ((uword64)mem[index++] << 48);
case 13:
value1 |= ((uword64)mem[index++] << 40);
case 12:
value1 |= ((uword64)mem[index++] << 32);
case 11:
value1 |= ((unsigned int)mem[index++] << 24);
case 10:
value1 |= ((unsigned int)mem[index++] << 16);
case 9:
value1 |= ((unsigned int)mem[index++] << 8);
case 8:
value1 |= mem[index];
case AccessLength_DOUBLEWORD :
value |= ((uword64)mem[index++] << 56);
case AccessLength_SEPTIBYTE :
value |= ((uword64)mem[index++] << 48);
case AccessLength_SEXTIBYTE :
value |= ((uword64)mem[index++] << 40);
case AccessLength_QUINTIBYTE :
value |= ((uword64)mem[index++] << 32);
case AccessLength_WORD :
value |= ((unsigned int)mem[index++] << 24);
case AccessLength_TRIPLEBYTE :
value |= ((unsigned int)mem[index++] << 16);
case AccessLength_HALFWORD :
value |= ((unsigned int)mem[index++] << 8);
case AccessLength_BYTE :
value |= mem[index];
break;
}
else {
index += (AccessLength + 1);
switch (AccessLength) { /* little-endian memory */
case AccessLength_QUADWORD :
value1 |= ((uword64)mem[--index] << 56);
case 14: /* AccessLength is one less than datalen */
value1 |= ((uword64)mem[--index] << 48);
case 13:
value1 |= ((uword64)mem[--index] << 40);
case 12:
value1 |= ((uword64)mem[--index] << 32);
case 11:
value1 |= ((uword64)mem[--index] << 24);
case 10:
value1 |= ((uword64)mem[--index] << 16);
case 9:
value1 |= ((uword64)mem[--index] << 8);
case 8:
value1 |= ((uword64)mem[--index] << 0);
case AccessLength_DOUBLEWORD :
value |= ((uword64)mem[--index] << 56);
case AccessLength_SEPTIBYTE :
value |= ((uword64)mem[--index] << 48);
case AccessLength_SEXTIBYTE :
value |= ((uword64)mem[--index] << 40);
case AccessLength_QUINTIBYTE :
value |= ((uword64)mem[--index] << 32);
case AccessLength_WORD :
value |= ((uword64)mem[--index] << 24);
case AccessLength_TRIPLEBYTE :
value |= ((uword64)mem[--index] << 16);
case AccessLength_HALFWORD :
value |= ((uword64)mem[--index] << 8);
case AccessLength_BYTE :
value |= ((uword64)mem[--index] << 0);
break;
}
}
#ifdef DEBUG
printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
(int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
#endif /* DEBUG */
/* When dealing with raw memory accesses there is no need to
deal with shifts. */
if (AccessLength <= AccessLength_DOUBLEWORD) {
if (!raw) { /* do nothing for raw accessess */
if (BigEndianMem)
value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
else /* little-endian only needs to be shifted up to the correct byte offset */
value <<= ((pAddr & LOADDRMASK) * 8);
}
}
#ifdef DEBUG
printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
pr_uword64(value1),pr_uword64(value));
#endif /* DEBUG */
/* for big endian target, byte (pAddr&LOADDRMASK == 0) is
shifted to the most significant byte position. */
value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
else
/* For little endian target, byte (pAddr&LOADDRMASK == 0)
is already in the correct postition. */
value <<= ((pAddr & LOADDRMASK) * 8);
}
}
#ifdef DEBUG
printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
pr_uword64(value1),pr_uword64(value));
#endif /* DEBUG */
*memvalp = value;
if (memval1p) *memval1p = value1;
}
@ -1692,7 +1417,7 @@ load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw)
will be changed. */
void
store_memory(sd,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw)
store_memory(sd,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr)
SIM_DESC sd;
int CCA;
int AccessLength;
@ -1700,169 +1425,89 @@ store_memory(sd,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw)
uword64 MemElem1; /* High order 64 bits */
address_word pAddr;
address_word vAddr;
int raw;
{
#ifdef DEBUG
sim_io_printf(sd,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s,%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr),(raw ? "isRAW" : "isREAL"));
sim_io_printf(sd,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr));
#endif /* DEBUG */
#if defined(WARN_MEM)
if (CCA != uncached)
sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
#endif /* WARN_MEM */
if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
#if defined(TRACE)
if (!raw)
dotrace(sd,tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
dotrace(sd,tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
#endif /* TRACE */
/* See the comments in the LoadMemory routine about optimising
memory accesses. Also if we wanted to make the simulator smaller,
we could merge a lot of this code with the LoadMemory
routine. However, this would slow the simulator down with
run-time conditionals. */
/* If the "raw" variable is set, the memory read being performed
should *NOT* update any I/O state or affect the CPU state
(including statistics gathering). The parameter MEMELEM is least
significant byte justified. */
{
unsigned int index = 0;
unsigned char *mem = NULL;
if ((pAddr >= STATE_MEM_BASE (sd)) && (pAddr < (STATE_MEM_BASE (sd) + STATE_MEM_SIZE (sd)))) {
index = ((unsigned int)(pAddr - STATE_MEM_BASE (sd)) & (STATE_MEM_SIZE (sd) - 1));
mem = STATE_MEMORY (sd);
} else if ((pAddr >= monitor_base) && (pAddr < (monitor_base + monitor_size))) {
index = ((unsigned int)(pAddr - monitor_base) & (monitor_size - 1));
mem = monitor;
}
if (mem == NULL)
sim_io_error(sd,"Simulator memory not found for physical address 0x%s\n",pr_addr(pAddr));
else {
int shift = 0;
#ifdef DEBUG
printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
#endif /* DEBUG */
if (AccessLength <= AccessLength_DOUBLEWORD) {
if (BigEndianMem) {
if (raw)
/* need to shift raw (least significant byte aligned) data
into correct byte slots */
shift = ((7 - AccessLength) * 8);
else /* real memory access */
shift = ((pAddr & LOADDRMASK) * 8);
MemElem <<= shift;
} else {
/* no need to shift raw little-endian data */
if (!raw)
MemElem >>= ((pAddr & LOADDRMASK) * 8);
}
}
#ifdef DEBUG
printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
#endif /* DEBUG */
if (BigEndianMem) {
switch (AccessLength) { /* big-endian memory */
case AccessLength_QUADWORD :
mem[index++] = (unsigned char)(MemElem1 >> 56);
MemElem1 <<= 8;
case 14 :
mem[index++] = (unsigned char)(MemElem1 >> 56);
MemElem1 <<= 8;
case 13 :
mem[index++] = (unsigned char)(MemElem1 >> 56);
MemElem1 <<= 8;
case 12 :
mem[index++] = (unsigned char)(MemElem1 >> 56);
MemElem1 <<= 8;
case 11 :
mem[index++] = (unsigned char)(MemElem1 >> 56);
MemElem1 <<= 8;
case 10 :
mem[index++] = (unsigned char)(MemElem1 >> 56);
MemElem1 <<= 8;
case 9 :
mem[index++] = (unsigned char)(MemElem1 >> 56);
MemElem1 <<= 8;
case 8 :
mem[index++] = (unsigned char)(MemElem1 >> 56);
case AccessLength_DOUBLEWORD :
mem[index++] = (unsigned char)(MemElem >> 56);
MemElem <<= 8;
case AccessLength_SEPTIBYTE :
mem[index++] = (unsigned char)(MemElem >> 56);
MemElem <<= 8;
case AccessLength_SEXTIBYTE :
mem[index++] = (unsigned char)(MemElem >> 56);
MemElem <<= 8;
case AccessLength_QUINTIBYTE :
mem[index++] = (unsigned char)(MemElem >> 56);
MemElem <<= 8;
case AccessLength_WORD :
mem[index++] = (unsigned char)(MemElem >> 56);
MemElem <<= 8;
case AccessLength_TRIPLEBYTE :
mem[index++] = (unsigned char)(MemElem >> 56);
MemElem <<= 8;
case AccessLength_HALFWORD :
mem[index++] = (unsigned char)(MemElem >> 56);
MemElem <<= 8;
case AccessLength_BYTE :
mem[index++] = (unsigned char)(MemElem >> 56);
break;
}
} else {
index += (AccessLength + 1);
switch (AccessLength) { /* little-endian memory */
case AccessLength_QUADWORD :
mem[--index] = (unsigned char)(MemElem1 >> 56);
case 14 :
mem[--index] = (unsigned char)(MemElem1 >> 48);
case 13 :
mem[--index] = (unsigned char)(MemElem1 >> 40);
case 12 :
mem[--index] = (unsigned char)(MemElem1 >> 32);
case 11 :
mem[--index] = (unsigned char)(MemElem1 >> 24);
case 10 :
mem[--index] = (unsigned char)(MemElem1 >> 16);
case 9 :
mem[--index] = (unsigned char)(MemElem1 >> 8);
case 8 :
mem[--index] = (unsigned char)(MemElem1 >> 0);
case AccessLength_DOUBLEWORD :
mem[--index] = (unsigned char)(MemElem >> 56);
case AccessLength_SEPTIBYTE :
mem[--index] = (unsigned char)(MemElem >> 48);
case AccessLength_SEXTIBYTE :
mem[--index] = (unsigned char)(MemElem >> 40);
case AccessLength_QUINTIBYTE :
mem[--index] = (unsigned char)(MemElem >> 32);
case AccessLength_WORD :
mem[--index] = (unsigned char)(MemElem >> 24);
case AccessLength_TRIPLEBYTE :
mem[--index] = (unsigned char)(MemElem >> 16);
case AccessLength_HALFWORD :
mem[--index] = (unsigned char)(MemElem >> 8);
case AccessLength_BYTE :
mem[--index] = (unsigned char)(MemElem >> 0);
break;
}
}
/* See also load_memory */
if (AccessLength <= AccessLength_DOUBLEWORD)
{
if (BigEndianMem)
/* for big endian target, byte (pAddr&LOADDRMASK == 0) is
shifted to the most significant byte position. */
MemElem >>= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
else
/* For little endian target, byte (pAddr&LOADDRMASK == 0)
is already in the correct postition. */
MemElem >>= ((pAddr & LOADDRMASK) * 8);
}
}
#ifdef DEBUG
printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
#endif /* DEBUG */
switch (AccessLength)
{
case AccessLength_QUADWORD :
{
unsigned_16 val = U16_8 (MemElem1, MemElem);
sim_core_write_aligned_16 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_write_map, pAddr, val);
break;
}
case AccessLength_DOUBLEWORD :
sim_core_write_aligned_8 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_write_map, pAddr, MemElem);
break;
case AccessLength_SEPTIBYTE :
sim_core_write_misaligned_7 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_write_map, pAddr, MemElem);
break;
case AccessLength_SEXTIBYTE :
sim_core_write_misaligned_6 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_write_map, pAddr, MemElem);
break;
case AccessLength_QUINTIBYTE :
sim_core_write_misaligned_5 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_write_map, pAddr, MemElem);
break;
case AccessLength_WORD :
sim_core_write_aligned_4 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_write_map, pAddr, MemElem);
break;
case AccessLength_TRIPLEBYTE :
sim_core_write_misaligned_3 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_write_map, pAddr, MemElem);
break;
case AccessLength_HALFWORD :
sim_core_write_aligned_2 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_write_map, pAddr, MemElem);
break;
case AccessLength_BYTE :
sim_core_write_aligned_1 (STATE_CPU (sd, 0), NULL_CIA,
sim_core_write_map, pAddr, MemElem);
break;
default:
abort ();
}
return;
}

View File

@ -1466,7 +1466,7 @@
int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));
byte = ((vaddr & mask) ^ bigend);
if (!!ByteSwapMem)
if (!BigEndianMem)
paddr &= ~mask;
LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);
GPR[destreg] = ((memval << ((7 - byte) * 8)) | (GPR[destreg] & (((unsigned64)1 << ((7 - byte) * 8)) - 1)));
@ -1510,7 +1510,7 @@
int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));
byte = ((vaddr & mask) ^ bigend);
if (!ByteSwapMem)
if (BigEndianMem)
paddr &= ~mask;
LoadMemory(&memval,&memval1,uncached,(7 - byte),paddr,vaddr,isDATA,isREAL);
{
@ -1864,7 +1864,7 @@
int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));
byte = ((vaddr & mask) ^ bigend);
if (!!ByteSwapMem)
if (!BigEndianMem)
paddr &= ~mask;
LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);
if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {
@ -1914,7 +1914,7 @@
int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));
byte = ((vaddr & mask) ^ bigend);
if (!ByteSwapMem)
if (BigEndianMem)
paddr &= ~mask;
LoadMemory(&memval,&memval1,uncached,(3 - byte),paddr,vaddr,isDATA,isREAL);
if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {
@ -2497,7 +2497,7 @@
int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));
byte = ((vaddr & mask) ^ bigend);
if (!!ByteSwapMem)
if (!BigEndianMem)
paddr &= ~mask;
memval = (op2 >> (8 * (7 - byte)));
StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);
@ -2541,7 +2541,7 @@
int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));
byte = ((vaddr & mask) ^ bigend);
if (!ByteSwapMem)
if (!BigEndianMem)
paddr &= ~mask;
memval = ((unsigned64) op2 << (byte * 8));
StoreMemory(uncached,(AccessLength_DOUBLEWORD - byte),memval,memval1,paddr,vaddr,isREAL);
@ -2996,7 +2996,7 @@
int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));
byte = ((vaddr & mask) ^ bigend);
if (!!ByteSwapMem)
if (!BigEndianMem)
paddr &= ~mask;
memval = (op2 >> (8 * (3 - byte)));
if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {
@ -3045,7 +3045,7 @@
int byte;
paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));
byte = ((vaddr & mask) ^ bigend);
if (!ByteSwapMem)
if (!BigEndianMem)
paddr &= ~mask;
memval = ((unsigned64) op2 << (byte * 8));
if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {

View File

@ -26,16 +26,24 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define SIM_ENGINE_RESUME_HOOK(SD, LAST_CPU, CIA)
#define SIM_HAVE_BIENDIAN
#define SIM_HAVE_FLATMEM
/* hobble some common features for moment */
#define WITH_WATCHPOINTS 1
#define WITH_MODULO_MEMORY 1
#include "sim-basics.h"
typedef address_word sim_cia;
#if (WITH_IGEN)
/* Get the number of instructions. FIXME: must be a more elegant way
of doing this. */
#include "itable.h"
#define MAX_INSNS (nr_itable_entries)
#define INSN_NAME(i) itable[(i)].name
#endif
#include "sim-base.h"
@ -579,10 +587,6 @@ struct sim_state {
#define BigEndianMem (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
/*(state & simBE) ? 1 : 0)*/
/* ByteSwapMem */
/* This is true if the host and target have different endianness. */
#define ByteSwapMem (CURRENT_TARGET_BYTE_ORDER != CURRENT_HOST_BYTE_ORDER)
/* ReverseEndian */
/* This mode is selected if in User mode with the RE bit being set in
SR (Status Register). It reverses the endianness of load and store
@ -691,13 +695,13 @@ int address_translation PARAMS ((SIM_DESC sd, address_word vAddr, int IorD, int
#define AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) \
address_translation(sd, vAddr,IorD,LorS,pAddr,CCA,raw)
void load_memory PARAMS ((SIM_DESC sd, uword64* memvalp, uword64* memval1p, int CCA, int AccessLength, address_word pAddr, address_word vAddr, int IorD, int raw));
void load_memory PARAMS ((SIM_DESC sd, uword64* memvalp, uword64* memval1p, int CCA, int AccessLength, address_word pAddr, address_word vAddr, int IorD));
#define LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) \
load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw)
load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD)
void store_memory PARAMS ((SIM_DESC sd, int CCA, int AccessLength, uword64 MemElem, uword64 MemElem1, address_word pAddr, address_word vAddr, int raw));
void store_memory PARAMS ((SIM_DESC sd, int CCA, int AccessLength, uword64 MemElem, uword64 MemElem1, address_word pAddr, address_word vAddr));
#define StoreMemory(CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw) \
store_memory(sd,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw)
store_memory(sd,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr)
void cache_op PARAMS ((SIM_DESC sd, int op, address_word pAddr, address_word vAddr, unsigned int instruction));
#define CacheOp(op,pAddr,vAddr,instruction) cache_op(sd,op,pAddr,vAddr,instruction)