Move global MIPS simulator variables into sim_cpu struct.

This commit is contained in:
Andrew Cagney 1997-10-14 09:26:03 +00:00
parent 1b217de0f3
commit 0c2c5f6141
4 changed files with 369 additions and 330 deletions

View File

@ -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.

View File

@ -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

View File

@ -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 (&registers[0])
#if defined(HASFPU)
#define FGRIDX (38)
#define FGR (&registers[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 (&registers1[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(&registers[R], &registers1[R], I)
#define GPR_SH(R,I) SUB_REG_SH(&registers[R], &registers1[R], I)
#define GPR_SW(R,I) SUB_REG_SW(&registers[R], &registers1[R], I)
#define GPR_SD(R,I) SUB_REG_SD(&registers[R], &registers1[R], I)
#define GPR_SB(R,I) SUB_REG_SB(&REGISTERS[R], &REGISTERS1[R], I)
#define GPR_SH(R,I) SUB_REG_SH(&REGISTERS[R], &REGISTERS1[R], I)
#define GPR_SW(R,I) SUB_REG_SW(&REGISTERS[R], &REGISTERS1[R], I)
#define GPR_SD(R,I) SUB_REG_SD(&REGISTERS[R], &REGISTERS1[R], I)
#define GPR_UB(R,I) SUB_REG_UB(&registers[R], &registers1[R], I)
#define GPR_UH(R,I) SUB_REG_UH(&registers[R], &registers1[R], I)
#define GPR_UW(R,I) SUB_REG_UW(&registers[R], &registers1[R], I)
#define GPR_UD(R,I) SUB_REG_UD(&registers[R], &registers1[R], I)
#define GPR_UB(R,I) SUB_REG_UB(&REGISTERS[R], &REGISTERS1[R], I)
#define GPR_UH(R,I) SUB_REG_UH(&REGISTERS[R], &REGISTERS1[R], I)
#define GPR_UW(R,I) SUB_REG_UW(&REGISTERS[R], &REGISTERS1[R], I)
#define GPR_UD(R,I) SUB_REG_UD(&REGISTERS[R], &REGISTERS1[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 */
}

View File

@ -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 (&REGISTERS[0])
#define FGRIDX (38)
#define FGR (&REGISTERS[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 (&REGISTERS1[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));