Move global MIPS simulator variables into sim_cpu struct.
This commit is contained in:
parent
1b217de0f3
commit
0c2c5f6141
4 changed files with 369 additions and 330 deletions
|
@ -1,3 +1,21 @@
|
|||
Tue Oct 14 17:38:18 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* Makefile.in (interp.o): Depends on sim-main.h
|
||||
|
||||
* interp.c (mips16_entry, ColdReset,dotrace): Add SD argument. Use GPR not registers.
|
||||
|
||||
* sim-main.h (sim_cpu): Add registers, register_widths, fpr_state,
|
||||
ipc, dspc, pending_*, hiaccess, loaccess, state, dsstate fields.
|
||||
(REGISTERS, REGISTER_WIDTHS, FPR_STATE, IPC, DSPC, PENDING_*,
|
||||
STATE, DSSTATE): Define
|
||||
(GPR, FGRIDX, ..): Define.
|
||||
|
||||
* interp.c (registers, register_widths, fpr_state, ipc, dspc,
|
||||
pending_*, hiaccess, loaccess, state, dsstate): Delete globals.
|
||||
(GPR, FGRIDX, ...): Delete macros.
|
||||
|
||||
* interp.c: Update names to match defines from sim-main.h
|
||||
|
||||
Tue Oct 14 15:11:45 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* interp.c (sim_monitor): Add SD argument.
|
||||
|
|
|
@ -44,7 +44,7 @@ SIM_RUN_OBJS = nrun.o
|
|||
|
||||
## COMMON_POST_CONFIG_FRAG
|
||||
|
||||
interp.o: $(srcdir)/interp.c engine.c config.h
|
||||
interp.o: $(srcdir)/interp.c engine.c config.h sim-main.h
|
||||
|
||||
engine.c: gencode
|
||||
./gencode @SIMCONF@ > tmp-engine
|
||||
|
|
|
@ -129,80 +129,6 @@ char* pr_uword64 PARAMS ((uword64 addr));
|
|||
#define AccessLength_DOUBLEWORD (7)
|
||||
#define AccessLength_QUADWORD (15)
|
||||
|
||||
/* NOTE: We cannot avoid globals, since the GDB "sim_" interface does
|
||||
not allow a private variable to be passed around. This means that
|
||||
simulators under GDB can only be single-threaded. However, it would
|
||||
be possible for the simulators to be multi-threaded if GDB allowed
|
||||
for a private pointer to be maintained. i.e. a general "void **ptr"
|
||||
variable that GDB passed around in the argument list to all of
|
||||
sim_xxx() routines. It could be initialised to NULL by GDB, and
|
||||
then updated by sim_open() and used by the other sim_xxx() support
|
||||
functions. This would allow new features in the simulator world,
|
||||
like storing a context - continuing execution to gather a result,
|
||||
and then going back to the point where the context was saved and
|
||||
changing some state before continuing. i.e. the ability to perform
|
||||
UNDOs on simulations. It would also allow the simulation of
|
||||
shared-memory multi-processor systems.
|
||||
|
||||
[NOTE: This is now partially implemented] */
|
||||
|
||||
/* This is nasty, since we have to rely on matching the register
|
||||
numbers used by GDB. Unfortunately, depending on the MIPS target
|
||||
GDB uses different register numbers. We cannot just include the
|
||||
relevant "gdb/tm.h" link, since GDB may not be configured before
|
||||
the sim world, and also the GDB header file requires too much other
|
||||
state. */
|
||||
/* TODO: Sort out a scheme for *KNOWING* the mapping between real
|
||||
registers, and the numbers that GDB uses. At the moment due to the
|
||||
order that the tools are built, we cannot rely on a configured GDB
|
||||
world whilst constructing the simulator. This means we have to
|
||||
assume the GDB register number mapping. */
|
||||
#ifndef TM_MIPS_H
|
||||
#define LAST_EMBED_REGNUM (89)
|
||||
#define NUM_REGS (LAST_EMBED_REGNUM + 1)
|
||||
/* start-sanitize-r5900 */
|
||||
#undef NUM_REGS
|
||||
#define NUM_REGS (128)
|
||||
/* end-sanitize-r5900 */
|
||||
#endif
|
||||
|
||||
/* To keep this default simulator simple, and fast, we use a direct
|
||||
vector of registers. The internal simulator engine then uses
|
||||
manifests to access the correct slot. */
|
||||
static ut_reg registers[LAST_EMBED_REGNUM + 1];
|
||||
static int register_widths[NUM_REGS];
|
||||
|
||||
#define GPR (®isters[0])
|
||||
#if defined(HASFPU)
|
||||
#define FGRIDX (38)
|
||||
#define FGR (®isters[FGRIDX])
|
||||
#endif /* HASFPU */
|
||||
#define LO (registers[33])
|
||||
#define HI (registers[34])
|
||||
#define PC (registers[37])
|
||||
#define CAUSE (registers[36])
|
||||
#define SRIDX (32)
|
||||
#define SR (registers[SRIDX]) /* CPU status register */
|
||||
#define FCR0IDX (71)
|
||||
#define FCR0 (registers[FCR0IDX]) /* really a 32bit register */
|
||||
#define FCR31IDX (70)
|
||||
#define FCR31 (registers[FCR31IDX]) /* really a 32bit register */
|
||||
#define FCSR (FCR31)
|
||||
#define Debug (registers[86])
|
||||
#define DEPC (registers[87])
|
||||
#define EPC (registers[88])
|
||||
#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */
|
||||
|
||||
/* The following are pseudonyms for standard registers */
|
||||
#define ZERO (registers[0])
|
||||
#define V0 (registers[2])
|
||||
#define A0 (registers[4])
|
||||
#define A1 (registers[5])
|
||||
#define A2 (registers[6])
|
||||
#define A3 (registers[7])
|
||||
#define SP (registers[29])
|
||||
#define RA (registers[31])
|
||||
|
||||
|
||||
/* Bits in the Debug register */
|
||||
#define Debug_DBD 0x80000000 /* Debug Branch Delay */
|
||||
|
@ -212,37 +138,20 @@ static int register_widths[NUM_REGS];
|
|||
|
||||
|
||||
/* start-sanitize-r5900 */
|
||||
/*
|
||||
The R5900 has 128 bit registers, but the hi 64 bits are only touched by
|
||||
multimedia (MMI) instructions. The normal mips instructions just use the
|
||||
lower 64 bits. To avoid changing the older parts of the simulator to
|
||||
handle this weirdness, the high 64 bits of each register are kept in
|
||||
a separate array (registers1). The high 64 bits of any register are by
|
||||
convention refered by adding a '1' to the end of the normal register's
|
||||
name. So LO still refers to the low 64 bits of the LO register, LO1
|
||||
refers to the high 64 bits of that same register.
|
||||
*/
|
||||
|
||||
/* The high part of each register */
|
||||
static ut_reg registers1[LAST_EMBED_REGNUM + 1];
|
||||
|
||||
#define GPR1 (®isters1[0])
|
||||
|
||||
#define LO1 (registers1[32])
|
||||
#define HI1 (registers1[33])
|
||||
#define REGISTER_SA (124)
|
||||
|
||||
#define BYTES_IN_MMI_REGS (sizeof(registers[0])+sizeof(registers1[0]))
|
||||
#define BYTES_IN_MMI_REGS (sizeof(signed_word) + sizeof(signed_word))
|
||||
#define HALFWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/2)
|
||||
#define WORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/4)
|
||||
#define DOUBLEWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/8)
|
||||
|
||||
#define BYTES_IN_MIPS_REGS (sizeof(registers[0]))
|
||||
#define BYTES_IN_MIPS_REGS (sizeof(signed_word))
|
||||
#define HALFWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/2)
|
||||
#define WORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/4)
|
||||
#define DOUBLEWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/8)
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
SUB_REG_FETCH - return as lvalue some sub-part of a "register"
|
||||
T - type of the sub part
|
||||
|
@ -277,15 +186,15 @@ GPR_<type>(R,I) - return, as lvalue, the I'th <type> of general register R
|
|||
#define SUB_REG_UW(A,A1,I) SUB_REG_FETCH(unsigned32, WORDS_IN_MIPS_REGS, A, A1, I)
|
||||
#define SUB_REG_UD(A,A1,I) SUB_REG_FETCH(unsigned64, DOUBLEWORDS_IN_MIPS_REGS, A, A1, I)
|
||||
|
||||
#define GPR_SB(R,I) SUB_REG_SB(®isters[R], ®isters1[R], I)
|
||||
#define GPR_SH(R,I) SUB_REG_SH(®isters[R], ®isters1[R], I)
|
||||
#define GPR_SW(R,I) SUB_REG_SW(®isters[R], ®isters1[R], I)
|
||||
#define GPR_SD(R,I) SUB_REG_SD(®isters[R], ®isters1[R], I)
|
||||
#define GPR_SB(R,I) SUB_REG_SB(®ISTERS[R], ®ISTERS1[R], I)
|
||||
#define GPR_SH(R,I) SUB_REG_SH(®ISTERS[R], ®ISTERS1[R], I)
|
||||
#define GPR_SW(R,I) SUB_REG_SW(®ISTERS[R], ®ISTERS1[R], I)
|
||||
#define GPR_SD(R,I) SUB_REG_SD(®ISTERS[R], ®ISTERS1[R], I)
|
||||
|
||||
#define GPR_UB(R,I) SUB_REG_UB(®isters[R], ®isters1[R], I)
|
||||
#define GPR_UH(R,I) SUB_REG_UH(®isters[R], ®isters1[R], I)
|
||||
#define GPR_UW(R,I) SUB_REG_UW(®isters[R], ®isters1[R], I)
|
||||
#define GPR_UD(R,I) SUB_REG_UD(®isters[R], ®isters1[R], I)
|
||||
#define GPR_UB(R,I) SUB_REG_UB(®ISTERS[R], ®ISTERS1[R], I)
|
||||
#define GPR_UH(R,I) SUB_REG_UH(®ISTERS[R], ®ISTERS1[R], I)
|
||||
#define GPR_UW(R,I) SUB_REG_UW(®ISTERS[R], ®ISTERS1[R], I)
|
||||
#define GPR_UD(R,I) SUB_REG_UD(®ISTERS[R], ®ISTERS1[R], I)
|
||||
|
||||
|
||||
#define RS_SB(I) SUB_REG_SB(&rs_reg, &rs_reg1, I)
|
||||
|
@ -332,20 +241,6 @@ GPR_<type>(R,I) - return, as lvalue, the I'th <type> of general register R
|
|||
/* end-sanitize-r5900 */
|
||||
|
||||
|
||||
/* start-sanitize-r5900 */
|
||||
static ut_reg SA; /* the shift amount register */
|
||||
/* end-sanitize-r5900 */
|
||||
|
||||
#if defined(HASFPU)
|
||||
/* Keep the current format state for each register: */
|
||||
static FP_formats fpr_state[32];
|
||||
#endif /* HASFPU */
|
||||
|
||||
/* The following are internal simulator state variables: */
|
||||
static ut_reg IPC = 0; /* internal Instruction PC */
|
||||
static ut_reg DSPC = 0; /* delay-slot PC */
|
||||
|
||||
|
||||
/* TODO : these should be the bitmasks for these bits within the
|
||||
status register. At the moment the following are VR4300
|
||||
bit-positions: */
|
||||
|
@ -381,7 +276,7 @@ static ut_reg DSPC = 0; /* delay-slot PC */
|
|||
|
||||
/* This should be the COC1 value at the start of the preceding
|
||||
instruction: */
|
||||
#define PREVCOC1() ((state & simPCOC1) ? 1 : 0)
|
||||
#define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0)
|
||||
#endif /* HASFPU */
|
||||
|
||||
/* Standard FCRS bits: */
|
||||
|
@ -413,25 +308,12 @@ static ut_reg DSPC = 0; /* delay-slot PC */
|
|||
#define FP_RM_TOMINF (3) /* Round to Minus infinity (Floor) */
|
||||
#define GETRM() (int)((FCSR >> FP_SH_RM) & FP_MASK_RM)
|
||||
|
||||
/* Slots for delayed register updates. For the moment we just have a
|
||||
fixed number of slots (rather than a more generic, dynamic
|
||||
system). This keeps the simulator fast. However, we only allow for
|
||||
the register update to be delayed for a single instruction
|
||||
cycle. */
|
||||
#define PSLOTS (5) /* Maximum number of instruction cycles */
|
||||
static int pending_in;
|
||||
static int pending_out;
|
||||
static int pending_total;
|
||||
static int pending_slot_count[PSLOTS];
|
||||
static int pending_slot_reg[PSLOTS];
|
||||
static ut_reg pending_slot_value[PSLOTS];
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*-- GDB simulator interface ------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static void dotrace PARAMS((FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...));
|
||||
static void ColdReset PARAMS((void));
|
||||
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_set_profile PARAMS((SIM_DESC sd, int n));
|
||||
|
@ -442,52 +324,20 @@ static void mips_size PARAMS((SIM_DESC sd, int n));
|
|||
|
||||
/* The following are not used for MIPS IV onwards: */
|
||||
#define PENDING_FILL(r,v) {\
|
||||
/* printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total); */\
|
||||
if (pending_slot_reg[pending_in] != (LAST_EMBED_REGNUM + 1))\
|
||||
/* printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL); */\
|
||||
if (PENDING_SLOT_REG[PENDING_IN] != (LAST_EMBED_REGNUM + 1))\
|
||||
sim_io_eprintf(sd,"Attempt to over-write pending value\n");\
|
||||
pending_slot_count[pending_in] = 2;\
|
||||
pending_slot_reg[pending_in] = (r);\
|
||||
pending_slot_value[pending_in] = (uword64)(v);\
|
||||
PENDING_SLOT_COUNT[PENDING_IN] = 2;\
|
||||
PENDING_SLOT_REG[PENDING_IN] = (r);\
|
||||
PENDING_SLOT_VALUE[PENDING_IN] = (uword64)(v);\
|
||||
/*printf("DBG: FILL reg %d value = 0x%s\n",(r),pr_addr(v));*/\
|
||||
pending_total++;\
|
||||
pending_in++;\
|
||||
if (pending_in == PSLOTS)\
|
||||
pending_in = 0;\
|
||||
/*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);*/\
|
||||
PENDING_TOTAL++;\
|
||||
PENDING_IN++;\
|
||||
if (PENDING_IN == PSLOTS)\
|
||||
PENDING_IN = 0;\
|
||||
/*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL);*/\
|
||||
}
|
||||
|
||||
static int LLBIT = 0;
|
||||
/* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic
|
||||
read-write instructions. It is set when a linked load occurs. It is
|
||||
tested and cleared by the conditional store. It is cleared (during
|
||||
other CPU operations) when a store to the location would no longer
|
||||
be atomic. In particular, it is cleared by exception return
|
||||
instructions. */
|
||||
|
||||
static int HIACCESS = 0;
|
||||
static int LOACCESS = 0;
|
||||
static int HI1ACCESS = 0;
|
||||
static int LO1ACCESS = 0;
|
||||
|
||||
/* ??? The 4300 and a few other processors have interlocks on hi/lo register
|
||||
reads, and hence do not have this problem. To avoid spurious warnings,
|
||||
we just disable this always. */
|
||||
#if 1
|
||||
#define CHECKHILO(s)
|
||||
#else
|
||||
/* The HIACCESS and LOACCESS counts are used to ensure that
|
||||
corruptions caused by using the HI or LO register to close to a
|
||||
following operation are spotted. */
|
||||
static ut_reg HLPC = 0;
|
||||
/* If either of the preceding two instructions have accessed the HI or
|
||||
LO registers, then the values they see should be
|
||||
undefined. However, to keep the simulator world simple, we just let
|
||||
them use the value read and raise a warning to notify the user: */
|
||||
#define CHECKHILO(s) {\
|
||||
if ((HIACCESS != 0) || (LOACCESS != 0) || (HI1ACCESS != 0) || (LO1ACCESS != 0))\
|
||||
sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\
|
||||
}
|
||||
#endif
|
||||
|
||||
/* NOTE: We keep the following status flags as bit values (1 for true,
|
||||
0 for false). This allows them to be used in binary boolean
|
||||
|
@ -525,6 +375,7 @@ static ut_reg HLPC = 0;
|
|||
/* At the moment these values will be the same, since we do not have
|
||||
access to the pipeline cycle count information from the simulator
|
||||
engine. */
|
||||
/* FIXME: These will be replaced by ../common/sim-profile.h */
|
||||
static unsigned int instruction_fetches = 0;
|
||||
static unsigned int instruction_fetch_overflow = 0;
|
||||
#endif
|
||||
|
@ -541,32 +392,29 @@ static unsigned int instruction_fetch_overflow = 0;
|
|||
#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */
|
||||
#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */
|
||||
|
||||
static unsigned int state = 0;
|
||||
static unsigned int dsstate;
|
||||
|
||||
#define DELAYSLOT() {\
|
||||
if (state & simDELAYSLOT)\
|
||||
if (STATE & simDELAYSLOT)\
|
||||
sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
|
||||
state |= simDELAYSLOT;\
|
||||
STATE |= simDELAYSLOT;\
|
||||
}
|
||||
|
||||
#define JALDELAYSLOT() {\
|
||||
DELAYSLOT ();\
|
||||
state |= simJALDELAYSLOT;\
|
||||
STATE |= simJALDELAYSLOT;\
|
||||
}
|
||||
|
||||
#define NULLIFY() {\
|
||||
state &= ~simDELAYSLOT;\
|
||||
state |= simSKIPNEXT;\
|
||||
STATE &= ~simDELAYSLOT;\
|
||||
STATE |= simSKIPNEXT;\
|
||||
}
|
||||
|
||||
#define CANCELDELAYSLOT() {\
|
||||
dsstate = 0;\
|
||||
state &= ~(simDELAYSLOT | simJALDELAYSLOT);\
|
||||
DSSTATE = 0;\
|
||||
STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
|
||||
}
|
||||
|
||||
#define INDELAYSLOT() ((state & simDELAYSLOT) != 0)
|
||||
#define INJALDELAYSLOT() ((state & simJALDELAYSLOT) != 0)
|
||||
#define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
|
||||
#define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
|
||||
|
||||
#define K0BASE (0x80000000)
|
||||
#define K0SIZE (0x20000000)
|
||||
|
@ -629,11 +477,11 @@ mips_option_handler (sd, opt, arg)
|
|||
(i.e. only from main onwards, excluding the run-time setup,
|
||||
etc.). */
|
||||
if (arg == NULL)
|
||||
state |= simTRACE;
|
||||
STATE |= simTRACE;
|
||||
else if (strcmp (arg, "yes") == 0)
|
||||
state |= simTRACE;
|
||||
STATE |= simTRACE;
|
||||
else if (strcmp (arg, "no") == 0)
|
||||
state &= ~simTRACE;
|
||||
STATE &= ~simTRACE;
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Unreconized trace option `%s'\n", arg);
|
||||
|
@ -668,7 +516,7 @@ Re-compile simulator with \"-DTRACE\" to enable this option.\n");
|
|||
|
||||
case 'p':
|
||||
#if defined(PROFILE)
|
||||
state |= simPROFILE;
|
||||
STATE |= simPROFILE;
|
||||
return SIM_RC_OK;
|
||||
#else /* !PROFILE */
|
||||
fprintf(stderr,"\
|
||||
|
@ -749,6 +597,7 @@ sim_open (kind, cb, abfd, argv)
|
|||
char **argv;
|
||||
{
|
||||
SIM_DESC sd = sim_state_alloc (kind, cb);
|
||||
sim_cpu *cpu = STATE_CPU (sd, 0);
|
||||
|
||||
/* FIXME: watchpoints code shouldn't need this */
|
||||
STATE_WATCHPOINTS (sd)->pc = &(PC);
|
||||
|
@ -760,7 +609,7 @@ sim_open (kind, cb, abfd, argv)
|
|||
STATE_MEM_SIZE (sd) = (2 << 20);
|
||||
STATE_MEM_BASE (sd) = K1BASE;
|
||||
|
||||
state = 0;
|
||||
STATE = 0;
|
||||
|
||||
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
|
||||
return 0;
|
||||
|
@ -845,23 +694,21 @@ sim_open (kind, cb, abfd, argv)
|
|||
int rn;
|
||||
for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) {
|
||||
if (rn < 32)
|
||||
register_widths[rn] = GPRLEN;
|
||||
#if defined(HASFPU)
|
||||
cpu->register_widths[rn] = GPRLEN;
|
||||
else if ((rn >= FGRIDX) && (rn < (FGRIDX + 32)))
|
||||
register_widths[rn] = GPRLEN;
|
||||
#endif
|
||||
cpu->register_widths[rn] = GPRLEN;
|
||||
else if ((rn >= 33) && (rn <= 37))
|
||||
register_widths[rn] = GPRLEN;
|
||||
cpu->register_widths[rn] = GPRLEN;
|
||||
else if ((rn == SRIDX) || (rn == FCR0IDX) || (rn == FCR31IDX) || ((rn >= 72) && (rn <= 89)))
|
||||
register_widths[rn] = 32;
|
||||
cpu->register_widths[rn] = 32;
|
||||
else
|
||||
register_widths[rn] = 0;
|
||||
cpu->register_widths[rn] = 0;
|
||||
}
|
||||
/* start-sanitize-r5900 */
|
||||
|
||||
/* set the 5900 "upper" registers to 64 bits */
|
||||
for( rn = LAST_EMBED_REGNUM+1; rn < NUM_REGS; rn++)
|
||||
register_widths[rn] = 64;
|
||||
cpu->register_widths[rn] = 64;
|
||||
/* end-sanitize-r5900 */
|
||||
}
|
||||
|
||||
|
@ -896,7 +743,7 @@ sim_open (kind, cb, abfd, argv)
|
|||
monitor_size);
|
||||
|
||||
#if defined(TRACE)
|
||||
if (state & simTRACE)
|
||||
if (STATE & simTRACE)
|
||||
open_trace(sd);
|
||||
#endif /* TRACE */
|
||||
|
||||
|
@ -1064,7 +911,7 @@ sim_close (sd, quitting)
|
|||
sim_io_shutdown (sd);
|
||||
|
||||
#if defined(PROFILE)
|
||||
if ((state & simPROFILE) && (profile_hist != NULL)) {
|
||||
if ((STATE & simPROFILE) && (profile_hist != NULL)) {
|
||||
FILE *pf = fopen("gmon.out","wb");
|
||||
unsigned loop;
|
||||
|
||||
|
@ -1095,7 +942,7 @@ sim_close (sd, quitting)
|
|||
|
||||
free(profile_hist);
|
||||
profile_hist = NULL;
|
||||
state &= ~simPROFILE;
|
||||
STATE &= ~simPROFILE;
|
||||
}
|
||||
#endif /* PROFILE */
|
||||
|
||||
|
@ -1103,7 +950,7 @@ sim_close (sd, quitting)
|
|||
if (tracefh != NULL && tracefh != stderr)
|
||||
fclose(tracefh);
|
||||
tracefh = NULL;
|
||||
state &= ~simTRACE;
|
||||
STATE &= ~simTRACE;
|
||||
#endif /* TRACE */
|
||||
|
||||
if (logfh != NULL && logfh != stdout && logfh != stderr)
|
||||
|
@ -1267,6 +1114,7 @@ sim_store_register (sd,rn,memory)
|
|||
int rn;
|
||||
unsigned char *memory;
|
||||
{
|
||||
sim_cpu *cpu = STATE_CPU (sd, 0);
|
||||
/* NOTE: gdb (the client) stores registers in target byte order
|
||||
while the simulator uses host byte order */
|
||||
#ifdef DEBUG
|
||||
|
@ -1277,18 +1125,18 @@ sim_store_register (sd,rn,memory)
|
|||
numbering one. We need to know what the width of each logical
|
||||
register number is for the architecture being simulated. */
|
||||
|
||||
if (register_widths[rn] == 0)
|
||||
if (cpu->register_widths[rn] == 0)
|
||||
sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
|
||||
/* start-sanitize-r5900 */
|
||||
else if (rn == REGISTER_SA)
|
||||
SA = T2H_8(*(uword64*)memory);
|
||||
else if (rn > LAST_EMBED_REGNUM)
|
||||
registers1[rn - LAST_EMBED_REGNUM - 1] = T2H_8(*(uword64*)memory);
|
||||
cpu->registers1[rn - LAST_EMBED_REGNUM - 1] = T2H_8(*(uword64*)memory);
|
||||
/* end-sanitize-r5900 */
|
||||
else if (register_widths[rn] == 32)
|
||||
registers[rn] = T2H_4 (*(unsigned int*)memory);
|
||||
else if (cpu->register_widths[rn] == 32)
|
||||
cpu->registers[rn] = T2H_4 (*(unsigned int*)memory);
|
||||
else
|
||||
registers[rn] = T2H_8 (*(uword64*)memory);
|
||||
cpu->registers[rn] = T2H_8 (*(uword64*)memory);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1299,24 +1147,25 @@ sim_fetch_register (sd,rn,memory)
|
|||
int rn;
|
||||
unsigned char *memory;
|
||||
{
|
||||
sim_cpu *cpu = STATE_CPU (sd, 0);
|
||||
/* NOTE: gdb (the client) stores registers in target byte order
|
||||
while the simulator uses host byte order */
|
||||
#ifdef DEBUG
|
||||
sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn]));
|
||||
#endif /* DEBUG */
|
||||
|
||||
if (register_widths[rn] == 0)
|
||||
if (cpu->register_widths[rn] == 0)
|
||||
sim_io_eprintf(sd,"Invalid register width for %d (register fetch ignored)\n",rn);
|
||||
/* start-sanitize-r5900 */
|
||||
else if (rn == REGISTER_SA)
|
||||
*((uword64 *)memory) = H2T_8(SA);
|
||||
else if (rn > LAST_EMBED_REGNUM)
|
||||
*((uword64 *)memory) = H2T_8(registers1[rn - LAST_EMBED_REGNUM - 1]);
|
||||
*((uword64 *)memory) = H2T_8(cpu->registers1[rn - LAST_EMBED_REGNUM - 1]);
|
||||
/* end-sanitize-r5900 */
|
||||
else if (register_widths[rn] == 32)
|
||||
*((unsigned int *)memory) = H2T_4 ((unsigned int)(registers[rn] & 0xFFFFFFFF));
|
||||
else if (cpu->register_widths[rn] == 32)
|
||||
*((unsigned int *)memory) = H2T_4 ((unsigned int)(cpu->registers[rn] & 0xFFFFFFFF));
|
||||
else /* 64bit register */
|
||||
*((uword64 *)memory) = H2T_8 (registers[rn]);
|
||||
*((uword64 *)memory) = H2T_8 (cpu->registers[rn]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1384,7 +1233,7 @@ sim_create_inferior (sd, abfd, argv,env)
|
|||
pr_addr(PC));
|
||||
#endif /* DEBUG */
|
||||
|
||||
ColdReset();
|
||||
ColdReset(sd);
|
||||
/* If we were providing a more complete I/O, co-processor or memory
|
||||
simulation, we should perform any "device" initialisation at this
|
||||
point. This can include pre-loading memory areas with particular
|
||||
|
@ -1468,7 +1317,7 @@ sim_do_command (sd,cmd)
|
|||
break;
|
||||
|
||||
case e_reset: /* no arguments */
|
||||
ColdReset();
|
||||
ColdReset(sd);
|
||||
/* NOTE: See the comments in sim_open() relating to device
|
||||
initialisation. */
|
||||
break;
|
||||
|
@ -1504,7 +1353,7 @@ mips_set_profile (sd,n)
|
|||
{
|
||||
#if defined(PROFILE)
|
||||
profile_frequency = n;
|
||||
state |= simPROFILE;
|
||||
STATE |= simPROFILE;
|
||||
#endif /* PROFILE */
|
||||
return;
|
||||
}
|
||||
|
@ -1515,7 +1364,7 @@ mips_set_profile_size (sd,n)
|
|||
int n;
|
||||
{
|
||||
#if defined(PROFILE)
|
||||
if (state & simPROFILE) {
|
||||
if (STATE & simPROFILE) {
|
||||
int bsize;
|
||||
|
||||
/* Since we KNOW that the memory banks are a power-of-2 in size: */
|
||||
|
@ -1538,7 +1387,7 @@ mips_set_profile_size (sd,n)
|
|||
profile_hist = (unsigned short *)realloc(profile_hist,bsize);
|
||||
if (profile_hist == NULL) {
|
||||
sim_io_eprintf(sd,"Failed to allocate VM for profiling buffer (0x%08X bytes)\n",bsize);
|
||||
state &= ~simPROFILE;
|
||||
STATE &= ~simPROFILE;
|
||||
}
|
||||
}
|
||||
#endif /* PROFILE */
|
||||
|
@ -1893,7 +1742,8 @@ load_word (sd, vaddr)
|
|||
code, but for ease of simulation we just handle them directly. */
|
||||
|
||||
static void
|
||||
mips16_entry (insn)
|
||||
mips16_entry (sd,insn)
|
||||
SIM_DESC sd;
|
||||
unsigned int insn;
|
||||
{
|
||||
int aregs, sregs, rreg;
|
||||
|
@ -1918,7 +1768,7 @@ mips16_entry (insn)
|
|||
/* This is the entry pseudo-instruction. */
|
||||
|
||||
for (i = 0; i < aregs; i++)
|
||||
store_word ((uword64) (SP + 4 * i), registers[i + 4]);
|
||||
store_word ((uword64) (SP + 4 * i), GPR[i + 4]);
|
||||
|
||||
tsp = SP;
|
||||
SP -= 32;
|
||||
|
@ -1932,7 +1782,7 @@ mips16_entry (insn)
|
|||
for (i = 0; i < sregs; i++)
|
||||
{
|
||||
tsp -= 4;
|
||||
store_word ((uword64) tsp, registers[16 + i]);
|
||||
store_word ((uword64) tsp, GPR[16 + i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1953,7 +1803,7 @@ mips16_entry (insn)
|
|||
for (i = 0; i < sregs; i++)
|
||||
{
|
||||
tsp -= 4;
|
||||
registers[i + 16] = load_word ((uword64) tsp);
|
||||
GPR[i + 16] = load_word ((uword64) tsp);
|
||||
}
|
||||
|
||||
SP += 32;
|
||||
|
@ -1962,14 +1812,14 @@ mips16_entry (insn)
|
|||
if (aregs == 5)
|
||||
{
|
||||
FGR[0] = WORD64LO (GPR[4]);
|
||||
fpr_state[0] = fmt_uninterpreted;
|
||||
FPR_STATE[0] = fmt_uninterpreted;
|
||||
}
|
||||
else if (aregs == 6)
|
||||
{
|
||||
FGR[0] = WORD64LO (GPR[5]);
|
||||
FGR[1] = WORD64LO (GPR[4]);
|
||||
fpr_state[0] = fmt_uninterpreted;
|
||||
fpr_state[1] = fmt_uninterpreted;
|
||||
FPR_STATE[0] = fmt_uninterpreted;
|
||||
FPR_STATE[1] = fmt_uninterpreted;
|
||||
}
|
||||
#endif /* defined(HASFPU) */
|
||||
|
||||
|
@ -2059,9 +1909,9 @@ getnum(sd,value)
|
|||
|
||||
|
||||
static
|
||||
void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...)
|
||||
void dotrace(SIM_DESC sd,FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...)
|
||||
{
|
||||
if (state & simTRACE) {
|
||||
if (STATE & simTRACE) {
|
||||
va_list ap;
|
||||
fprintf(tracefh,"%d %s ; width %d ; ",
|
||||
type,
|
||||
|
@ -2095,7 +1945,8 @@ void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...
|
|||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
ColdReset()
|
||||
ColdReset(sd)
|
||||
SIM_DESC sd;
|
||||
{
|
||||
/* RESET: Fixed PC address: */
|
||||
PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000);
|
||||
|
@ -2114,8 +1965,8 @@ ColdReset()
|
|||
{
|
||||
int loop;
|
||||
for (loop = 0; (loop < PSLOTS); loop++)
|
||||
pending_slot_reg[loop] = (LAST_EMBED_REGNUM + 1);
|
||||
pending_in = pending_out = pending_total = 0;
|
||||
PENDING_SLOT_REG[loop] = (LAST_EMBED_REGNUM + 1);
|
||||
PENDING_IN = PENDING_OUT = PENDING_TOTAL = 0;
|
||||
}
|
||||
|
||||
#if defined(HASFPU)
|
||||
|
@ -2123,7 +1974,7 @@ ColdReset()
|
|||
{
|
||||
int rn;
|
||||
for (rn = 0; (rn < 32); rn++)
|
||||
fpr_state[rn] = fmt_uninterpreted;
|
||||
FPR_STATE[rn] = fmt_uninterpreted;
|
||||
}
|
||||
#endif /* HASFPU */
|
||||
|
||||
|
@ -2305,7 +2156,7 @@ load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw)
|
|||
|
||||
#if defined(TRACE)
|
||||
if (!raw)
|
||||
dotrace(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 */
|
||||
|
||||
/* NOTE: Quicker methods of decoding the address space can be used
|
||||
|
@ -2477,7 +2328,7 @@ store_memory(sd,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw)
|
|||
|
||||
#if defined(TRACE)
|
||||
if (!raw)
|
||||
dotrace(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
|
||||
|
@ -2755,7 +2606,7 @@ signal_exception (SIM_DESC sd, int exception,...)
|
|||
sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
|
||||
}
|
||||
}
|
||||
if (state & simDELAYSLOT)
|
||||
if (STATE & simDELAYSLOT)
|
||||
PC = IPC - 4; /* reference the branch instruction */
|
||||
else
|
||||
PC = IPC;
|
||||
|
@ -2773,9 +2624,9 @@ signal_exception (SIM_DESC sd, int exception,...)
|
|||
if (! (SR & status_EXL))
|
||||
{
|
||||
CAUSE = (exception << 2);
|
||||
if (state & simDELAYSLOT)
|
||||
if (STATE & simDELAYSLOT)
|
||||
{
|
||||
state &= ~simDELAYSLOT;
|
||||
STATE &= ~simDELAYSLOT;
|
||||
CAUSE |= cause_BD;
|
||||
EPC = (IPC - 4); /* reference the branch instruction */
|
||||
}
|
||||
|
@ -3038,24 +2889,24 @@ value_fpr(sd,fpr,fmt)
|
|||
#if 1
|
||||
/* If request to read data as "uninterpreted", then use the current
|
||||
encoding: */
|
||||
fmt = fpr_state[fpr];
|
||||
fmt = FPR_STATE[fpr];
|
||||
#else
|
||||
fmt = fmt_long;
|
||||
#endif
|
||||
|
||||
/* For values not yet accessed, set to the desired format: */
|
||||
if (fpr_state[fpr] == fmt_uninterpreted) {
|
||||
fpr_state[fpr] = fmt;
|
||||
if (FPR_STATE[fpr] == fmt_uninterpreted) {
|
||||
FPR_STATE[fpr] = fmt;
|
||||
#ifdef DEBUG
|
||||
printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
if (fmt != fpr_state[fpr]) {
|
||||
sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(fpr_state[fpr]),DOFMT(fmt),pr_addr(IPC));
|
||||
fpr_state[fpr] = fmt_unknown;
|
||||
if (fmt != FPR_STATE[fpr]) {
|
||||
sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(IPC));
|
||||
FPR_STATE[fpr] = fmt_unknown;
|
||||
}
|
||||
|
||||
if (fpr_state[fpr] == fmt_unknown) {
|
||||
if (FPR_STATE[fpr] == fmt_unknown) {
|
||||
/* Set QNaN value: */
|
||||
switch (fmt) {
|
||||
case fmt_single:
|
||||
|
@ -3146,18 +2997,18 @@ store_fpr(sd,fpr,fmt,value)
|
|||
case fmt_single :
|
||||
case fmt_word :
|
||||
FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
|
||||
fpr_state[fpr] = fmt;
|
||||
FPR_STATE[fpr] = fmt;
|
||||
break;
|
||||
|
||||
case fmt_uninterpreted:
|
||||
case fmt_double :
|
||||
case fmt_long :
|
||||
FGR[fpr] = value;
|
||||
fpr_state[fpr] = fmt;
|
||||
FPR_STATE[fpr] = fmt;
|
||||
break;
|
||||
|
||||
default :
|
||||
fpr_state[fpr] = fmt_unknown;
|
||||
FPR_STATE[fpr] = fmt_unknown;
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -3166,7 +3017,7 @@ store_fpr(sd,fpr,fmt,value)
|
|||
case fmt_single :
|
||||
case fmt_word :
|
||||
FGR[fpr] = (value & 0xFFFFFFFF);
|
||||
fpr_state[fpr] = fmt;
|
||||
FPR_STATE[fpr] = fmt;
|
||||
break;
|
||||
|
||||
case fmt_uninterpreted:
|
||||
|
@ -3175,17 +3026,17 @@ store_fpr(sd,fpr,fmt,value)
|
|||
if ((fpr & 1) == 0) { /* even register number only */
|
||||
FGR[fpr+1] = (value >> 32);
|
||||
FGR[fpr] = (value & 0xFFFFFFFF);
|
||||
fpr_state[fpr + 1] = fmt;
|
||||
fpr_state[fpr] = fmt;
|
||||
FPR_STATE[fpr + 1] = fmt;
|
||||
FPR_STATE[fpr] = fmt;
|
||||
} else {
|
||||
fpr_state[fpr] = fmt_unknown;
|
||||
fpr_state[fpr + 1] = fmt_unknown;
|
||||
FPR_STATE[fpr] = fmt_unknown;
|
||||
FPR_STATE[fpr + 1] = fmt_unknown;
|
||||
SignalException(ReservedInstruction,0);
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
fpr_state[fpr] = fmt_unknown;
|
||||
FPR_STATE[fpr] = fmt_unknown;
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -3910,7 +3761,7 @@ cop_lw(sd,coproc_num,coproc_reg,memword)
|
|||
printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword));
|
||||
#endif
|
||||
StoreFPR(coproc_reg,fmt_word,(uword64)memword);
|
||||
fpr_state[coproc_reg] = fmt_uninterpreted;
|
||||
FPR_STATE[coproc_reg] = fmt_uninterpreted;
|
||||
break;
|
||||
#endif /* HASFPU */
|
||||
|
||||
|
@ -3960,17 +3811,17 @@ cop_sw(sd,coproc_num,coproc_reg)
|
|||
#if 1
|
||||
{
|
||||
FP_formats hold;
|
||||
hold = fpr_state[coproc_reg];
|
||||
fpr_state[coproc_reg] = fmt_word;
|
||||
hold = FPR_STATE[coproc_reg];
|
||||
FPR_STATE[coproc_reg] = fmt_word;
|
||||
value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
|
||||
fpr_state[coproc_reg] = hold;
|
||||
FPR_STATE[coproc_reg] = hold;
|
||||
}
|
||||
#else
|
||||
#if 1
|
||||
value = (unsigned int)ValueFPR(coproc_reg,fpr_state[coproc_reg]);
|
||||
value = (unsigned int)ValueFPR(coproc_reg,FPR_STATE[coproc_reg]);
|
||||
#else
|
||||
#ifdef DEBUG
|
||||
printf("DBG: COP_SW: reg in format %s (will be accessing as single)\n",DOFMT(fpr_state[coproc_reg]));
|
||||
printf("DBG: COP_SW: reg in format %s (will be accessing as single)\n",DOFMT(FPR_STATE[coproc_reg]));
|
||||
#endif /* DEBUG */
|
||||
value = (unsigned int)ValueFPR(coproc_reg,fmt_single);
|
||||
#endif
|
||||
|
@ -4001,10 +3852,10 @@ cop_sd(sd,coproc_num,coproc_reg)
|
|||
value = ValueFPR(coproc_reg,fmt_uninterpreted);
|
||||
#else
|
||||
#if 1
|
||||
value = ValueFPR(coproc_reg,fpr_state[coproc_reg]);
|
||||
value = ValueFPR(coproc_reg,FPR_STATE[coproc_reg]);
|
||||
#else
|
||||
#ifdef DEBUG
|
||||
printf("DBG: COP_SD: reg in format %s (will be accessing as double)\n",DOFMT(fpr_state[coproc_reg]));
|
||||
printf("DBG: COP_SD: reg in format %s (will be accessing as double)\n",DOFMT(FPR_STATE[coproc_reg]));
|
||||
#endif /* DEBUG */
|
||||
value = ValueFPR(coproc_reg,fmt_double);
|
||||
#endif
|
||||
|
@ -4218,7 +4069,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
|||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
dsstate = (state & simDELAYSLOT);
|
||||
DSSTATE = (STATE & simDELAYSLOT);
|
||||
#ifdef DEBUG
|
||||
if (dsstate)
|
||||
sim_io_printf(sd,"DBG: DSPC = 0x%s\n",pr_addr(DSPC));
|
||||
|
@ -4265,7 +4116,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
|||
if (instruction_fetches == 0)
|
||||
instruction_fetch_overflow++;
|
||||
#if defined(PROFILE)
|
||||
if ((state & simPROFILE) && ((instruction_fetches % profile_frequency) == 0) && profile_hist) {
|
||||
if ((STATE & simPROFILE) && ((instruction_fetches % profile_frequency) == 0) && profile_hist) {
|
||||
unsigned n = ((unsigned int)(PC - profile_minpc) >> (profile_shift + 2));
|
||||
if (n < profile_nsamples) {
|
||||
/* NOTE: The counts for the profiling bins are only 16bits wide */
|
||||
|
@ -4324,15 +4175,15 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
|||
|
||||
#if defined(HASFPU)
|
||||
/* Set previous flag, depending on current: */
|
||||
if (state & simPCOC0)
|
||||
state |= simPCOC1;
|
||||
if (STATE & simPCOC0)
|
||||
STATE |= simPCOC1;
|
||||
else
|
||||
state &= ~simPCOC1;
|
||||
STATE &= ~simPCOC1;
|
||||
/* and update the current value: */
|
||||
if (GETFCC(0))
|
||||
state |= simPCOC0;
|
||||
STATE |= simPCOC0;
|
||||
else
|
||||
state &= ~simPCOC0;
|
||||
STATE &= ~simPCOC0;
|
||||
#endif /* HASFPU */
|
||||
|
||||
/* NOTE: For multi-context simulation environments the "instruction"
|
||||
|
@ -4342,7 +4193,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
|||
variables (and a single-threaded simulator engine), then we can
|
||||
create the actual variables with these names. */
|
||||
|
||||
if (!(state & simSKIPNEXT)) {
|
||||
if (!(STATE & simSKIPNEXT)) {
|
||||
/* Include the simulator engine */
|
||||
#include "engine.c"
|
||||
#if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
|
||||
|
@ -4378,11 +4229,11 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
|||
ZERO = 0; /* reset back to zero before next instruction */
|
||||
}
|
||||
} else /* simSKIPNEXT check */
|
||||
state &= ~simSKIPNEXT;
|
||||
STATE &= ~simSKIPNEXT;
|
||||
|
||||
/* If the delay slot was active before the instruction is
|
||||
executed, then update the PC to its new value: */
|
||||
if (dsstate) {
|
||||
if (DSSTATE) {
|
||||
#ifdef DEBUG
|
||||
printf("DBG: dsstate set before instruction execution - updating PC to 0x%s\n",pr_addr(DSPC));
|
||||
#endif /* DEBUG */
|
||||
|
@ -4395,11 +4246,11 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
|||
#ifdef DEBUG
|
||||
printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
|
||||
#endif /* DEBUG */
|
||||
if (pending_out != pending_in) {
|
||||
if (PENDING_OUT != PENDING_IN) {
|
||||
int loop;
|
||||
int index = pending_out;
|
||||
int total = pending_total;
|
||||
if (pending_total == 0) {
|
||||
int index = PENDING_OUT;
|
||||
int total = PENDING_TOTAL;
|
||||
if (PENDING_TOTAL == 0) {
|
||||
fprintf(stderr,"FATAL: Mis-match on pending update pointers\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -4407,39 +4258,39 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
|||
#ifdef DEBUG
|
||||
printf("DBG: BEFORE index = %d, loop = %d\n",index,loop);
|
||||
#endif /* DEBUG */
|
||||
if (pending_slot_reg[index] != (LAST_EMBED_REGNUM + 1)) {
|
||||
if (PENDING_SLOT_REG[index] != (LAST_EMBED_REGNUM + 1)) {
|
||||
#ifdef DEBUG
|
||||
printf("pending_slot_count[%d] = %d\n",index,pending_slot_count[index]);
|
||||
printf("pending_slot_count[%d] = %d\n",index,PENDING_SLOT_COUNT[index]);
|
||||
#endif /* DEBUG */
|
||||
if (--(pending_slot_count[index]) == 0) {
|
||||
if (--(PENDING_SLOT_COUNT[index]) == 0) {
|
||||
#ifdef DEBUG
|
||||
printf("pending_slot_reg[%d] = %d\n",index,pending_slot_reg[index]);
|
||||
printf("pending_slot_value[%d] = 0x%s\n",index,pr_addr(pending_slot_value[index]));
|
||||
printf("pending_slot_reg[%d] = %d\n",index,PENDING_SLOT_REG[index]);
|
||||
printf("pending_slot_value[%d] = 0x%s\n",index,pr_addr(PENDING_SLOT_VALUE[index]));
|
||||
#endif /* DEBUG */
|
||||
if (pending_slot_reg[index] == COCIDX) {
|
||||
if (PENDING_SLOT_REG[index] == COCIDX) {
|
||||
#if defined(HASFPU)
|
||||
SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
} else {
|
||||
registers[pending_slot_reg[index]] = pending_slot_value[index];
|
||||
REGISTERS[PENDING_SLOT_REG[index]] = PENDING_SLOT_VALUE[index];
|
||||
#if defined(HASFPU)
|
||||
/* The only time we have PENDING updates to FPU
|
||||
registers, is when performing binary transfers. This
|
||||
means we should update the register type field. */
|
||||
if ((pending_slot_reg[index] >= FGRIDX) && (pending_slot_reg[index] < (FGRIDX + 32)))
|
||||
fpr_state[pending_slot_reg[index] - FGRIDX] = fmt_uninterpreted;
|
||||
if ((PENDING_SLOT_REG[index] >= FGRIDX) && (PENDING_SLOT_REG[index] < (FGRIDX + 32)))
|
||||
FPR_STATE[PENDING_SLOT_REG[index] - FGRIDX] = fmt_uninterpreted;
|
||||
#endif /* HASFPU */
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("registers[%d] = 0x%s\n",pending_slot_reg[index],pr_addr(registers[pending_slot_reg[index]]));
|
||||
printf("registers[%d] = 0x%s\n",PENDING_SLOT_REG[index],pr_addr(REGISTERS[PENDING_SLOT_REG[index]]));
|
||||
#endif /* DEBUG */
|
||||
pending_slot_reg[index] = (LAST_EMBED_REGNUM + 1);
|
||||
pending_out++;
|
||||
if (pending_out == PSLOTS)
|
||||
pending_out = 0;
|
||||
pending_total--;
|
||||
PENDING_SLOT_REG[index] = (LAST_EMBED_REGNUM + 1);
|
||||
PENDING_OUT++;
|
||||
if (PENDING_OUT == PSLOTS)
|
||||
PENDING_OUT = 0;
|
||||
PENDING_TOTAL--;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
|
@ -4451,7 +4302,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
|||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
|
||||
printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
|
|
|
@ -78,8 +78,215 @@ typedef unsigned64 uword64;
|
|||
#endif
|
||||
|
||||
|
||||
/* FIXME: At present the CPU registers are static */
|
||||
/* Floating-point operations: */
|
||||
|
||||
/* FPU registers must be one of the following types. All other values
|
||||
are reserved (and undefined). */
|
||||
typedef enum {
|
||||
fmt_single = 0,
|
||||
fmt_double = 1,
|
||||
fmt_word = 4,
|
||||
fmt_long = 5,
|
||||
/* The following are well outside the normal acceptable format
|
||||
range, and are used in the register status vector. */
|
||||
fmt_unknown = 0x10000000,
|
||||
fmt_uninterpreted = 0x20000000,
|
||||
} FP_formats;
|
||||
|
||||
unsigned64 value_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats));
|
||||
#define ValueFPR(FPR,FMT) value_fpr (sd, (FPR), (FMT))
|
||||
|
||||
void store_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats fmt, unsigned64 value));
|
||||
#define StoreFPR(FPR,FMT,VALUE) store_fpr (sd, (FPR), (FMT), (VALUE))
|
||||
|
||||
int NaN PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
int Infinity PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
int Less PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
int Equal PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 AbsoluteValue PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
unsigned64 Negate PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
unsigned64 Add PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 Sub PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 Multiply PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 Divide PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 Recip PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
unsigned64 SquareRoot PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
unsigned64 convert PARAMS ((SIM_DESC sd, int rm, unsigned64 op, FP_formats from, FP_formats to));
|
||||
#define Convert(rm,op,from,to) convert(sd,rm,op,from,to)
|
||||
|
||||
|
||||
|
||||
|
||||
struct _sim_cpu {
|
||||
|
||||
|
||||
/* The following are internal simulator state variables: */
|
||||
address_word ipc; /* internal Instruction PC */
|
||||
address_word dspc; /* delay-slot PC */
|
||||
#define IPC ((STATE_CPU (sd,0))->ipc)
|
||||
#define DSPC ((STATE_CPU (sd,0))->dspc)
|
||||
|
||||
|
||||
/* State of the simulator */
|
||||
unsigned int state;
|
||||
unsigned int dsstate;
|
||||
#define STATE ((STATE_CPU (sd,0))->state)
|
||||
#define DSSTATE ((STATE_CPU (sd,0))->dsstate)
|
||||
|
||||
|
||||
/* This is nasty, since we have to rely on matching the register
|
||||
numbers used by GDB. Unfortunately, depending on the MIPS target
|
||||
GDB uses different register numbers. We cannot just include the
|
||||
relevant "gdb/tm.h" link, since GDB may not be configured before
|
||||
the sim world, and also the GDB header file requires too much other
|
||||
state. */
|
||||
|
||||
#ifndef TM_MIPS_H
|
||||
#define LAST_EMBED_REGNUM (89)
|
||||
#define NUM_REGS (LAST_EMBED_REGNUM + 1)
|
||||
/* start-sanitize-r5900 */
|
||||
#undef NUM_REGS
|
||||
#define NUM_REGS (128)
|
||||
/* end-sanitize-r5900 */
|
||||
#endif
|
||||
|
||||
/* To keep this default simulator simple, and fast, we use a direct
|
||||
vector of registers. The internal simulator engine then uses
|
||||
manifests to access the correct slot. */
|
||||
|
||||
signed_word registers[LAST_EMBED_REGNUM + 1];
|
||||
int register_widths[NUM_REGS];
|
||||
#define REGISTERS ((STATE_CPU (sd,0))->registers)
|
||||
|
||||
#define GPR (®ISTERS[0])
|
||||
#define FGRIDX (38)
|
||||
#define FGR (®ISTERS[FGRIDX])
|
||||
#define LO (REGISTERS[33])
|
||||
#define HI (REGISTERS[34])
|
||||
#define PC (REGISTERS[37])
|
||||
#define CAUSE (REGISTERS[36])
|
||||
#define SRIDX (32)
|
||||
#define SR (REGISTERS[SRIDX]) /* CPU status register */
|
||||
#define FCR0IDX (71)
|
||||
#define FCR0 (REGISTERS[FCR0IDX]) /* really a 32bit register */
|
||||
#define FCR31IDX (70)
|
||||
#define FCR31 (REGISTERS[FCR31IDX]) /* really a 32bit register */
|
||||
#define FCSR (FCR31)
|
||||
#define Debug (REGISTERS[86])
|
||||
#define DEPC (REGISTERS[87])
|
||||
#define EPC (REGISTERS[88])
|
||||
#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */
|
||||
|
||||
/* The following are pseudonyms for standard registers */
|
||||
#define ZERO (REGISTERS[0])
|
||||
#define V0 (REGISTERS[2])
|
||||
#define A0 (REGISTERS[4])
|
||||
#define A1 (REGISTERS[5])
|
||||
#define A2 (REGISTERS[6])
|
||||
#define A3 (REGISTERS[7])
|
||||
#define SP (REGISTERS[29])
|
||||
#define RA (REGISTERS[31])
|
||||
|
||||
/* Keep the current format state for each register: */
|
||||
FP_formats fpr_state[32];
|
||||
#define FPR_STATE ((STATE_CPU (sd, 0))->fpr_state)
|
||||
|
||||
|
||||
/* Slots for delayed register updates. For the moment we just have a
|
||||
fixed number of slots (rather than a more generic, dynamic
|
||||
system). This keeps the simulator fast. However, we only allow
|
||||
for the register update to be delayed for a single instruction
|
||||
cycle. */
|
||||
#define PSLOTS (5) /* Maximum number of instruction cycles */
|
||||
int pending_in;
|
||||
int pending_out;
|
||||
int pending_total;
|
||||
int pending_slot_count[PSLOTS];
|
||||
int pending_slot_reg[PSLOTS];
|
||||
unsigned_word pending_slot_value[PSLOTS];
|
||||
#define PENDING_IN ((STATE_CPU (sd, 0))->pending_in)
|
||||
#define PENDING_OUT ((STATE_CPU (sd, 0))->pending_out)
|
||||
#define PENDING_TOTAL ((STATE_CPU (sd, 0))->pending_total)
|
||||
#define PENDING_SLOT_COUNT ((STATE_CPU (sd, 0))->pending_slot_count)
|
||||
#define PENDING_SLOT_REG ((STATE_CPU (sd, 0))->pending_slot_reg)
|
||||
#define PENDING_SLOT_VALUE ((STATE_CPU (sd, 0))->pending_slot_value)
|
||||
|
||||
|
||||
/* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic
|
||||
read-write instructions. It is set when a linked load occurs. It
|
||||
is tested and cleared by the conditional store. It is cleared
|
||||
(during other CPU operations) when a store to the location would
|
||||
no longer be atomic. In particular, it is cleared by exception
|
||||
return instructions. */
|
||||
int llbit;
|
||||
#define LLBIT ((STATE_CPU (sd, 0))->llbit)
|
||||
|
||||
|
||||
/* The HIACCESS and LOACCESS counts are used to ensure that
|
||||
corruptions caused by using the HI or LO register to close to a
|
||||
following operation are spotted. */
|
||||
|
||||
int hiaccess;
|
||||
int loaccess;
|
||||
#define HIACCESS ((STATE_CPU (sd, 0))->hiaccess)
|
||||
#define LOACCESS ((STATE_CPU (sd, 0))->loaccess)
|
||||
/* start-sanitize-r5900 */
|
||||
int hi1access;
|
||||
int lo1access;
|
||||
#define HI1ACCESS ((STATE_CPU (sd, 0))->hi1access)
|
||||
#define LO1ACCESS ((STATE_CPU (sd, 0))->lo1access)
|
||||
/* end-sanitize-r5900 */
|
||||
#if 1
|
||||
/* The 4300 and a few other processors have interlocks on hi/lo
|
||||
register reads, and hence do not have this problem. To avoid
|
||||
spurious warnings, we just disable this always. */
|
||||
#define CHECKHILO(s)
|
||||
#else
|
||||
unsigned_word HLPC;
|
||||
/* If either of the preceding two instructions have accessed the HI
|
||||
or LO registers, then the values they see should be
|
||||
undefined. However, to keep the simulator world simple, we just
|
||||
let them use the value read and raise a warning to notify the
|
||||
user: */
|
||||
#define CHECKHILO(s) {\
|
||||
if ((HIACCESS != 0) || (LOACCESS != 0)) \
|
||||
sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\
|
||||
}
|
||||
/* end-sanitize-r5900 */
|
||||
#undef CHECKHILO
|
||||
#define CHECKHILO(s) {\
|
||||
if ((HIACCESS != 0) || (LOACCESS != 0) || (HI1ACCESS != 0) || (LO1ACCESS != 0))\
|
||||
sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\
|
||||
}
|
||||
/* end-sanitize-r5900 */
|
||||
#endif
|
||||
|
||||
|
||||
/* start-sanitize-r5900 */
|
||||
/* The R5900 has 128 bit registers, but the hi 64 bits are only
|
||||
touched by multimedia (MMI) instructions. The normal mips
|
||||
instructions just use the lower 64 bits. To avoid changing the
|
||||
older parts of the simulator to handle this weirdness, the high
|
||||
64 bits of each register are kept in a separate array
|
||||
(registers1). The high 64 bits of any register are by convention
|
||||
refered by adding a '1' to the end of the normal register's name.
|
||||
So LO still refers to the low 64 bits of the LO register, LO1
|
||||
refers to the high 64 bits of that same register. */
|
||||
|
||||
signed_word registers1[LAST_EMBED_REGNUM + 1];
|
||||
#define REGISTERS1 ((STATE_CPU (sd, 0))->registers1)
|
||||
#define GPR1 (®ISTERS1[0])
|
||||
#define LO1 (REGISTERS1[32])
|
||||
#define HI1 (REGISTERS1[33])
|
||||
#define REGISTER_SA (124)
|
||||
|
||||
unsigned_word sa; /* the shift amount register */
|
||||
#define SA ((STATE_CPU (sd, 0))->sa)
|
||||
|
||||
/* end-sanitize-r5900 */
|
||||
|
||||
|
||||
|
||||
sim_cpu_base base;
|
||||
};
|
||||
|
||||
|
@ -150,43 +357,6 @@ void signal_exception (SIM_DESC sd, int exception, ...);
|
|||
#define SignalExceptionCoProcessorUnusable() signal_exception (sd, CoProcessorUnusable)
|
||||
|
||||
|
||||
/* Floating-point operations: */
|
||||
|
||||
/* FPU registers must be one of the following types. All other values
|
||||
are reserved (and undefined). */
|
||||
typedef enum {
|
||||
fmt_single = 0,
|
||||
fmt_double = 1,
|
||||
fmt_word = 4,
|
||||
fmt_long = 5,
|
||||
/* The following are well outside the normal acceptable format
|
||||
range, and are used in the register status vector. */
|
||||
fmt_unknown = 0x10000000,
|
||||
fmt_uninterpreted = 0x20000000,
|
||||
} FP_formats;
|
||||
|
||||
unsigned64 value_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats));
|
||||
#define ValueFPR(FPR,FMT) value_fpr (sd, (FPR), (FMT))
|
||||
|
||||
void store_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats fmt, unsigned64 value));
|
||||
#define StoreFPR(FPR,FMT,VALUE) store_fpr (sd, (FPR), (FMT), (VALUE))
|
||||
|
||||
int NaN PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
int Infinity PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
int Less PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
int Equal PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 AbsoluteValue PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
unsigned64 Negate PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
unsigned64 Add PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 Sub PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 Multiply PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 Divide PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
|
||||
unsigned64 Recip PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
unsigned64 SquareRoot PARAMS ((unsigned64 op, FP_formats fmt));
|
||||
unsigned64 convert PARAMS ((SIM_DESC sd, int rm, unsigned64 op, FP_formats from, FP_formats to));
|
||||
#define Convert(rm,op,from,to) convert(sd,rm,op,from,to)
|
||||
|
||||
|
||||
/* Co-processor accesses */
|
||||
|
||||
void cop_lw PARAMS ((SIM_DESC sd, int coproc_num, int coproc_reg, unsigned int memword));
|
||||
|
|
Loading…
Reference in a new issue