sim: cr16: convert to common sim memory modules
The cr16 port has a lot of translation/offset logic baked into it, but it all looks like copy & paste from the d10v port rather than something the cr16 port wants.
This commit is contained in:
parent
267b3b8e06
commit
761e171ad8
|
@ -1,3 +1,9 @@
|
|||
2015-11-15 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* sim-cr16.h (SIM_CR16_MEMORY_UNIFIED, SIM_CR16_MEMORY_INSN,
|
||||
SIM_CR16_MEMORY_DATA, SIM_CR16_MEMORY_DMAP, SIM_CR16_MEMORY_IMAP):
|
||||
Delete.
|
||||
|
||||
2015-11-14 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* sim-arm.h: Delete __cplusplus checks and extern "C" linkage.
|
||||
|
|
|
@ -20,15 +20,6 @@
|
|||
#if !defined (SIM_CR16_H)
|
||||
#define SIM_CR16_H
|
||||
|
||||
enum
|
||||
{
|
||||
SIM_CR16_MEMORY_UNIFIED = 0x00000000,
|
||||
SIM_CR16_MEMORY_INSN = 0x10000000,
|
||||
SIM_CR16_MEMORY_DATA = 0x10000000,
|
||||
SIM_CR16_MEMORY_DMAP = 0x10000000,
|
||||
SIM_CR16_MEMORY_IMAP = 0x10000000
|
||||
};
|
||||
|
||||
/* The simulator makes use of the following register information. */
|
||||
|
||||
enum sim_cr16_regs
|
||||
|
|
|
@ -1,3 +1,31 @@
|
|||
2015-11-15 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* Makefile.in (SIM_OBJS): Delete endian.o.
|
||||
(INCLUDE): Delete endian.c.
|
||||
* configure.ac (SIM_AC_OPTION_ENDIAN): Declare little endian.
|
||||
(SIM_AC_OPTION_ALIGNMENT): release unaligned loads.
|
||||
* configure: Regenerate.
|
||||
* cr16_sim.h (IMAP_BLOCK_SIZE, DMAP_BLOCK_SIZE, SEGMENT_SIZE,
|
||||
IMEM_SEGMENTS, DMEM_SEGMENTS, UMEM_SEGMENTS, cr16_memory, dmem_addr,
|
||||
imem_addr, decode_pc, get_longword, get_word, write_word,
|
||||
write_longword, READ_16): Delete.
|
||||
(struct _state): Delete mem member.
|
||||
(endian.c): Delete include.
|
||||
(SB, RB, SW, RW, SLW): Rewrite to use sim-core functions.
|
||||
(get_longword): New function.
|
||||
(RLW): Rewrite to use get_longword.
|
||||
* endian.c: Delete file.
|
||||
* interp.c (map_memory, sim_size, last_segname, last_from, last_to,
|
||||
IMAP0_OFFSET, DMAP0_OFFSET, DMAP2_SHADDOW, DMAP2_OFFSET,
|
||||
dmap_register, imap_register, sim_cr16_translate_dmap_addr,
|
||||
sim_cr16_translate_imap_addr, sim_cr16_translate_addr, map_memory,
|
||||
xfer_mem, sim_write, sim_read, dmem_addr, imem_addr): Delete.
|
||||
(do_run): Delete iaddr and replace imem_addr/get_longword with RW.
|
||||
(sim_open): Call sim_do_commandf. Delete sim_size call.
|
||||
(sim_resume): Delete iaddr and replace imem_addr/get_longword with
|
||||
RLW.
|
||||
* simops.c (MEMPTR): Rewrite to use sim_core_trans_addr.
|
||||
|
||||
2015-11-15 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* cr16_sim.h (struct simops): Add SIM_DESC and SIM_CPU to func args.
|
||||
|
|
|
@ -23,11 +23,10 @@ SIM_OBJS = \
|
|||
sim-reg.o \
|
||||
interp.o \
|
||||
table.o \
|
||||
simops.o \
|
||||
endian.o
|
||||
simops.o
|
||||
SIM_EXTRA_CLEAN = clean-extra
|
||||
|
||||
INCLUDE = cr16_sim.h $(srcroot)/include/gdb/callback.h targ-vals.h endian.c \
|
||||
INCLUDE = cr16_sim.h $(srcroot)/include/gdb/callback.h targ-vals.h \
|
||||
$(srcroot)/include/gdb/sim-cr16.h
|
||||
|
||||
# This selects the cr16 newlib/libgloss syscall definitions.
|
||||
|
|
|
@ -12914,7 +12914,7 @@ sim_link_links="${sim_link_links} targ-vals.def"
|
|||
|
||||
|
||||
|
||||
wire_endian=""
|
||||
wire_endian="LITTLE_ENDIAN"
|
||||
default_endian=""
|
||||
# Check whether --enable-sim-endian was given.
|
||||
if test "${enable_sim_endian+set}" = set; then :
|
||||
|
@ -12958,8 +12958,8 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
wire_alignment="STRICT_ALIGNMENT"
|
||||
default_alignment="STRICT_ALIGNMENT"
|
||||
wire_alignment="NONSTRICT_ALIGNMENT"
|
||||
default_alignment=""
|
||||
|
||||
# Check whether --enable-sim-alignment was given.
|
||||
if test "${enable_sim_alignment+set}" = set; then :
|
||||
|
|
|
@ -5,8 +5,8 @@ sinclude(../common/acinclude.m4)
|
|||
|
||||
SIM_AC_COMMON
|
||||
|
||||
SIM_AC_OPTION_ENDIAN
|
||||
SIM_AC_OPTION_ALIGNMENT(STRICT_ALIGNMENT,STRICT_ALIGNMENT)
|
||||
SIM_AC_OPTION_ENDIAN(LITTLE_ENDIAN)
|
||||
SIM_AC_OPTION_ALIGNMENT(NONSTRICT_ALIGNMENT)
|
||||
SIM_AC_OPTION_HOSTENDIAN
|
||||
SIM_AC_OPTION_ENVIRONMENT
|
||||
SIM_AC_OPTION_INLINE
|
||||
|
|
|
@ -198,37 +198,6 @@ enum {
|
|||
} \
|
||||
while (0)
|
||||
|
||||
/* cr16 memory: There are three separate cr16 memory regions IMEM,
|
||||
UMEM and DMEM. The IMEM and DMEM are further broken down into
|
||||
blocks (very like VM pages). */
|
||||
|
||||
enum
|
||||
{
|
||||
IMAP_BLOCK_SIZE = 0x2000000,
|
||||
DMAP_BLOCK_SIZE = 0x4000000
|
||||
};
|
||||
|
||||
/* Implement the three memory regions using sparse arrays. Allocate
|
||||
memory using ``segments''. A segment must be at least as large as
|
||||
a BLOCK - ensures that an access that doesn't cross a block
|
||||
boundary can't cross a segment boundary */
|
||||
|
||||
enum
|
||||
{
|
||||
SEGMENT_SIZE = 0x2000000, /* 128KB - MAX(IMAP_BLOCK_SIZE,DMAP_BLOCK_SIZE) */
|
||||
IMEM_SEGMENTS = 8, /* 1MB */
|
||||
DMEM_SEGMENTS = 8, /* 1MB */
|
||||
UMEM_SEGMENTS = 128 /* 16MB */
|
||||
};
|
||||
|
||||
struct cr16_memory
|
||||
{
|
||||
uint8 *insn[IMEM_SEGMENTS];
|
||||
uint8 *data[DMEM_SEGMENTS];
|
||||
uint8 *unif[UMEM_SEGMENTS];
|
||||
uint8 fault[16];
|
||||
};
|
||||
|
||||
struct _state
|
||||
{
|
||||
creg_t regs[16]; /* general-purpose registers */
|
||||
|
@ -274,8 +243,6 @@ struct _state
|
|||
/* NOTE: everything below this line is not reset by
|
||||
sim_create_inferior() */
|
||||
|
||||
struct cr16_memory mem;
|
||||
|
||||
enum _ins_type ins_type;
|
||||
|
||||
} State;
|
||||
|
@ -421,30 +388,19 @@ enum
|
|||
/* sign-extend a 32-bit number */
|
||||
#define SEXT32(x) ((((x)&0xffffffff)^(~0x7fffffff))+0x80000000)
|
||||
|
||||
extern uint8 *dmem_addr (SIM_DESC, SIM_CPU *, uint32 offset);
|
||||
extern uint8 *imem_addr (SIM_DESC, SIM_CPU *, uint32);
|
||||
extern bfd_vma decode_pc (void);
|
||||
#define SB(addr, data) sim_core_write_1 (cpu, PC, read_map, addr, data)
|
||||
#define RB(addr) sim_core_read_1 (cpu, PC, read_map, addr)
|
||||
#define SW(addr, data) sim_core_write_unaligned_2 (cpu, PC, read_map, addr, data)
|
||||
#define RW(addr) sim_core_read_unaligned_2 (cpu, PC, read_map, addr)
|
||||
#define SLW(addr, data) sim_core_write_unaligned_4 (cpu, PC, read_map, addr, data)
|
||||
|
||||
#define RB(x) (*(dmem_addr (sd, cpu, x)))
|
||||
#define SB(addr,data) ( RB(addr) = (data & 0xff))
|
||||
|
||||
#if defined(__GNUC__) && defined(__OPTIMIZE__) && !defined(NO_ENDIAN_INLINE)
|
||||
#define ENDIAN_INLINE static __inline__
|
||||
#include "endian.c"
|
||||
#undef ENDIAN_INLINE
|
||||
|
||||
#else
|
||||
extern uint32 get_longword (uint8 *);
|
||||
extern uint16 get_word (uint8 *);
|
||||
extern void write_word (uint8 *addr, uint16 data);
|
||||
extern void write_longword (uint8 *addr, uint32 data);
|
||||
#endif
|
||||
|
||||
#define SW(addr,data) write_word (dmem_addr (sd, cpu, addr), data)
|
||||
#define RW(x) get_word (dmem_addr (sd, cpu, x))
|
||||
#define SLW(addr,data) write_longword (dmem_addr (sd, cpu, addr), data)
|
||||
#define RLW(x) get_longword (dmem_addr (sd, cpu, x))
|
||||
#define READ_16(x) get_word(x)
|
||||
/* Yes, this is as whacked as it looks. The sim currently reads little endian
|
||||
for 16 bits, but then merge them like big endian to get 32 bits. */
|
||||
static inline uint32 get_longword (SIM_CPU *cpu, address_word addr)
|
||||
{
|
||||
return (RW (addr) << 16) | RW (addr + 2);
|
||||
}
|
||||
#define RLW(addr) get_longword (cpu, addr)
|
||||
|
||||
#define JMP(x) do { SET_PC (x); State.pc_changed = 1; } while (0)
|
||||
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/* Simulation code for the CR16 processor.
|
||||
Copyright (C) 2008-2015 Free Software Foundation, Inc.
|
||||
Contributed by M Ranga Swami Reddy <MR.Swami.Reddy@nsc.com>
|
||||
|
||||
This file is part of GDB, the GNU debugger.
|
||||
|
||||
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, 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/>. */
|
||||
|
||||
|
||||
/* If we're being compiled as a .c file, rather than being included in
|
||||
cr16_sim.h, then ENDIAN_INLINE won't be defined yet. */
|
||||
|
||||
#ifndef ENDIAN_INLINE
|
||||
#define NO_ENDIAN_INLINE
|
||||
#include "sim-main.h"
|
||||
#define ENDIAN_INLINE
|
||||
#endif
|
||||
|
||||
ENDIAN_INLINE uint16
|
||||
get_word (uint8 *x)
|
||||
{
|
||||
return *(uint16 *)x;
|
||||
}
|
||||
|
||||
ENDIAN_INLINE uint32
|
||||
get_longword (uint8 *x)
|
||||
{
|
||||
return (((uint32) *(uint16 *)x) << 16) | ((uint32) *(uint16 *)(x+2));
|
||||
}
|
||||
|
||||
ENDIAN_INLINE void
|
||||
write_word (uint8 *addr, uint16 data)
|
||||
{
|
||||
addr[1] = (data >> 8) & 0xff;
|
||||
addr[0] = data & 0xff;
|
||||
|
||||
}
|
||||
|
||||
ENDIAN_INLINE void
|
||||
write_longword (uint8 *addr, uint32 data)
|
||||
{
|
||||
*(uint16 *)(addr + 2) = (uint16)(data >> 16);
|
||||
*(uint16 *)(addr) = (uint16)data;
|
||||
}
|
|
@ -42,7 +42,6 @@ uint32 sign_flag;
|
|||
|
||||
static struct hash_entry *lookup_hash (SIM_DESC, SIM_CPU *, uint64 ins, int size);
|
||||
static void get_operands (operand_desc *s, uint64 mcode, int isize, int nops);
|
||||
static INLINE uint8 *map_memory (SIM_DESC, SIM_CPU *, unsigned phys_addr);
|
||||
|
||||
#define MAX_HASH 16
|
||||
|
||||
|
@ -335,7 +334,6 @@ do_run (SIM_DESC sd, SIM_CPU *cpu, uint64 mcode)
|
|||
struct simops *s= Simops;
|
||||
struct hash_entry *h;
|
||||
char func[12]="\0";
|
||||
uint8 *iaddr;
|
||||
#ifdef DEBUG
|
||||
if ((cr16_debug & DEBUG_INSTRUCTION) != 0)
|
||||
(*cr16_callback->printf_filtered) (cr16_callback, "do_long 0x%x\n", mcode);
|
||||
|
@ -346,11 +344,8 @@ do_run (SIM_DESC sd, SIM_CPU *cpu, uint64 mcode)
|
|||
if ((h == NULL) || (h->opcode == 0))
|
||||
return 0;
|
||||
|
||||
if (h->size == 3)
|
||||
{
|
||||
iaddr = imem_addr (sd, cpu, (uint32)PC + 2);
|
||||
mcode = (mcode << 16) | get_longword( iaddr );
|
||||
}
|
||||
if (h->size == 3)
|
||||
mcode = (mcode << 16) | RW (PC + 4);
|
||||
|
||||
/* Re-set OP list. */
|
||||
OP[0] = OP[1] = OP[2] = OP[3] = sign_flag = 0;
|
||||
|
@ -370,389 +365,6 @@ do_run (SIM_DESC sd, SIM_CPU *cpu, uint64 mcode)
|
|||
return h->size;
|
||||
}
|
||||
|
||||
static void
|
||||
sim_size (int power)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < IMEM_SEGMENTS; i++)
|
||||
{
|
||||
if (State.mem.insn[i])
|
||||
free (State.mem.insn[i]);
|
||||
}
|
||||
for (i = 0; i < DMEM_SEGMENTS; i++)
|
||||
{
|
||||
if (State.mem.data[i])
|
||||
free (State.mem.data[i]);
|
||||
}
|
||||
for (i = 0; i < UMEM_SEGMENTS; i++)
|
||||
{
|
||||
if (State.mem.unif[i])
|
||||
free (State.mem.unif[i]);
|
||||
}
|
||||
/* Always allocate dmem segment 0. This contains the IMAP and DMAP
|
||||
registers. */
|
||||
State.mem.data[0] = calloc (1, SEGMENT_SIZE);
|
||||
}
|
||||
|
||||
/* For tracing - leave info on last access around. */
|
||||
static char *last_segname = "invalid";
|
||||
static char *last_from = "invalid";
|
||||
static char *last_to = "invalid";
|
||||
|
||||
enum
|
||||
{
|
||||
IMAP0_OFFSET = 0xff00,
|
||||
DMAP0_OFFSET = 0xff08,
|
||||
DMAP2_SHADDOW = 0xff04,
|
||||
DMAP2_OFFSET = 0xff0c
|
||||
};
|
||||
|
||||
static unsigned long
|
||||
dmap_register (SIM_DESC sd, SIM_CPU *cpu, void *regcache, int reg_nr)
|
||||
{
|
||||
uint8 *raw = map_memory (sd, cpu, SIM_CR16_MEMORY_DATA
|
||||
+ DMAP0_OFFSET + 2 * reg_nr);
|
||||
return READ_16 (raw);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
imap_register (SIM_DESC sd, SIM_CPU *cpu, void *regcache, int reg_nr)
|
||||
{
|
||||
uint8 *raw = map_memory (sd, cpu, SIM_CR16_MEMORY_DATA
|
||||
+ IMAP0_OFFSET + 2 * reg_nr);
|
||||
return READ_16 (raw);
|
||||
}
|
||||
|
||||
/* Given a virtual address in the DMAP address space, translate it
|
||||
into a physical address. */
|
||||
|
||||
static unsigned long
|
||||
sim_cr16_translate_dmap_addr (SIM_DESC sd,
|
||||
SIM_CPU *cpu,
|
||||
unsigned long offset,
|
||||
int nr_bytes,
|
||||
unsigned long *phys,
|
||||
void *regcache,
|
||||
unsigned long (*dmap_register) (SIM_DESC,
|
||||
SIM_CPU *,
|
||||
void *regcache,
|
||||
int reg_nr))
|
||||
{
|
||||
short map;
|
||||
int regno;
|
||||
last_from = "logical-data";
|
||||
if (offset >= DMAP_BLOCK_SIZE * SIM_CR16_NR_DMAP_REGS)
|
||||
{
|
||||
/* Logical address out side of data segments, not supported */
|
||||
return 0;
|
||||
}
|
||||
regno = (offset / DMAP_BLOCK_SIZE);
|
||||
offset = (offset % DMAP_BLOCK_SIZE);
|
||||
|
||||
#if 1
|
||||
if ((offset % DMAP_BLOCK_SIZE) + nr_bytes > DMAP_BLOCK_SIZE)
|
||||
{
|
||||
/* Don't cross a BLOCK boundary */
|
||||
nr_bytes = DMAP_BLOCK_SIZE - (offset % DMAP_BLOCK_SIZE);
|
||||
}
|
||||
map = dmap_register (sd, cpu, regcache, regno);
|
||||
if (regno == 3)
|
||||
{
|
||||
/* Always maps to data memory */
|
||||
int iospi = (offset / 0x1000) % 4;
|
||||
int iosp = (map >> (4 * (3 - iospi))) % 0x10;
|
||||
last_to = "io-space";
|
||||
*phys = (SIM_CR16_MEMORY_DATA + (iosp * 0x10000) + 0xc000 + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
int sp = ((map & 0x3000) >> 12);
|
||||
int segno = (map & 0x3ff);
|
||||
switch (sp)
|
||||
{
|
||||
case 0: /* 00: Unified memory */
|
||||
*phys = SIM_CR16_MEMORY_UNIFIED + (segno * DMAP_BLOCK_SIZE) + offset;
|
||||
last_to = "unified";
|
||||
break;
|
||||
case 1: /* 01: Instruction Memory */
|
||||
*phys = SIM_CR16_MEMORY_INSN + (segno * DMAP_BLOCK_SIZE) + offset;
|
||||
last_to = "chip-insn";
|
||||
break;
|
||||
case 2: /* 10: Internal data memory */
|
||||
*phys = SIM_CR16_MEMORY_DATA + (segno << 16) + (regno * DMAP_BLOCK_SIZE) + offset;
|
||||
last_to = "chip-data";
|
||||
break;
|
||||
case 3: /* 11: Reserved */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
/* Given a virtual address in the IMAP address space, translate it
|
||||
into a physical address. */
|
||||
|
||||
static unsigned long
|
||||
sim_cr16_translate_imap_addr (SIM_DESC sd,
|
||||
SIM_CPU *cpu,
|
||||
unsigned long offset,
|
||||
int nr_bytes,
|
||||
unsigned long *phys,
|
||||
void *regcache,
|
||||
unsigned long (*imap_register) (SIM_DESC,
|
||||
SIM_CPU *,
|
||||
void *regcache,
|
||||
int reg_nr))
|
||||
{
|
||||
short map;
|
||||
int regno;
|
||||
int sp;
|
||||
int segno;
|
||||
last_from = "logical-insn";
|
||||
if (offset >= (IMAP_BLOCK_SIZE * SIM_CR16_NR_IMAP_REGS))
|
||||
{
|
||||
/* Logical address outside of IMAP segments, not supported */
|
||||
return 0;
|
||||
}
|
||||
regno = (offset / IMAP_BLOCK_SIZE);
|
||||
offset = (offset % IMAP_BLOCK_SIZE);
|
||||
if (offset + nr_bytes > IMAP_BLOCK_SIZE)
|
||||
{
|
||||
/* Don't cross a BLOCK boundary */
|
||||
nr_bytes = IMAP_BLOCK_SIZE - offset;
|
||||
}
|
||||
map = imap_register (sd, cpu, regcache, regno);
|
||||
sp = (map & 0x3000) >> 12;
|
||||
segno = (map & 0x007f);
|
||||
switch (sp)
|
||||
{
|
||||
case 0: /* 00: unified memory */
|
||||
*phys = SIM_CR16_MEMORY_UNIFIED + (segno << 17) + offset;
|
||||
last_to = "unified";
|
||||
break;
|
||||
case 1: /* 01: instruction memory */
|
||||
*phys = SIM_CR16_MEMORY_INSN + (IMAP_BLOCK_SIZE * regno) + offset;
|
||||
last_to = "chip-insn";
|
||||
break;
|
||||
case 2: /*10*/
|
||||
/* Reserved. */
|
||||
return 0;
|
||||
case 3: /* 11: for testing - instruction memory */
|
||||
offset = (offset % 0x800);
|
||||
*phys = SIM_CR16_MEMORY_INSN + offset;
|
||||
if (offset + nr_bytes > 0x800)
|
||||
/* don't cross VM boundary */
|
||||
nr_bytes = 0x800 - offset;
|
||||
last_to = "test-insn";
|
||||
break;
|
||||
}
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
sim_cr16_translate_addr (SIM_DESC sd,
|
||||
SIM_CPU *cpu,
|
||||
unsigned long memaddr,
|
||||
int nr_bytes,
|
||||
unsigned long *targ_addr,
|
||||
void *regcache,
|
||||
unsigned long (*dmap_register) (SIM_DESC,
|
||||
SIM_CPU *,
|
||||
void *regcache,
|
||||
int reg_nr),
|
||||
unsigned long (*imap_register) (SIM_DESC,
|
||||
SIM_CPU *,
|
||||
void *regcache,
|
||||
int reg_nr))
|
||||
{
|
||||
unsigned long phys;
|
||||
unsigned long seg;
|
||||
unsigned long off;
|
||||
|
||||
last_from = "unknown";
|
||||
last_to = "unknown";
|
||||
|
||||
seg = (memaddr >> 24);
|
||||
off = (memaddr & 0xffffffL);
|
||||
|
||||
switch (seg)
|
||||
{
|
||||
case 0x00: /* Physical unified memory */
|
||||
last_from = "phys-unified";
|
||||
last_to = "unified";
|
||||
phys = SIM_CR16_MEMORY_UNIFIED + off;
|
||||
if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE)
|
||||
nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE);
|
||||
break;
|
||||
|
||||
case 0x01: /* Physical instruction memory */
|
||||
last_from = "phys-insn";
|
||||
last_to = "chip-insn";
|
||||
phys = SIM_CR16_MEMORY_INSN + off;
|
||||
if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE)
|
||||
nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE);
|
||||
break;
|
||||
|
||||
case 0x02: /* Physical data memory segment */
|
||||
last_from = "phys-data";
|
||||
last_to = "chip-data";
|
||||
phys = SIM_CR16_MEMORY_DATA + off;
|
||||
if ((off % SEGMENT_SIZE) + nr_bytes > SEGMENT_SIZE)
|
||||
nr_bytes = SEGMENT_SIZE - (off % SEGMENT_SIZE);
|
||||
break;
|
||||
|
||||
case 0x10: /* in logical data address segment */
|
||||
nr_bytes = sim_cr16_translate_dmap_addr (sd, cpu, off, nr_bytes, &phys,
|
||||
regcache, dmap_register);
|
||||
break;
|
||||
|
||||
case 0x11: /* in logical instruction address segment */
|
||||
nr_bytes = sim_cr16_translate_imap_addr (sd, cpu, off, nr_bytes, &phys,
|
||||
regcache, imap_register);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
*targ_addr = phys;
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
/* Return a pointer into the raw buffer designated by phys_addr. It
|
||||
is assumed that the client has already ensured that the access
|
||||
isn't going to cross a segment boundary. */
|
||||
|
||||
uint8 *
|
||||
map_memory (SIM_DESC sd, SIM_CPU *cpu, unsigned phys_addr)
|
||||
{
|
||||
uint8 **memory;
|
||||
uint8 *raw;
|
||||
unsigned offset;
|
||||
int segment = ((phys_addr >> 24) & 0xff);
|
||||
|
||||
switch (segment)
|
||||
{
|
||||
|
||||
case 0x00: /* Unified memory */
|
||||
{
|
||||
memory = &State.mem.unif[(phys_addr / SEGMENT_SIZE) % UMEM_SEGMENTS];
|
||||
last_segname = "umem";
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x01: /* On-chip insn memory */
|
||||
{
|
||||
memory = &State.mem.insn[(phys_addr / SEGMENT_SIZE) % IMEM_SEGMENTS];
|
||||
last_segname = "imem";
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x02: /* On-chip data memory */
|
||||
{
|
||||
if ((phys_addr & 0xff00) == 0xff00)
|
||||
{
|
||||
phys_addr = (phys_addr & 0xffff);
|
||||
if (phys_addr == DMAP2_SHADDOW)
|
||||
{
|
||||
phys_addr = DMAP2_OFFSET;
|
||||
last_segname = "dmap";
|
||||
}
|
||||
else
|
||||
last_segname = "reg";
|
||||
}
|
||||
else
|
||||
last_segname = "dmem";
|
||||
memory = &State.mem.data[(phys_addr / SEGMENT_SIZE) % DMEM_SEGMENTS];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* OOPS! */
|
||||
last_segname = "scrap";
|
||||
return State.mem.fault;
|
||||
}
|
||||
|
||||
if (*memory == NULL)
|
||||
{
|
||||
*memory = calloc (1, SEGMENT_SIZE);
|
||||
if (*memory == NULL)
|
||||
{
|
||||
(*cr16_callback->printf_filtered) (cr16_callback, "Malloc failed.\n");
|
||||
return State.mem.fault;
|
||||
}
|
||||
}
|
||||
|
||||
offset = (phys_addr % SEGMENT_SIZE);
|
||||
raw = *memory + offset;
|
||||
return raw;
|
||||
}
|
||||
|
||||
/* Transfer data to/from simulated memory. Since a bug in either the
|
||||
simulated program or in gdb or the simulator itself may cause a
|
||||
bogus address to be passed in, we need to do some sanity checking
|
||||
on addresses to make sure they are within bounds. When an address
|
||||
fails the bounds check, treat it as a zero length read/write rather
|
||||
than aborting the entire run. */
|
||||
|
||||
static int
|
||||
xfer_mem (SIM_DESC sd, SIM_ADDR virt,
|
||||
unsigned char *buffer,
|
||||
int size,
|
||||
int write_p)
|
||||
{
|
||||
host_callback *cr16_callback = STATE_CALLBACK (sd);
|
||||
uint8 *memory;
|
||||
unsigned long phys;
|
||||
int phys_size;
|
||||
phys_size = sim_cr16_translate_addr (sd, NULL, virt, size, &phys, NULL,
|
||||
dmap_register, imap_register);
|
||||
if (phys_size == 0)
|
||||
return 0;
|
||||
|
||||
memory = map_memory (sd, NULL, phys);
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((cr16_debug & DEBUG_INSTRUCTION) != 0)
|
||||
{
|
||||
(*cr16_callback->printf_filtered)
|
||||
(cr16_callback,
|
||||
"sim_%s %d bytes: 0x%08lx (%s) -> 0x%08lx (%s) -> 0x%08lx (%s)\n",
|
||||
(write_p ? "write" : "read"),
|
||||
phys_size, virt, last_from,
|
||||
phys, last_to,
|
||||
(long) memory, last_segname);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (write_p)
|
||||
{
|
||||
memcpy (memory, buffer, phys_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (buffer, memory, phys_size);
|
||||
}
|
||||
|
||||
return phys_size;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
|
||||
{
|
||||
/* FIXME: this should be performing a virtual transfer */
|
||||
return xfer_mem (sd, addr, buffer, size, 1);
|
||||
}
|
||||
|
||||
int
|
||||
sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
|
||||
{
|
||||
/* FIXME: this should be performing a virtual transfer */
|
||||
return xfer_mem (sd, addr, buffer, size, 0);
|
||||
}
|
||||
|
||||
static sim_cia
|
||||
cr16_pc_get (sim_cpu *cpu)
|
||||
{
|
||||
|
@ -848,6 +460,14 @@ sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *cb, struct bfd *abfd,
|
|||
CPU_PC_STORE (cpu) = cr16_pc_set;
|
||||
}
|
||||
|
||||
/* The CR16 has an interrupt controller at 0xFC00, but we don't currently
|
||||
handle that. Revisit if anyone ever implements operating mode. */
|
||||
/* cr16 memory: There are three separate cr16 memory regions IMEM,
|
||||
UMEM and DMEM. The IMEM and DMEM are further broken down into
|
||||
blocks (very like VM pages). This might not match the hardware,
|
||||
but it matches what the toolchain currently expects. Ugh. */
|
||||
sim_do_commandf (sd, "memory-size %#x", 20 * 1024 * 1024);
|
||||
|
||||
cr16_callback = cb;
|
||||
|
||||
/* put all the opcodes in the hash table. */
|
||||
|
@ -956,72 +576,9 @@ sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *cb, struct bfd *abfd,
|
|||
}
|
||||
}
|
||||
|
||||
/* reset the processor state */
|
||||
if (!State.mem.data[0])
|
||||
sim_size (1);
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
uint8 *
|
||||
dmem_addr (SIM_DESC sd, SIM_CPU *cpu, uint32 offset)
|
||||
{
|
||||
unsigned long phys;
|
||||
uint8 *mem;
|
||||
int phys_size;
|
||||
|
||||
/* Note: DMEM address range is 0..0x10000. Calling code can compute
|
||||
things like ``0xfffe + 0x0e60 == 0x10e5d''. Since offset's type
|
||||
is uint16 this is modulo'ed onto 0x0e5d. */
|
||||
|
||||
phys_size = sim_cr16_translate_dmap_addr (sd, cpu, offset, 1, &phys, NULL,
|
||||
dmap_register);
|
||||
if (phys_size == 0)
|
||||
{
|
||||
mem = State.mem.fault;
|
||||
}
|
||||
else
|
||||
mem = map_memory (sd, cpu, phys);
|
||||
#ifdef DEBUG
|
||||
if ((cr16_debug & DEBUG_MEMORY))
|
||||
{
|
||||
(*cr16_callback->printf_filtered)
|
||||
(cr16_callback,
|
||||
"mem: 0x%08x (%s) -> 0x%08lx %d (%s) -> 0x%08lx (%s)\n",
|
||||
offset, last_from,
|
||||
phys, phys_size, last_to,
|
||||
(long) mem, last_segname);
|
||||
}
|
||||
#endif
|
||||
return mem;
|
||||
}
|
||||
|
||||
uint8 *
|
||||
imem_addr (SIM_DESC sd, SIM_CPU *cpu, uint32 offset)
|
||||
{
|
||||
unsigned long phys;
|
||||
uint8 *mem;
|
||||
int phys_size = sim_cr16_translate_imap_addr (sd, cpu, offset, 1, &phys, NULL,
|
||||
imap_register);
|
||||
if (phys_size == 0)
|
||||
{
|
||||
return State.mem.fault;
|
||||
}
|
||||
mem = map_memory (sd, cpu, phys);
|
||||
#ifdef DEBUG
|
||||
if ((cr16_debug & DEBUG_MEMORY))
|
||||
{
|
||||
(*cr16_callback->printf_filtered)
|
||||
(cr16_callback,
|
||||
"mem: 0x%08x (%s) -> 0x%08lx %d (%s) -> 0x%08lx (%s)\n",
|
||||
offset, last_from,
|
||||
phys, phys_size, last_to,
|
||||
(long) mem, last_segname);
|
||||
}
|
||||
#endif
|
||||
return mem;
|
||||
}
|
||||
|
||||
static int stop_simulator = 0;
|
||||
|
||||
int
|
||||
|
@ -1038,8 +595,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
|
|||
{
|
||||
SIM_CPU *cpu = STATE_CPU (sd, 0);
|
||||
uint32 curr_ins_size = 0;
|
||||
uint64 mcode = 0;
|
||||
uint8 *iaddr;
|
||||
uint64 mcode;
|
||||
|
||||
#ifdef DEBUG
|
||||
// (*cr16_callback->printf_filtered) (cr16_callback, "sim_resume (%d,%d) PC=0x%x\n",step,siggnal,PC);
|
||||
|
@ -1076,19 +632,8 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
|
|||
|
||||
do
|
||||
{
|
||||
iaddr = imem_addr (sd, cpu, (uint32)PC);
|
||||
if (iaddr == State.mem.fault)
|
||||
{
|
||||
#ifdef SIGBUS
|
||||
State.exception = SIGBUS;
|
||||
#else
|
||||
State.exception = SIGSEGV;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
mcode = get_longword( iaddr );
|
||||
|
||||
mcode = RLW (PC);
|
||||
|
||||
State.pc_changed = 0;
|
||||
|
||||
curr_ins_size = do_run (sd, cpu, mcode);
|
||||
|
@ -1134,7 +679,7 @@ sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env)
|
|||
bfd_vma start_address;
|
||||
|
||||
/* reset all state information */
|
||||
memset (&State.regs, 0, (uintptr_t)&State.mem - (uintptr_t)&State.regs);
|
||||
memset (&State, 0, sizeof (State));
|
||||
|
||||
/* There was a hack here to copy the values of argc and argv into r0
|
||||
and r1. The values were also saved into some high memory that
|
||||
|
|
|
@ -5143,7 +5143,7 @@ OP_C_C (SIM_DESC sd, SIM_CPU *cpu)
|
|||
|
||||
/* Turn a pointer in a register into a pointer into real memory. */
|
||||
|
||||
#define MEMPTR(x) ((char *)(dmem_addr (sd, cpu, x)))
|
||||
#define MEMPTR(x) sim_core_trans_addr (sd, cpu, read_map, x)
|
||||
|
||||
switch (FUNC)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue