#define AccessLength_DOUBLEWORD (7)
#define AccessLength_QUADWORD (15)
-/* NOTE: We cannot avoid globals, since the GDB "sim_" interface does
- not allow a private variable to be passed around. This means that
- simulators under GDB can only be single-threaded. However, it would
- be possible for the simulators to be multi-threaded if GDB allowed
- for a private pointer to be maintained. i.e. a general "void **ptr"
- variable that GDB passed around in the argument list to all of
- sim_xxx() routines. It could be initialised to NULL by GDB, and
- then updated by sim_open() and used by the other sim_xxx() support
- functions. This would allow new features in the simulator world,
- like storing a context - continuing execution to gather a result,
- and then going back to the point where the context was saved and
- changing some state before continuing. i.e. the ability to perform
- UNDOs on simulations. It would also allow the simulation of
- shared-memory multi-processor systems.
-
- [NOTE: This is now partially implemented] */
-
-/* This is nasty, since we have to rely on matching the register
- numbers used by GDB. Unfortunately, depending on the MIPS target
- GDB uses different register numbers. We cannot just include the
- relevant "gdb/tm.h" link, since GDB may not be configured before
- the sim world, and also the GDB header file requires too much other
- state. */
-/* TODO: Sort out a scheme for *KNOWING* the mapping between real
- registers, and the numbers that GDB uses. At the moment due to the
- order that the tools are built, we cannot rely on a configured GDB
- world whilst constructing the simulator. This means we have to
- assume the GDB register number mapping. */
-#ifndef TM_MIPS_H
-#define LAST_EMBED_REGNUM (89)
-#define NUM_REGS (LAST_EMBED_REGNUM + 1)
-/* start-sanitize-r5900 */
-#undef NUM_REGS
-#define NUM_REGS (128)
-/* end-sanitize-r5900 */
-#endif
-
-/* To keep this default simulator simple, and fast, we use a direct
- vector of registers. The internal simulator engine then uses
- manifests to access the correct slot. */
-static ut_reg registers[LAST_EMBED_REGNUM + 1];
-static int register_widths[NUM_REGS];
-
-#define GPR (®isters[0])
-#if defined(HASFPU)
-#define FGRIDX (38)
-#define FGR (®isters[FGRIDX])
-#endif /* HASFPU */
-#define LO (registers[33])
-#define HI (registers[34])
-#define PC (registers[37])
-#define CAUSE (registers[36])
-#define SRIDX (32)
-#define SR (registers[SRIDX]) /* CPU status register */
-#define FCR0IDX (71)
-#define FCR0 (registers[FCR0IDX]) /* really a 32bit register */
-#define FCR31IDX (70)
-#define FCR31 (registers[FCR31IDX]) /* really a 32bit register */
-#define FCSR (FCR31)
-#define Debug (registers[86])
-#define DEPC (registers[87])
-#define EPC (registers[88])
-#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */
-
-/* The following are pseudonyms for standard registers */
-#define ZERO (registers[0])
-#define V0 (registers[2])
-#define A0 (registers[4])
-#define A1 (registers[5])
-#define A2 (registers[6])
-#define A3 (registers[7])
-#define SP (registers[29])
-#define RA (registers[31])
-
/* Bits in the Debug register */
#define Debug_DBD 0x80000000 /* Debug Branch Delay */
/* start-sanitize-r5900 */
-/*
-The R5900 has 128 bit registers, but the hi 64 bits are only touched by
-multimedia (MMI) instructions. The normal mips instructions just use the
-lower 64 bits. To avoid changing the older parts of the simulator to
-handle this weirdness, the high 64 bits of each register are kept in
-a separate array (registers1). The high 64 bits of any register are by
-convention refered by adding a '1' to the end of the normal register's
-name. So LO still refers to the low 64 bits of the LO register, LO1
-refers to the high 64 bits of that same register.
-*/
-
-/* The high part of each register */
-static ut_reg registers1[LAST_EMBED_REGNUM + 1];
-
-#define GPR1 (®isters1[0])
-#define LO1 (registers1[32])
-#define HI1 (registers1[33])
-#define REGISTER_SA (124)
-
-#define BYTES_IN_MMI_REGS (sizeof(registers[0])+sizeof(registers1[0]))
+#define BYTES_IN_MMI_REGS (sizeof(signed_word) + sizeof(signed_word))
#define HALFWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/2)
#define WORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/4)
#define DOUBLEWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/8)
-#define BYTES_IN_MIPS_REGS (sizeof(registers[0]))
+#define BYTES_IN_MIPS_REGS (sizeof(signed_word))
#define HALFWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/2)
#define WORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/4)
#define DOUBLEWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/8)
+
+
/*
SUB_REG_FETCH - return as lvalue some sub-part of a "register"
T - type of the sub part
#define SUB_REG_UW(A,A1,I) SUB_REG_FETCH(unsigned32, WORDS_IN_MIPS_REGS, A, A1, I)
#define SUB_REG_UD(A,A1,I) SUB_REG_FETCH(unsigned64, DOUBLEWORDS_IN_MIPS_REGS, A, A1, I)
-#define GPR_SB(R,I) SUB_REG_SB(®isters[R], ®isters1[R], I)
-#define GPR_SH(R,I) SUB_REG_SH(®isters[R], ®isters1[R], I)
-#define GPR_SW(R,I) SUB_REG_SW(®isters[R], ®isters1[R], I)
-#define GPR_SD(R,I) SUB_REG_SD(®isters[R], ®isters1[R], I)
+#define GPR_SB(R,I) SUB_REG_SB(®ISTERS[R], ®ISTERS1[R], I)
+#define GPR_SH(R,I) SUB_REG_SH(®ISTERS[R], ®ISTERS1[R], I)
+#define GPR_SW(R,I) SUB_REG_SW(®ISTERS[R], ®ISTERS1[R], I)
+#define GPR_SD(R,I) SUB_REG_SD(®ISTERS[R], ®ISTERS1[R], I)
-#define GPR_UB(R,I) SUB_REG_UB(®isters[R], ®isters1[R], I)
-#define GPR_UH(R,I) SUB_REG_UH(®isters[R], ®isters1[R], I)
-#define GPR_UW(R,I) SUB_REG_UW(®isters[R], ®isters1[R], I)
-#define GPR_UD(R,I) SUB_REG_UD(®isters[R], ®isters1[R], I)
+#define GPR_UB(R,I) SUB_REG_UB(®ISTERS[R], ®ISTERS1[R], I)
+#define GPR_UH(R,I) SUB_REG_UH(®ISTERS[R], ®ISTERS1[R], I)
+#define GPR_UW(R,I) SUB_REG_UW(®ISTERS[R], ®ISTERS1[R], I)
+#define GPR_UD(R,I) SUB_REG_UD(®ISTERS[R], ®ISTERS1[R], I)
#define RS_SB(I) SUB_REG_SB(&rs_reg, &rs_reg1, I)
/* 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: */
/* 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: */
#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));
/* 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
/* 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
#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)
(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);
case 'p':
#if defined(PROFILE)
- state |= simPROFILE;
+ STATE |= simPROFILE;
return SIM_RC_OK;
#else /* !PROFILE */
fprintf(stderr,"\
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);
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;
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 */
}
monitor_size);
#if defined(TRACE)
- if (state & simTRACE)
+ if (STATE & simTRACE)
open_trace(sd);
#endif /* TRACE */
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;
free(profile_hist);
profile_hist = NULL;
- state &= ~simPROFILE;
+ STATE &= ~simPROFILE;
}
#endif /* PROFILE */
if (tracefh != NULL && tracefh != stderr)
fclose(tracefh);
tracefh = NULL;
- state &= ~simTRACE;
+ STATE &= ~simTRACE;
#endif /* TRACE */
if (logfh != NULL && logfh != stdout && logfh != stderr)
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
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;
}
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;
}
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
break;
case e_reset: /* no arguments */
- ColdReset();
+ ColdReset(sd);
/* NOTE: See the comments in sim_open() relating to device
initialisation. */
break;
{
#if defined(PROFILE)
profile_frequency = n;
- state |= simPROFILE;
+ STATE |= simPROFILE;
#endif /* PROFILE */
return;
}
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: */
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 */
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;
/* 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;
for (i = 0; i < sregs; i++)
{
tsp -= 4;
- store_word ((uword64) tsp, registers[16 + i]);
+ store_word ((uword64) tsp, GPR[16 + i]);
}
}
else
for (i = 0; i < sregs; i++)
{
tsp -= 4;
- registers[i + 16] = load_word ((uword64) tsp);
+ GPR[i + 16] = load_word ((uword64) tsp);
}
SP += 32;
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) */
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,
/*---------------------------------------------------------------------------*/
static void
-ColdReset()
+ColdReset(sd)
+ SIM_DESC sd;
{
/* RESET: Fixed PC address: */
PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000);
{
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)
{
int rn;
for (rn = 0; (rn < 32); rn++)
- fpr_state[rn] = fmt_uninterpreted;
+ FPR_STATE[rn] = fmt_uninterpreted;
}
#endif /* HASFPU */
#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
#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
sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
}
}
- if (state & simDELAYSLOT)
+ if (STATE & simDELAYSLOT)
PC = IPC - 4; /* reference the branch instruction */
else
PC = IPC;
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 */
}
#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:
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;
}
case fmt_single :
case fmt_word :
FGR[fpr] = (value & 0xFFFFFFFF);
- fpr_state[fpr] = fmt;
+ FPR_STATE[fpr] = fmt;
break;
case fmt_uninterpreted:
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;
}
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 */
#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
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
}
#endif /* DEBUG */
- dsstate = (state & simDELAYSLOT);
+ DSSTATE = (STATE & simDELAYSLOT);
#ifdef DEBUG
if (dsstate)
sim_io_printf(sd,"DBG: DSPC = 0x%s\n",pr_addr(DSPC));
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 */
#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"
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)
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 */
#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);
}
#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
}
}
#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
-/* FIXME: At present the CPU registers are static */
+/* Floating-point operations: */
+
+/* FPU registers must be one of the following types. All other values
+ are reserved (and undefined). */
+typedef enum {
+ fmt_single = 0,
+ fmt_double = 1,
+ fmt_word = 4,
+ fmt_long = 5,
+ /* The following are well outside the normal acceptable format
+ range, and are used in the register status vector. */
+ fmt_unknown = 0x10000000,
+ fmt_uninterpreted = 0x20000000,
+} FP_formats;
+
+unsigned64 value_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats));
+#define ValueFPR(FPR,FMT) value_fpr (sd, (FPR), (FMT))
+
+void store_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats fmt, unsigned64 value));
+#define StoreFPR(FPR,FMT,VALUE) store_fpr (sd, (FPR), (FMT), (VALUE))
+
+int NaN PARAMS ((unsigned64 op, FP_formats fmt));
+int Infinity PARAMS ((unsigned64 op, FP_formats fmt));
+int Less PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
+int Equal PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
+unsigned64 AbsoluteValue PARAMS ((unsigned64 op, FP_formats fmt));
+unsigned64 Negate PARAMS ((unsigned64 op, FP_formats fmt));
+unsigned64 Add PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
+unsigned64 Sub PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
+unsigned64 Multiply PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
+unsigned64 Divide PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
+unsigned64 Recip PARAMS ((unsigned64 op, FP_formats fmt));
+unsigned64 SquareRoot PARAMS ((unsigned64 op, FP_formats fmt));
+unsigned64 convert PARAMS ((SIM_DESC sd, int rm, unsigned64 op, FP_formats from, FP_formats to));
+#define Convert(rm,op,from,to) convert(sd,rm,op,from,to)
+
+
+
+
struct _sim_cpu {
+
+
+ /* The following are internal simulator state variables: */
+ address_word ipc; /* internal Instruction PC */
+ address_word dspc; /* delay-slot PC */
+#define IPC ((STATE_CPU (sd,0))->ipc)
+#define DSPC ((STATE_CPU (sd,0))->dspc)
+
+
+ /* State of the simulator */
+ unsigned int state;
+ unsigned int dsstate;
+#define STATE ((STATE_CPU (sd,0))->state)
+#define DSSTATE ((STATE_CPU (sd,0))->dsstate)
+
+
+/* This is nasty, since we have to rely on matching the register
+ numbers used by GDB. Unfortunately, depending on the MIPS target
+ GDB uses different register numbers. We cannot just include the
+ relevant "gdb/tm.h" link, since GDB may not be configured before
+ the sim world, and also the GDB header file requires too much other
+ state. */
+
+#ifndef TM_MIPS_H
+#define LAST_EMBED_REGNUM (89)
+#define NUM_REGS (LAST_EMBED_REGNUM + 1)
+/* start-sanitize-r5900 */
+#undef NUM_REGS
+#define NUM_REGS (128)
+/* end-sanitize-r5900 */
+#endif
+
+/* To keep this default simulator simple, and fast, we use a direct
+ vector of registers. The internal simulator engine then uses
+ manifests to access the correct slot. */
+
+ signed_word registers[LAST_EMBED_REGNUM + 1];
+ int register_widths[NUM_REGS];
+#define REGISTERS ((STATE_CPU (sd,0))->registers)
+
+#define GPR (®ISTERS[0])
+#define FGRIDX (38)
+#define FGR (®ISTERS[FGRIDX])
+#define LO (REGISTERS[33])
+#define HI (REGISTERS[34])
+#define PC (REGISTERS[37])
+#define CAUSE (REGISTERS[36])
+#define SRIDX (32)
+#define SR (REGISTERS[SRIDX]) /* CPU status register */
+#define FCR0IDX (71)
+#define FCR0 (REGISTERS[FCR0IDX]) /* really a 32bit register */
+#define FCR31IDX (70)
+#define FCR31 (REGISTERS[FCR31IDX]) /* really a 32bit register */
+#define FCSR (FCR31)
+#define Debug (REGISTERS[86])
+#define DEPC (REGISTERS[87])
+#define EPC (REGISTERS[88])
+#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */
+
+/* The following are pseudonyms for standard registers */
+#define ZERO (REGISTERS[0])
+#define V0 (REGISTERS[2])
+#define A0 (REGISTERS[4])
+#define A1 (REGISTERS[5])
+#define A2 (REGISTERS[6])
+#define A3 (REGISTERS[7])
+#define SP (REGISTERS[29])
+#define RA (REGISTERS[31])
+
+ /* Keep the current format state for each register: */
+ FP_formats fpr_state[32];
+#define FPR_STATE ((STATE_CPU (sd, 0))->fpr_state)
+
+
+ /* Slots for delayed register updates. For the moment we just have a
+ fixed number of slots (rather than a more generic, dynamic
+ system). This keeps the simulator fast. However, we only allow
+ for the register update to be delayed for a single instruction
+ cycle. */
+#define PSLOTS (5) /* Maximum number of instruction cycles */
+ int pending_in;
+ int pending_out;
+ int pending_total;
+ int pending_slot_count[PSLOTS];
+ int pending_slot_reg[PSLOTS];
+ unsigned_word pending_slot_value[PSLOTS];
+#define PENDING_IN ((STATE_CPU (sd, 0))->pending_in)
+#define PENDING_OUT ((STATE_CPU (sd, 0))->pending_out)
+#define PENDING_TOTAL ((STATE_CPU (sd, 0))->pending_total)
+#define PENDING_SLOT_COUNT ((STATE_CPU (sd, 0))->pending_slot_count)
+#define PENDING_SLOT_REG ((STATE_CPU (sd, 0))->pending_slot_reg)
+#define PENDING_SLOT_VALUE ((STATE_CPU (sd, 0))->pending_slot_value)
+
+
+ /* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic
+ read-write instructions. It is set when a linked load occurs. It
+ is tested and cleared by the conditional store. It is cleared
+ (during other CPU operations) when a store to the location would
+ no longer be atomic. In particular, it is cleared by exception
+ return instructions. */
+ int llbit;
+#define LLBIT ((STATE_CPU (sd, 0))->llbit)
+
+
+/* The HIACCESS and LOACCESS counts are used to ensure that
+ corruptions caused by using the HI or LO register to close to a
+ following operation are spotted. */
+
+ int hiaccess;
+ int loaccess;
+#define HIACCESS ((STATE_CPU (sd, 0))->hiaccess)
+#define LOACCESS ((STATE_CPU (sd, 0))->loaccess)
+ /* start-sanitize-r5900 */
+ int hi1access;
+ int lo1access;
+#define HI1ACCESS ((STATE_CPU (sd, 0))->hi1access)
+#define LO1ACCESS ((STATE_CPU (sd, 0))->lo1access)
+ /* end-sanitize-r5900 */
+#if 1
+ /* The 4300 and a few other processors have interlocks on hi/lo
+ register reads, and hence do not have this problem. To avoid
+ spurious warnings, we just disable this always. */
+#define CHECKHILO(s)
+#else
+ unsigned_word HLPC;
+ /* If either of the preceding two instructions have accessed the HI
+ or LO registers, then the values they see should be
+ undefined. However, to keep the simulator world simple, we just
+ let them use the value read and raise a warning to notify the
+ user: */
+#define CHECKHILO(s) {\
+ if ((HIACCESS != 0) || (LOACCESS != 0)) \
+ sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\
+}
+ /* end-sanitize-r5900 */
+#undef CHECKHILO
+#define CHECKHILO(s) {\
+ if ((HIACCESS != 0) || (LOACCESS != 0) || (HI1ACCESS != 0) || (LO1ACCESS != 0))\
+ sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\
+}
+ /* end-sanitize-r5900 */
+#endif
+
+
+ /* start-sanitize-r5900 */
+ /* The R5900 has 128 bit registers, but the hi 64 bits are only
+ touched by multimedia (MMI) instructions. The normal mips
+ instructions just use the lower 64 bits. To avoid changing the
+ older parts of the simulator to handle this weirdness, the high
+ 64 bits of each register are kept in a separate array
+ (registers1). The high 64 bits of any register are by convention
+ refered by adding a '1' to the end of the normal register's name.
+ So LO still refers to the low 64 bits of the LO register, LO1
+ refers to the high 64 bits of that same register. */
+
+ signed_word registers1[LAST_EMBED_REGNUM + 1];
+#define REGISTERS1 ((STATE_CPU (sd, 0))->registers1)
+#define GPR1 (®ISTERS1[0])
+#define LO1 (REGISTERS1[32])
+#define HI1 (REGISTERS1[33])
+#define REGISTER_SA (124)
+
+ unsigned_word sa; /* the shift amount register */
+#define SA ((STATE_CPU (sd, 0))->sa)
+
+ /* end-sanitize-r5900 */
+
+
+
sim_cpu_base base;
};
#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));