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>
|
Tue Oct 14 15:11:45 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
* interp.c (sim_monitor): Add SD argument.
|
* interp.c (sim_monitor): Add SD argument.
|
||||||
|
|
|
@ -44,7 +44,7 @@ SIM_RUN_OBJS = nrun.o
|
||||||
|
|
||||||
## COMMON_POST_CONFIG_FRAG
|
## 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
|
engine.c: gencode
|
||||||
./gencode @SIMCONF@ > tmp-engine
|
./gencode @SIMCONF@ > tmp-engine
|
||||||
|
|
|
@ -129,80 +129,6 @@ char* pr_uword64 PARAMS ((uword64 addr));
|
||||||
#define AccessLength_DOUBLEWORD (7)
|
#define AccessLength_DOUBLEWORD (7)
|
||||||
#define AccessLength_QUADWORD (15)
|
#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 */
|
/* Bits in the Debug register */
|
||||||
#define Debug_DBD 0x80000000 /* Debug Branch Delay */
|
#define Debug_DBD 0x80000000 /* Debug Branch Delay */
|
||||||
|
@ -212,37 +138,20 @@ static int register_widths[NUM_REGS];
|
||||||
|
|
||||||
|
|
||||||
/* start-sanitize-r5900 */
|
/* 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 */
|
#define BYTES_IN_MMI_REGS (sizeof(signed_word) + sizeof(signed_word))
|
||||||
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 HALFWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/2)
|
#define HALFWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/2)
|
||||||
#define WORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/4)
|
#define WORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/4)
|
||||||
#define DOUBLEWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/8)
|
#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 HALFWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/2)
|
||||||
#define WORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/4)
|
#define WORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/4)
|
||||||
#define DOUBLEWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/8)
|
#define DOUBLEWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/8)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SUB_REG_FETCH - return as lvalue some sub-part of a "register"
|
SUB_REG_FETCH - return as lvalue some sub-part of a "register"
|
||||||
T - type of the sub part
|
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_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 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_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_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_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_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_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_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_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_UD(R,I) SUB_REG_UD(®ISTERS[R], ®ISTERS1[R], I)
|
||||||
|
|
||||||
|
|
||||||
#define RS_SB(I) SUB_REG_SB(&rs_reg, &rs_reg1, 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 */
|
/* 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
|
/* TODO : these should be the bitmasks for these bits within the
|
||||||
status register. At the moment the following are VR4300
|
status register. At the moment the following are VR4300
|
||||||
bit-positions: */
|
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
|
/* This should be the COC1 value at the start of the preceding
|
||||||
instruction: */
|
instruction: */
|
||||||
#define PREVCOC1() ((state & simPCOC1) ? 1 : 0)
|
#define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0)
|
||||||
#endif /* HASFPU */
|
#endif /* HASFPU */
|
||||||
|
|
||||||
/* Standard FCRS bits: */
|
/* 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 FP_RM_TOMINF (3) /* Round to Minus infinity (Floor) */
|
||||||
#define GETRM() (int)((FCSR >> FP_SH_RM) & FP_MASK_RM)
|
#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 ------------------------------------------------*/
|
/*-- GDB simulator interface ------------------------------------------------*/
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void dotrace PARAMS((FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...));
|
static void dotrace PARAMS((SIM_DESC sd,FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...));
|
||||||
static void ColdReset PARAMS((void));
|
static void ColdReset PARAMS((SIM_DESC sd));
|
||||||
static long getnum PARAMS((SIM_DESC sd, char *value));
|
static long getnum PARAMS((SIM_DESC sd, char *value));
|
||||||
static unsigned int power2 PARAMS((unsigned int value));
|
static unsigned int power2 PARAMS((unsigned int value));
|
||||||
static void mips_set_profile PARAMS((SIM_DESC sd, int n));
|
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: */
|
/* The following are not used for MIPS IV onwards: */
|
||||||
#define PENDING_FILL(r,v) {\
|
#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); */\
|
/* 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))\
|
if (PENDING_SLOT_REG[PENDING_IN] != (LAST_EMBED_REGNUM + 1))\
|
||||||
sim_io_eprintf(sd,"Attempt to over-write pending value\n");\
|
sim_io_eprintf(sd,"Attempt to over-write pending value\n");\
|
||||||
pending_slot_count[pending_in] = 2;\
|
PENDING_SLOT_COUNT[PENDING_IN] = 2;\
|
||||||
pending_slot_reg[pending_in] = (r);\
|
PENDING_SLOT_REG[PENDING_IN] = (r);\
|
||||||
pending_slot_value[pending_in] = (uword64)(v);\
|
PENDING_SLOT_VALUE[PENDING_IN] = (uword64)(v);\
|
||||||
/*printf("DBG: FILL reg %d value = 0x%s\n",(r),pr_addr(v));*/\
|
/*printf("DBG: FILL reg %d value = 0x%s\n",(r),pr_addr(v));*/\
|
||||||
pending_total++;\
|
PENDING_TOTAL++;\
|
||||||
pending_in++;\
|
PENDING_IN++;\
|
||||||
if (pending_in == PSLOTS)\
|
if (PENDING_IN == PSLOTS)\
|
||||||
pending_in = 0;\
|
PENDING_IN = 0;\
|
||||||
/*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);*/\
|
/*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,
|
/* 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
|
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
|
/* At the moment these values will be the same, since we do not have
|
||||||
access to the pipeline cycle count information from the simulator
|
access to the pipeline cycle count information from the simulator
|
||||||
engine. */
|
engine. */
|
||||||
|
/* FIXME: These will be replaced by ../common/sim-profile.h */
|
||||||
static unsigned int instruction_fetches = 0;
|
static unsigned int instruction_fetches = 0;
|
||||||
static unsigned int instruction_fetch_overflow = 0;
|
static unsigned int instruction_fetch_overflow = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -541,32 +392,29 @@ static unsigned int instruction_fetch_overflow = 0;
|
||||||
#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */
|
#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */
|
||||||
#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */
|
#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */
|
||||||
|
|
||||||
static unsigned int state = 0;
|
|
||||||
static unsigned int dsstate;
|
|
||||||
|
|
||||||
#define DELAYSLOT() {\
|
#define DELAYSLOT() {\
|
||||||
if (state & simDELAYSLOT)\
|
if (STATE & simDELAYSLOT)\
|
||||||
sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
|
sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
|
||||||
state |= simDELAYSLOT;\
|
STATE |= simDELAYSLOT;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define JALDELAYSLOT() {\
|
#define JALDELAYSLOT() {\
|
||||||
DELAYSLOT ();\
|
DELAYSLOT ();\
|
||||||
state |= simJALDELAYSLOT;\
|
STATE |= simJALDELAYSLOT;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NULLIFY() {\
|
#define NULLIFY() {\
|
||||||
state &= ~simDELAYSLOT;\
|
STATE &= ~simDELAYSLOT;\
|
||||||
state |= simSKIPNEXT;\
|
STATE |= simSKIPNEXT;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CANCELDELAYSLOT() {\
|
#define CANCELDELAYSLOT() {\
|
||||||
dsstate = 0;\
|
DSSTATE = 0;\
|
||||||
state &= ~(simDELAYSLOT | simJALDELAYSLOT);\
|
STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INDELAYSLOT() ((state & simDELAYSLOT) != 0)
|
#define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
|
||||||
#define INJALDELAYSLOT() ((state & simJALDELAYSLOT) != 0)
|
#define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
|
||||||
|
|
||||||
#define K0BASE (0x80000000)
|
#define K0BASE (0x80000000)
|
||||||
#define K0SIZE (0x20000000)
|
#define K0SIZE (0x20000000)
|
||||||
|
@ -629,11 +477,11 @@ mips_option_handler (sd, opt, arg)
|
||||||
(i.e. only from main onwards, excluding the run-time setup,
|
(i.e. only from main onwards, excluding the run-time setup,
|
||||||
etc.). */
|
etc.). */
|
||||||
if (arg == NULL)
|
if (arg == NULL)
|
||||||
state |= simTRACE;
|
STATE |= simTRACE;
|
||||||
else if (strcmp (arg, "yes") == 0)
|
else if (strcmp (arg, "yes") == 0)
|
||||||
state |= simTRACE;
|
STATE |= simTRACE;
|
||||||
else if (strcmp (arg, "no") == 0)
|
else if (strcmp (arg, "no") == 0)
|
||||||
state &= ~simTRACE;
|
STATE &= ~simTRACE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Unreconized trace option `%s'\n", arg);
|
fprintf (stderr, "Unreconized trace option `%s'\n", arg);
|
||||||
|
@ -668,7 +516,7 @@ Re-compile simulator with \"-DTRACE\" to enable this option.\n");
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
#if defined(PROFILE)
|
#if defined(PROFILE)
|
||||||
state |= simPROFILE;
|
STATE |= simPROFILE;
|
||||||
return SIM_RC_OK;
|
return SIM_RC_OK;
|
||||||
#else /* !PROFILE */
|
#else /* !PROFILE */
|
||||||
fprintf(stderr,"\
|
fprintf(stderr,"\
|
||||||
|
@ -749,6 +597,7 @@ sim_open (kind, cb, abfd, argv)
|
||||||
char **argv;
|
char **argv;
|
||||||
{
|
{
|
||||||
SIM_DESC sd = sim_state_alloc (kind, cb);
|
SIM_DESC sd = sim_state_alloc (kind, cb);
|
||||||
|
sim_cpu *cpu = STATE_CPU (sd, 0);
|
||||||
|
|
||||||
/* FIXME: watchpoints code shouldn't need this */
|
/* FIXME: watchpoints code shouldn't need this */
|
||||||
STATE_WATCHPOINTS (sd)->pc = &(PC);
|
STATE_WATCHPOINTS (sd)->pc = &(PC);
|
||||||
|
@ -760,7 +609,7 @@ sim_open (kind, cb, abfd, argv)
|
||||||
STATE_MEM_SIZE (sd) = (2 << 20);
|
STATE_MEM_SIZE (sd) = (2 << 20);
|
||||||
STATE_MEM_BASE (sd) = K1BASE;
|
STATE_MEM_BASE (sd) = K1BASE;
|
||||||
|
|
||||||
state = 0;
|
STATE = 0;
|
||||||
|
|
||||||
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
|
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -845,23 +694,21 @@ sim_open (kind, cb, abfd, argv)
|
||||||
int rn;
|
int rn;
|
||||||
for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) {
|
for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) {
|
||||||
if (rn < 32)
|
if (rn < 32)
|
||||||
register_widths[rn] = GPRLEN;
|
cpu->register_widths[rn] = GPRLEN;
|
||||||
#if defined(HASFPU)
|
|
||||||
else if ((rn >= FGRIDX) && (rn < (FGRIDX + 32)))
|
else if ((rn >= FGRIDX) && (rn < (FGRIDX + 32)))
|
||||||
register_widths[rn] = GPRLEN;
|
cpu->register_widths[rn] = GPRLEN;
|
||||||
#endif
|
|
||||||
else if ((rn >= 33) && (rn <= 37))
|
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)))
|
else if ((rn == SRIDX) || (rn == FCR0IDX) || (rn == FCR31IDX) || ((rn >= 72) && (rn <= 89)))
|
||||||
register_widths[rn] = 32;
|
cpu->register_widths[rn] = 32;
|
||||||
else
|
else
|
||||||
register_widths[rn] = 0;
|
cpu->register_widths[rn] = 0;
|
||||||
}
|
}
|
||||||
/* start-sanitize-r5900 */
|
/* start-sanitize-r5900 */
|
||||||
|
|
||||||
/* set the 5900 "upper" registers to 64 bits */
|
/* set the 5900 "upper" registers to 64 bits */
|
||||||
for( rn = LAST_EMBED_REGNUM+1; rn < NUM_REGS; rn++)
|
for( rn = LAST_EMBED_REGNUM+1; rn < NUM_REGS; rn++)
|
||||||
register_widths[rn] = 64;
|
cpu->register_widths[rn] = 64;
|
||||||
/* end-sanitize-r5900 */
|
/* end-sanitize-r5900 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -896,7 +743,7 @@ sim_open (kind, cb, abfd, argv)
|
||||||
monitor_size);
|
monitor_size);
|
||||||
|
|
||||||
#if defined(TRACE)
|
#if defined(TRACE)
|
||||||
if (state & simTRACE)
|
if (STATE & simTRACE)
|
||||||
open_trace(sd);
|
open_trace(sd);
|
||||||
#endif /* TRACE */
|
#endif /* TRACE */
|
||||||
|
|
||||||
|
@ -1064,7 +911,7 @@ sim_close (sd, quitting)
|
||||||
sim_io_shutdown (sd);
|
sim_io_shutdown (sd);
|
||||||
|
|
||||||
#if defined(PROFILE)
|
#if defined(PROFILE)
|
||||||
if ((state & simPROFILE) && (profile_hist != NULL)) {
|
if ((STATE & simPROFILE) && (profile_hist != NULL)) {
|
||||||
FILE *pf = fopen("gmon.out","wb");
|
FILE *pf = fopen("gmon.out","wb");
|
||||||
unsigned loop;
|
unsigned loop;
|
||||||
|
|
||||||
|
@ -1095,7 +942,7 @@ sim_close (sd, quitting)
|
||||||
|
|
||||||
free(profile_hist);
|
free(profile_hist);
|
||||||
profile_hist = NULL;
|
profile_hist = NULL;
|
||||||
state &= ~simPROFILE;
|
STATE &= ~simPROFILE;
|
||||||
}
|
}
|
||||||
#endif /* PROFILE */
|
#endif /* PROFILE */
|
||||||
|
|
||||||
|
@ -1103,7 +950,7 @@ sim_close (sd, quitting)
|
||||||
if (tracefh != NULL && tracefh != stderr)
|
if (tracefh != NULL && tracefh != stderr)
|
||||||
fclose(tracefh);
|
fclose(tracefh);
|
||||||
tracefh = NULL;
|
tracefh = NULL;
|
||||||
state &= ~simTRACE;
|
STATE &= ~simTRACE;
|
||||||
#endif /* TRACE */
|
#endif /* TRACE */
|
||||||
|
|
||||||
if (logfh != NULL && logfh != stdout && logfh != stderr)
|
if (logfh != NULL && logfh != stdout && logfh != stderr)
|
||||||
|
@ -1267,6 +1114,7 @@ sim_store_register (sd,rn,memory)
|
||||||
int rn;
|
int rn;
|
||||||
unsigned char *memory;
|
unsigned char *memory;
|
||||||
{
|
{
|
||||||
|
sim_cpu *cpu = STATE_CPU (sd, 0);
|
||||||
/* NOTE: gdb (the client) stores registers in target byte order
|
/* NOTE: gdb (the client) stores registers in target byte order
|
||||||
while the simulator uses host byte order */
|
while the simulator uses host byte order */
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -1277,18 +1125,18 @@ sim_store_register (sd,rn,memory)
|
||||||
numbering one. We need to know what the width of each logical
|
numbering one. We need to know what the width of each logical
|
||||||
register number is for the architecture being simulated. */
|
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);
|
sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
|
||||||
/* start-sanitize-r5900 */
|
/* start-sanitize-r5900 */
|
||||||
else if (rn == REGISTER_SA)
|
else if (rn == REGISTER_SA)
|
||||||
SA = T2H_8(*(uword64*)memory);
|
SA = T2H_8(*(uword64*)memory);
|
||||||
else if (rn > LAST_EMBED_REGNUM)
|
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 */
|
/* end-sanitize-r5900 */
|
||||||
else if (register_widths[rn] == 32)
|
else if (cpu->register_widths[rn] == 32)
|
||||||
registers[rn] = T2H_4 (*(unsigned int*)memory);
|
cpu->registers[rn] = T2H_4 (*(unsigned int*)memory);
|
||||||
else
|
else
|
||||||
registers[rn] = T2H_8 (*(uword64*)memory);
|
cpu->registers[rn] = T2H_8 (*(uword64*)memory);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1299,24 +1147,25 @@ sim_fetch_register (sd,rn,memory)
|
||||||
int rn;
|
int rn;
|
||||||
unsigned char *memory;
|
unsigned char *memory;
|
||||||
{
|
{
|
||||||
|
sim_cpu *cpu = STATE_CPU (sd, 0);
|
||||||
/* NOTE: gdb (the client) stores registers in target byte order
|
/* NOTE: gdb (the client) stores registers in target byte order
|
||||||
while the simulator uses host byte order */
|
while the simulator uses host byte order */
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn]));
|
sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn]));
|
||||||
#endif /* DEBUG */
|
#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);
|
sim_io_eprintf(sd,"Invalid register width for %d (register fetch ignored)\n",rn);
|
||||||
/* start-sanitize-r5900 */
|
/* start-sanitize-r5900 */
|
||||||
else if (rn == REGISTER_SA)
|
else if (rn == REGISTER_SA)
|
||||||
*((uword64 *)memory) = H2T_8(SA);
|
*((uword64 *)memory) = H2T_8(SA);
|
||||||
else if (rn > LAST_EMBED_REGNUM)
|
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 */
|
/* end-sanitize-r5900 */
|
||||||
else if (register_widths[rn] == 32)
|
else if (cpu->register_widths[rn] == 32)
|
||||||
*((unsigned int *)memory) = H2T_4 ((unsigned int)(registers[rn] & 0xFFFFFFFF));
|
*((unsigned int *)memory) = H2T_4 ((unsigned int)(cpu->registers[rn] & 0xFFFFFFFF));
|
||||||
else /* 64bit register */
|
else /* 64bit register */
|
||||||
*((uword64 *)memory) = H2T_8 (registers[rn]);
|
*((uword64 *)memory) = H2T_8 (cpu->registers[rn]);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1384,7 +1233,7 @@ sim_create_inferior (sd, abfd, argv,env)
|
||||||
pr_addr(PC));
|
pr_addr(PC));
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
ColdReset();
|
ColdReset(sd);
|
||||||
/* If we were providing a more complete I/O, co-processor or memory
|
/* If we were providing a more complete I/O, co-processor or memory
|
||||||
simulation, we should perform any "device" initialisation at this
|
simulation, we should perform any "device" initialisation at this
|
||||||
point. This can include pre-loading memory areas with particular
|
point. This can include pre-loading memory areas with particular
|
||||||
|
@ -1468,7 +1317,7 @@ sim_do_command (sd,cmd)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case e_reset: /* no arguments */
|
case e_reset: /* no arguments */
|
||||||
ColdReset();
|
ColdReset(sd);
|
||||||
/* NOTE: See the comments in sim_open() relating to device
|
/* NOTE: See the comments in sim_open() relating to device
|
||||||
initialisation. */
|
initialisation. */
|
||||||
break;
|
break;
|
||||||
|
@ -1504,7 +1353,7 @@ mips_set_profile (sd,n)
|
||||||
{
|
{
|
||||||
#if defined(PROFILE)
|
#if defined(PROFILE)
|
||||||
profile_frequency = n;
|
profile_frequency = n;
|
||||||
state |= simPROFILE;
|
STATE |= simPROFILE;
|
||||||
#endif /* PROFILE */
|
#endif /* PROFILE */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1515,7 +1364,7 @@ mips_set_profile_size (sd,n)
|
||||||
int n;
|
int n;
|
||||||
{
|
{
|
||||||
#if defined(PROFILE)
|
#if defined(PROFILE)
|
||||||
if (state & simPROFILE) {
|
if (STATE & simPROFILE) {
|
||||||
int bsize;
|
int bsize;
|
||||||
|
|
||||||
/* Since we KNOW that the memory banks are a power-of-2 in size: */
|
/* 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);
|
profile_hist = (unsigned short *)realloc(profile_hist,bsize);
|
||||||
if (profile_hist == NULL) {
|
if (profile_hist == NULL) {
|
||||||
sim_io_eprintf(sd,"Failed to allocate VM for profiling buffer (0x%08X bytes)\n",bsize);
|
sim_io_eprintf(sd,"Failed to allocate VM for profiling buffer (0x%08X bytes)\n",bsize);
|
||||||
state &= ~simPROFILE;
|
STATE &= ~simPROFILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* PROFILE */
|
#endif /* PROFILE */
|
||||||
|
@ -1893,7 +1742,8 @@ load_word (sd, vaddr)
|
||||||
code, but for ease of simulation we just handle them directly. */
|
code, but for ease of simulation we just handle them directly. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mips16_entry (insn)
|
mips16_entry (sd,insn)
|
||||||
|
SIM_DESC sd;
|
||||||
unsigned int insn;
|
unsigned int insn;
|
||||||
{
|
{
|
||||||
int aregs, sregs, rreg;
|
int aregs, sregs, rreg;
|
||||||
|
@ -1918,7 +1768,7 @@ mips16_entry (insn)
|
||||||
/* This is the entry pseudo-instruction. */
|
/* This is the entry pseudo-instruction. */
|
||||||
|
|
||||||
for (i = 0; i < aregs; i++)
|
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;
|
tsp = SP;
|
||||||
SP -= 32;
|
SP -= 32;
|
||||||
|
@ -1932,7 +1782,7 @@ mips16_entry (insn)
|
||||||
for (i = 0; i < sregs; i++)
|
for (i = 0; i < sregs; i++)
|
||||||
{
|
{
|
||||||
tsp -= 4;
|
tsp -= 4;
|
||||||
store_word ((uword64) tsp, registers[16 + i]);
|
store_word ((uword64) tsp, GPR[16 + i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1953,7 +1803,7 @@ mips16_entry (insn)
|
||||||
for (i = 0; i < sregs; i++)
|
for (i = 0; i < sregs; i++)
|
||||||
{
|
{
|
||||||
tsp -= 4;
|
tsp -= 4;
|
||||||
registers[i + 16] = load_word ((uword64) tsp);
|
GPR[i + 16] = load_word ((uword64) tsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
SP += 32;
|
SP += 32;
|
||||||
|
@ -1962,14 +1812,14 @@ mips16_entry (insn)
|
||||||
if (aregs == 5)
|
if (aregs == 5)
|
||||||
{
|
{
|
||||||
FGR[0] = WORD64LO (GPR[4]);
|
FGR[0] = WORD64LO (GPR[4]);
|
||||||
fpr_state[0] = fmt_uninterpreted;
|
FPR_STATE[0] = fmt_uninterpreted;
|
||||||
}
|
}
|
||||||
else if (aregs == 6)
|
else if (aregs == 6)
|
||||||
{
|
{
|
||||||
FGR[0] = WORD64LO (GPR[5]);
|
FGR[0] = WORD64LO (GPR[5]);
|
||||||
FGR[1] = WORD64LO (GPR[4]);
|
FGR[1] = WORD64LO (GPR[4]);
|
||||||
fpr_state[0] = fmt_uninterpreted;
|
FPR_STATE[0] = fmt_uninterpreted;
|
||||||
fpr_state[1] = fmt_uninterpreted;
|
FPR_STATE[1] = fmt_uninterpreted;
|
||||||
}
|
}
|
||||||
#endif /* defined(HASFPU) */
|
#endif /* defined(HASFPU) */
|
||||||
|
|
||||||
|
@ -2059,9 +1909,9 @@ getnum(sd,value)
|
||||||
|
|
||||||
|
|
||||||
static
|
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;
|
va_list ap;
|
||||||
fprintf(tracefh,"%d %s ; width %d ; ",
|
fprintf(tracefh,"%d %s ; width %d ; ",
|
||||||
type,
|
type,
|
||||||
|
@ -2095,7 +1945,8 @@ void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ColdReset()
|
ColdReset(sd)
|
||||||
|
SIM_DESC sd;
|
||||||
{
|
{
|
||||||
/* RESET: Fixed PC address: */
|
/* RESET: Fixed PC address: */
|
||||||
PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000);
|
PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000);
|
||||||
|
@ -2114,8 +1965,8 @@ ColdReset()
|
||||||
{
|
{
|
||||||
int loop;
|
int loop;
|
||||||
for (loop = 0; (loop < PSLOTS); loop++)
|
for (loop = 0; (loop < PSLOTS); loop++)
|
||||||
pending_slot_reg[loop] = (LAST_EMBED_REGNUM + 1);
|
PENDING_SLOT_REG[loop] = (LAST_EMBED_REGNUM + 1);
|
||||||
pending_in = pending_out = pending_total = 0;
|
PENDING_IN = PENDING_OUT = PENDING_TOTAL = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HASFPU)
|
#if defined(HASFPU)
|
||||||
|
@ -2123,7 +1974,7 @@ ColdReset()
|
||||||
{
|
{
|
||||||
int rn;
|
int rn;
|
||||||
for (rn = 0; (rn < 32); rn++)
|
for (rn = 0; (rn < 32); rn++)
|
||||||
fpr_state[rn] = fmt_uninterpreted;
|
FPR_STATE[rn] = fmt_uninterpreted;
|
||||||
}
|
}
|
||||||
#endif /* HASFPU */
|
#endif /* HASFPU */
|
||||||
|
|
||||||
|
@ -2305,7 +2156,7 @@ load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw)
|
||||||
|
|
||||||
#if defined(TRACE)
|
#if defined(TRACE)
|
||||||
if (!raw)
|
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 */
|
#endif /* TRACE */
|
||||||
|
|
||||||
/* NOTE: Quicker methods of decoding the address space can be used
|
/* 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 defined(TRACE)
|
||||||
if (!raw)
|
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 */
|
#endif /* TRACE */
|
||||||
|
|
||||||
/* See the comments in the LoadMemory routine about optimising
|
/* 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));
|
sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state & simDELAYSLOT)
|
if (STATE & simDELAYSLOT)
|
||||||
PC = IPC - 4; /* reference the branch instruction */
|
PC = IPC - 4; /* reference the branch instruction */
|
||||||
else
|
else
|
||||||
PC = IPC;
|
PC = IPC;
|
||||||
|
@ -2773,9 +2624,9 @@ signal_exception (SIM_DESC sd, int exception,...)
|
||||||
if (! (SR & status_EXL))
|
if (! (SR & status_EXL))
|
||||||
{
|
{
|
||||||
CAUSE = (exception << 2);
|
CAUSE = (exception << 2);
|
||||||
if (state & simDELAYSLOT)
|
if (STATE & simDELAYSLOT)
|
||||||
{
|
{
|
||||||
state &= ~simDELAYSLOT;
|
STATE &= ~simDELAYSLOT;
|
||||||
CAUSE |= cause_BD;
|
CAUSE |= cause_BD;
|
||||||
EPC = (IPC - 4); /* reference the branch instruction */
|
EPC = (IPC - 4); /* reference the branch instruction */
|
||||||
}
|
}
|
||||||
|
@ -3038,24 +2889,24 @@ value_fpr(sd,fpr,fmt)
|
||||||
#if 1
|
#if 1
|
||||||
/* If request to read data as "uninterpreted", then use the current
|
/* If request to read data as "uninterpreted", then use the current
|
||||||
encoding: */
|
encoding: */
|
||||||
fmt = fpr_state[fpr];
|
fmt = FPR_STATE[fpr];
|
||||||
#else
|
#else
|
||||||
fmt = fmt_long;
|
fmt = fmt_long;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* For values not yet accessed, set to the desired format: */
|
/* For values not yet accessed, set to the desired format: */
|
||||||
if (fpr_state[fpr] == fmt_uninterpreted) {
|
if (FPR_STATE[fpr] == fmt_uninterpreted) {
|
||||||
fpr_state[fpr] = fmt;
|
FPR_STATE[fpr] = fmt;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
|
printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
}
|
}
|
||||||
if (fmt != fpr_state[fpr]) {
|
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));
|
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;
|
FPR_STATE[fpr] = fmt_unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fpr_state[fpr] == fmt_unknown) {
|
if (FPR_STATE[fpr] == fmt_unknown) {
|
||||||
/* Set QNaN value: */
|
/* Set QNaN value: */
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
case fmt_single:
|
case fmt_single:
|
||||||
|
@ -3146,18 +2997,18 @@ store_fpr(sd,fpr,fmt,value)
|
||||||
case fmt_single :
|
case fmt_single :
|
||||||
case fmt_word :
|
case fmt_word :
|
||||||
FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
|
FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
|
||||||
fpr_state[fpr] = fmt;
|
FPR_STATE[fpr] = fmt;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fmt_uninterpreted:
|
case fmt_uninterpreted:
|
||||||
case fmt_double :
|
case fmt_double :
|
||||||
case fmt_long :
|
case fmt_long :
|
||||||
FGR[fpr] = value;
|
FGR[fpr] = value;
|
||||||
fpr_state[fpr] = fmt;
|
FPR_STATE[fpr] = fmt;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default :
|
default :
|
||||||
fpr_state[fpr] = fmt_unknown;
|
FPR_STATE[fpr] = fmt_unknown;
|
||||||
err = -1;
|
err = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3166,7 +3017,7 @@ store_fpr(sd,fpr,fmt,value)
|
||||||
case fmt_single :
|
case fmt_single :
|
||||||
case fmt_word :
|
case fmt_word :
|
||||||
FGR[fpr] = (value & 0xFFFFFFFF);
|
FGR[fpr] = (value & 0xFFFFFFFF);
|
||||||
fpr_state[fpr] = fmt;
|
FPR_STATE[fpr] = fmt;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fmt_uninterpreted:
|
case fmt_uninterpreted:
|
||||||
|
@ -3175,17 +3026,17 @@ store_fpr(sd,fpr,fmt,value)
|
||||||
if ((fpr & 1) == 0) { /* even register number only */
|
if ((fpr & 1) == 0) { /* even register number only */
|
||||||
FGR[fpr+1] = (value >> 32);
|
FGR[fpr+1] = (value >> 32);
|
||||||
FGR[fpr] = (value & 0xFFFFFFFF);
|
FGR[fpr] = (value & 0xFFFFFFFF);
|
||||||
fpr_state[fpr + 1] = fmt;
|
FPR_STATE[fpr + 1] = fmt;
|
||||||
fpr_state[fpr] = fmt;
|
FPR_STATE[fpr] = fmt;
|
||||||
} else {
|
} else {
|
||||||
fpr_state[fpr] = fmt_unknown;
|
FPR_STATE[fpr] = fmt_unknown;
|
||||||
fpr_state[fpr + 1] = fmt_unknown;
|
FPR_STATE[fpr + 1] = fmt_unknown;
|
||||||
SignalException(ReservedInstruction,0);
|
SignalException(ReservedInstruction,0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default :
|
default :
|
||||||
fpr_state[fpr] = fmt_unknown;
|
FPR_STATE[fpr] = fmt_unknown;
|
||||||
err = -1;
|
err = -1;
|
||||||
break;
|
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));
|
printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword));
|
||||||
#endif
|
#endif
|
||||||
StoreFPR(coproc_reg,fmt_word,(uword64)memword);
|
StoreFPR(coproc_reg,fmt_word,(uword64)memword);
|
||||||
fpr_state[coproc_reg] = fmt_uninterpreted;
|
FPR_STATE[coproc_reg] = fmt_uninterpreted;
|
||||||
break;
|
break;
|
||||||
#endif /* HASFPU */
|
#endif /* HASFPU */
|
||||||
|
|
||||||
|
@ -3960,17 +3811,17 @@ cop_sw(sd,coproc_num,coproc_reg)
|
||||||
#if 1
|
#if 1
|
||||||
{
|
{
|
||||||
FP_formats hold;
|
FP_formats hold;
|
||||||
hold = fpr_state[coproc_reg];
|
hold = FPR_STATE[coproc_reg];
|
||||||
fpr_state[coproc_reg] = fmt_word;
|
FPR_STATE[coproc_reg] = fmt_word;
|
||||||
value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
|
value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
|
||||||
fpr_state[coproc_reg] = hold;
|
FPR_STATE[coproc_reg] = hold;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#if 1
|
#if 1
|
||||||
value = (unsigned int)ValueFPR(coproc_reg,fpr_state[coproc_reg]);
|
value = (unsigned int)ValueFPR(coproc_reg,FPR_STATE[coproc_reg]);
|
||||||
#else
|
#else
|
||||||
#ifdef DEBUG
|
#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 */
|
#endif /* DEBUG */
|
||||||
value = (unsigned int)ValueFPR(coproc_reg,fmt_single);
|
value = (unsigned int)ValueFPR(coproc_reg,fmt_single);
|
||||||
#endif
|
#endif
|
||||||
|
@ -4001,10 +3852,10 @@ cop_sd(sd,coproc_num,coproc_reg)
|
||||||
value = ValueFPR(coproc_reg,fmt_uninterpreted);
|
value = ValueFPR(coproc_reg,fmt_uninterpreted);
|
||||||
#else
|
#else
|
||||||
#if 1
|
#if 1
|
||||||
value = ValueFPR(coproc_reg,fpr_state[coproc_reg]);
|
value = ValueFPR(coproc_reg,FPR_STATE[coproc_reg]);
|
||||||
#else
|
#else
|
||||||
#ifdef DEBUG
|
#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 */
|
#endif /* DEBUG */
|
||||||
value = ValueFPR(coproc_reg,fmt_double);
|
value = ValueFPR(coproc_reg,fmt_double);
|
||||||
#endif
|
#endif
|
||||||
|
@ -4218,7 +4069,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
||||||
}
|
}
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
dsstate = (state & simDELAYSLOT);
|
DSSTATE = (STATE & simDELAYSLOT);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (dsstate)
|
if (dsstate)
|
||||||
sim_io_printf(sd,"DBG: DSPC = 0x%s\n",pr_addr(DSPC));
|
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)
|
if (instruction_fetches == 0)
|
||||||
instruction_fetch_overflow++;
|
instruction_fetch_overflow++;
|
||||||
#if defined(PROFILE)
|
#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));
|
unsigned n = ((unsigned int)(PC - profile_minpc) >> (profile_shift + 2));
|
||||||
if (n < profile_nsamples) {
|
if (n < profile_nsamples) {
|
||||||
/* NOTE: The counts for the profiling bins are only 16bits wide */
|
/* 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)
|
#if defined(HASFPU)
|
||||||
/* Set previous flag, depending on current: */
|
/* Set previous flag, depending on current: */
|
||||||
if (state & simPCOC0)
|
if (STATE & simPCOC0)
|
||||||
state |= simPCOC1;
|
STATE |= simPCOC1;
|
||||||
else
|
else
|
||||||
state &= ~simPCOC1;
|
STATE &= ~simPCOC1;
|
||||||
/* and update the current value: */
|
/* and update the current value: */
|
||||||
if (GETFCC(0))
|
if (GETFCC(0))
|
||||||
state |= simPCOC0;
|
STATE |= simPCOC0;
|
||||||
else
|
else
|
||||||
state &= ~simPCOC0;
|
STATE &= ~simPCOC0;
|
||||||
#endif /* HASFPU */
|
#endif /* HASFPU */
|
||||||
|
|
||||||
/* NOTE: For multi-context simulation environments the "instruction"
|
/* 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
|
variables (and a single-threaded simulator engine), then we can
|
||||||
create the actual variables with these names. */
|
create the actual variables with these names. */
|
||||||
|
|
||||||
if (!(state & simSKIPNEXT)) {
|
if (!(STATE & simSKIPNEXT)) {
|
||||||
/* Include the simulator engine */
|
/* Include the simulator engine */
|
||||||
#include "engine.c"
|
#include "engine.c"
|
||||||
#if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
|
#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 */
|
ZERO = 0; /* reset back to zero before next instruction */
|
||||||
}
|
}
|
||||||
} else /* simSKIPNEXT check */
|
} else /* simSKIPNEXT check */
|
||||||
state &= ~simSKIPNEXT;
|
STATE &= ~simSKIPNEXT;
|
||||||
|
|
||||||
/* If the delay slot was active before the instruction is
|
/* If the delay slot was active before the instruction is
|
||||||
executed, then update the PC to its new value: */
|
executed, then update the PC to its new value: */
|
||||||
if (dsstate) {
|
if (DSSTATE) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("DBG: dsstate set before instruction execution - updating PC to 0x%s\n",pr_addr(DSPC));
|
printf("DBG: dsstate set before instruction execution - updating PC to 0x%s\n",pr_addr(DSPC));
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
@ -4395,11 +4246,11 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
|
printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
if (pending_out != pending_in) {
|
if (PENDING_OUT != PENDING_IN) {
|
||||||
int loop;
|
int loop;
|
||||||
int index = pending_out;
|
int index = PENDING_OUT;
|
||||||
int total = pending_total;
|
int total = PENDING_TOTAL;
|
||||||
if (pending_total == 0) {
|
if (PENDING_TOTAL == 0) {
|
||||||
fprintf(stderr,"FATAL: Mis-match on pending update pointers\n");
|
fprintf(stderr,"FATAL: Mis-match on pending update pointers\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -4407,39 +4258,39 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("DBG: BEFORE index = %d, loop = %d\n",index,loop);
|
printf("DBG: BEFORE index = %d, loop = %d\n",index,loop);
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
if (pending_slot_reg[index] != (LAST_EMBED_REGNUM + 1)) {
|
if (PENDING_SLOT_REG[index] != (LAST_EMBED_REGNUM + 1)) {
|
||||||
#ifdef DEBUG
|
#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 */
|
#endif /* DEBUG */
|
||||||
if (--(pending_slot_count[index]) == 0) {
|
if (--(PENDING_SLOT_COUNT[index]) == 0) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("pending_slot_reg[%d] = %d\n",index,pending_slot_reg[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]));
|
printf("pending_slot_value[%d] = 0x%s\n",index,pr_addr(PENDING_SLOT_VALUE[index]));
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
if (pending_slot_reg[index] == COCIDX) {
|
if (PENDING_SLOT_REG[index] == COCIDX) {
|
||||||
#if defined(HASFPU)
|
#if defined(HASFPU)
|
||||||
SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
|
SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
|
||||||
#else
|
#else
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
registers[pending_slot_reg[index]] = pending_slot_value[index];
|
REGISTERS[PENDING_SLOT_REG[index]] = PENDING_SLOT_VALUE[index];
|
||||||
#if defined(HASFPU)
|
#if defined(HASFPU)
|
||||||
/* The only time we have PENDING updates to FPU
|
/* The only time we have PENDING updates to FPU
|
||||||
registers, is when performing binary transfers. This
|
registers, is when performing binary transfers. This
|
||||||
means we should update the register type field. */
|
means we should update the register type field. */
|
||||||
if ((pending_slot_reg[index] >= FGRIDX) && (pending_slot_reg[index] < (FGRIDX + 32)))
|
if ((PENDING_SLOT_REG[index] >= FGRIDX) && (PENDING_SLOT_REG[index] < (FGRIDX + 32)))
|
||||||
fpr_state[pending_slot_reg[index] - FGRIDX] = fmt_uninterpreted;
|
FPR_STATE[PENDING_SLOT_REG[index] - FGRIDX] = fmt_uninterpreted;
|
||||||
#endif /* HASFPU */
|
#endif /* HASFPU */
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#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 */
|
#endif /* DEBUG */
|
||||||
pending_slot_reg[index] = (LAST_EMBED_REGNUM + 1);
|
PENDING_SLOT_REG[index] = (LAST_EMBED_REGNUM + 1);
|
||||||
pending_out++;
|
PENDING_OUT++;
|
||||||
if (pending_out == PSLOTS)
|
if (PENDING_OUT == PSLOTS)
|
||||||
pending_out = 0;
|
PENDING_OUT = 0;
|
||||||
pending_total--;
|
PENDING_TOTAL--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -4451,7 +4302,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#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 */
|
#endif /* DEBUG */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,8 +78,215 @@ typedef unsigned64 uword64;
|
||||||
#endif
|
#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 {
|
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;
|
sim_cpu_base base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -150,43 +357,6 @@ void signal_exception (SIM_DESC sd, int exception, ...);
|
||||||
#define SignalExceptionCoProcessorUnusable() signal_exception (sd, CoProcessorUnusable)
|
#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 */
|
/* Co-processor accesses */
|
||||||
|
|
||||||
void cop_lw PARAMS ((SIM_DESC sd, int coproc_num, int coproc_reg, unsigned int memword));
|
void cop_lw PARAMS ((SIM_DESC sd, int coproc_num, int coproc_reg, unsigned int memword));
|
||||||
|
|
Loading…
Reference in a new issue