aboutsummaryrefslogtreecommitdiff
path: root/sim/mips
diff options
context:
space:
mode:
Diffstat (limited to 'sim/mips')
-rw-r--r--sim/mips/ChangeLog18
-rw-r--r--sim/mips/interp.c157
2 files changed, 163 insertions, 12 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog
index f3ffe86..0f7b64d 100644
--- a/sim/mips/ChangeLog
+++ b/sim/mips/ChangeLog
@@ -1,3 +1,21 @@
+Wed May 8 15:12:58 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * interp.c (xfer_direct_word, xfer_direct_long,
+ swap_direct_word, swap_direct_long, xfer_big_word,
+ xfer_big_long, xfer_little_word, xfer_little_long,
+ swap_word,swap_long): Added.
+ * interp.c (ColdReset): Provide function indirection to
+ host<->simulated_target transfer routines.
+ * interp.c (sim_store_register, sim_fetch_register): Updated to
+ make use of indirected transfer routines.
+
+Fri Apr 19 15:48:24 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gencode.c (process_instructions): Ensure FP ABS instruction
+ recognised.
+ * interp.c (AbsoluteValue): Add routine. Also provide simple PMON
+ system call support.
+
Wed Apr 10 09:51:38 1996 James G. Smith <jsmith@cygnus.co.uk>
* interp.c (sim_do_command): Complain if callback structure not
diff --git a/sim/mips/interp.c b/sim/mips/interp.c
index cda45d6..af3ae29 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -61,6 +61,9 @@ code on the hardware.
#include "engine.c"
#undef SIM_MANIFESTS
+/* This variable holds the GDB view of the target endianness: */
+extern int target_byte_order;
+
/* The following reserved instruction value is used when a simulator
trap is required. NOTE: Care must be taken, since this value may be
used in later revisions of the MIPS ISA. */
@@ -405,7 +408,7 @@ unsigned int pipeline_ticks = 0;
#define simEXCEPTION (1 << 26) /* 0 = no exception; 1 = exception has occurred */
#define simEXIT (1 << 27) /* 0 = do nothing; 1 = run-time exit() processing */
-unsigned int state = (0 | simBE); /* big-endian simulator by default */
+unsigned int state = 0;
unsigned int rcexit = 0; /* _exit() reason code holder */
#define DELAYSLOT() {\
@@ -447,6 +450,19 @@ ut_reg profile_maxpc;
int profile_shift = 0; /* address shift amount */
#endif /* PROFILE */
+/* The following are used to provide shortcuts to the required version
+ of host<->target copying. This avoids run-time conditionals, which
+ would slow the simulator throughput. */
+typedef unsigned int (*fnptr_read_word) PARAMS((unsigned char *memory));
+typedef unsigned int (*fnptr_swap_word) PARAMS((unsigned int data));
+typedef uword64 (*fnptr_read_long) PARAMS((unsigned char *memory));
+typedef uword64 (*fnptr_swap_long) PARAMS((uword64 data));
+
+fnptr_read_word host_read_word;
+fnptr_read_long host_read_long;
+fnptr_swap_word host_swap_word;
+fnptr_swap_long host_swap_long;
+
/*---------------------------------------------------------------------------*/
/*-- GDB simulator interface ------------------------------------------------*/
/*---------------------------------------------------------------------------*/
@@ -459,10 +475,12 @@ static void StoreMemory PARAMS((int CCA,int AccessLength,uword64 MemElem,uword64
static uword64 LoadMemory PARAMS((int CCA,int AccessLength,uword64 pAddr,uword64 vAddr,int IorD,int raw));
static void SignalException PARAMS((int exception,...));
static void simulate PARAMS((void));
-static long getnum(char *value);
-extern void sim_size(unsigned int newsize);
-extern void sim_set_profile(int frequency);
-static unsigned int power2(unsigned int value);
+static long getnum PARAMS((char *value));
+extern void sim_size PARAMS((unsigned int newsize));
+extern void sim_set_profile PARAMS((int frequency));
+static unsigned int power2 PARAMS((unsigned int value));
+
+/*---------------------------------------------------------------------------*/
void
sim_open (args)
@@ -1056,9 +1074,9 @@ sim_store_register (rn,memory)
callback->printf_filtered(callback,"Warning: Invalid register width for %d (register store ignored)\n",rn);
else {
if (register_widths[rn] == 32)
- registers[rn] = *((unsigned int *)memory);
+ registers[rn] = host_read_word(memory);
else
- registers[rn] = *((uword64 *)memory);
+ registers[rn] = host_read_long(memory);
}
return;
@@ -1077,9 +1095,9 @@ sim_fetch_register (rn,memory)
callback->printf_filtered(callback,"Warning: Invalid register width for %d (register fetch ignored)\n",rn);
else {
if (register_widths[rn] == 32)
- *((unsigned int *)memory) = (registers[rn] & 0xFFFFFFFF);
+ *((unsigned int *)memory) = host_swap_word(registers[rn] & 0xFFFFFFFF);
else /* 64bit register */
- *((uword64 *)memory) = registers[rn];
+ *((uword64 *)memory) = host_swap_long(registers[rn]);
}
return;
}
@@ -1722,6 +1740,95 @@ void dotrace(tracefh,type,address,width,comment)
#endif /* TRACE */
/*---------------------------------------------------------------------------*/
+/*-- host<->target transfers ------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/* The following routines allow conditionals to be avoided during the
+ simulation, at the cost of increasing the image and source size. */
+
+static unsigned int
+xfer_direct_word(memory)
+ unsigned char *memory;
+{
+ return *((unsigned int *)memory);
+}
+
+static uword64
+xfer_direct_long(memory)
+ unsigned char *memory;
+{
+ return *((uword64 *)memory);
+}
+
+static unsigned int
+swap_direct_word(data)
+ unsigned int data;
+{
+ return data;
+}
+
+static uword64
+swap_direct_long(data)
+ uword64 data;
+{
+ return data;
+}
+
+static unsigned int
+xfer_big_word(memory)
+ unsigned char *memory;
+{
+ return ((memory[0] << 24) | (memory[1] << 16) | (memory[2] << 8) | memory[3]);
+}
+
+static uword64
+xfer_big_long(memory)
+ unsigned char *memory;
+{
+ return (((uword64)memory[0] << 56) | ((uword64)memory[1] << 48)
+ | ((uword64)memory[2] << 40) | ((uword64)memory[3] << 32)
+ | (memory[4] << 24) | (memory[5] << 16) | (memory[6] << 8) | memory[7]);
+}
+
+static unsigned int
+xfer_little_word(memory)
+ unsigned char *memory;
+{
+ return ((memory[3] << 24) | (memory[2] << 16) | (memory[1] << 8) | memory[0]);
+}
+
+static uword64
+xfer_little_long(memory)
+ unsigned char *memory;
+{
+ return (((uword64)memory[7] << 56) | ((uword64)memory[6] << 48)
+ | ((uword64)memory[5] << 40) | ((uword64)memory[4] << 32)
+ | (memory[3] << 24) | (memory[2] << 16) | (memory[1] << 8) | memory[0]);
+}
+
+static unsigned int
+swap_word(data)
+ unsigned int data;
+{
+ unsigned int result;
+ result = data ^ ((data << 16) | (data >> 16));
+ result &= ~0x00FF0000;
+ data = (data << 24) | (data >> 8);
+ return data ^ (result >> 8);
+}
+
+static uword64
+swap_long(data)
+ uword64 data;
+{
+ unsigned int tmphi = WORD64HI(data);
+ unsigned int tmplo = WORD64LO(data);
+ tmphi = swap_word(tmphi);
+ tmplo = swap_word(tmplo);
+ /* Now swap the HI and LO parts */
+ return SET64LO(tmphi) | SET64HI(tmplo);
+}
+
+/*---------------------------------------------------------------------------*/
/*-- simulator engine -------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
@@ -1762,6 +1869,35 @@ ColdReset()
}
#endif /* HASFPU */
+ /* In reality this check should be performed at various points
+ within the simulation, since it is possible to change the
+ endianness of user programs. However, we perform the check here
+ to ensure that the start-of-day values agree: */
+ state |= (BigEndianCPU ? simBE : 0);
+ if ((target_byte_order == 1234) != !(state & simBE)) {
+ fprintf(stderr,"ColdReset: GDB (%s) and simulator (%s) do not agree on target endianness\n",
+ target_byte_order == 1234 ? "little" : "big",
+ state & simBE ? "big" : "little");
+ exit(1);
+ }
+
+ if ((state & simHOSTBE) == (state & simBE)) {
+ host_read_word = xfer_direct_word;
+ host_read_long = xfer_direct_long;
+ host_swap_word = swap_direct_word;
+ host_swap_long = swap_direct_long;
+ } else if (state & simHOSTBE) {
+ host_read_word = xfer_little_word;
+ host_read_long = xfer_little_long;
+ host_swap_word = swap_word;
+ host_swap_long = swap_long;
+ } else { /* HOST little-endian */
+ host_read_word = xfer_big_word;
+ host_read_long = xfer_big_long;
+ host_swap_word = swap_word;
+ host_swap_long = swap_long;
+ }
+
return;
}
@@ -3441,9 +3577,6 @@ simulate ()
callback->printf_filtered(callback,"DBG: fetched 0x%08X from PC = 0x%08X%08X\n",instruction,WORD64HI(PC),WORD64LO(PC));
#endif /* DEBUG */
-/*DBG*/ if (instruction == 0x46200005) /* ABS.D */
-/*DBG*/ callback->printf_filtered(callback,"DBG: ABS.D (0x%08X) instruction\n",instruction);
-
#if !defined(FASTSIM) || defined(PROFILE)
instruction_fetches++;
/* Since we increment above, the value should only ever be zero if