aboutsummaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1996-12-16 20:01:15 +0000
committerIan Lance Taylor <ian@airs.com>1996-12-16 20:01:15 +0000
commitaaff84371eac84395861cac662a5d16eebcb07b9 (patch)
tree59c6708db779470eab0c2e1da6848bb9b36bef03 /sim
parente85f2fbd1522788287510c836cc8e95293cf5188 (diff)
downloadgdb-aaff84371eac84395861cac662a5d16eebcb07b9.zip
gdb-aaff84371eac84395861cac662a5d16eebcb07b9.tar.gz
gdb-aaff84371eac84395861cac662a5d16eebcb07b9.tar.bz2
* gencode.c (build_mips16_operands): Fix base PC value for PC
relative operands. (build_instruction): Call JALDELAYSLOT rather than DELAYSLOT for a jal instruction. * interp.c (simJALDELAYSLOT): Define. (JALDELAYSLOT): Define. (INDELAYSLOT, INJALDELAYSLOT): Define. (simulate): Clear simJALDELAYSLOT when simDELAYSLOT is cleared.
Diffstat (limited to 'sim')
-rw-r--r--sim/mips/ChangeLog30
-rw-r--r--sim/mips/gencode.c9
-rw-r--r--sim/mips/interp.c175
3 files changed, 95 insertions, 119 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog
index fbccabb..5abef5b 100644
--- a/sim/mips/ChangeLog
+++ b/sim/mips/ChangeLog
@@ -1,3 +1,33 @@
+Mon Dec 16 14:59:38 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gencode.c (build_mips16_operands): Fix base PC value for PC
+ relative operands.
+ (build_instruction): Call JALDELAYSLOT rather than DELAYSLOT for a
+ jal instruction.
+ * interp.c (simJALDELAYSLOT): Define.
+ (JALDELAYSLOT): Define.
+ (INDELAYSLOT, INJALDELAYSLOT): Define.
+ (simulate): Clear simJALDELAYSLOT when simDELAYSLOT is cleared.
+
+Wed Dec 11 13:53:51 1996 Jim Wilson <wilson@cygnus.com>
+
+ * gencode.c (build_instruction): Use !ByteSwapMem instead of
+ BigEndianMem.
+ * interp.c (CONFIG, config_EP_{mask,shift,D,DxxDxx, config_BE): Delete.
+ (BigEndianMem): Rename to ByteSwapMem and change sense.
+ (BigEndianCPU, sim_write, LoadMemory, StoreMemory): Change
+ BigEndianMem references to !ByteSwapMem.
+ (set_endianness): New function, with prototype.
+ (sim_open): Call set_endianness.
+ (sim_info): Use simBE instead of BigEndianMem.
+ (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): Delete unnecessary MSC_VER
+ ifdefs, keeping the prototype declaration.
+ (swap_word): Rewrite correctly.
+ (ColdReset): Delete references to CONFIG. Delete endianness related
+ code; moved to set_endianness.
+
Tue Dec 10 11:32:04 1996 Jim Wilson <wilson@cygnus.com>
* gencode.c (build_instruction, case JUMP): Truncate PC to 32 bits.
diff --git a/sim/mips/gencode.c b/sim/mips/gencode.c
index 4df7c58..c8adaa2 100644
--- a/sim/mips/gencode.c
+++ b/sim/mips/gencode.c
@@ -954,10 +954,10 @@ build_mips16_operands (bitmap)
{
int j;
- printf ("PC & ~ (uword64) 1");
+ printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : IPC) & ~ (uword64) 1)");
for (j = 0; j < opindex; j++)
if (ops[j]->shift != 0)
- printf (" & 0x%x", ~ ((1 << op->shift) - 1));
+ printf (" & ~ (uword64) 0x%x", (1 << ops[j]->shift) - 1);
}
else if ((op->flags & MIPS16_ZERO) != 0)
printf ("0");
@@ -1867,7 +1867,10 @@ build_instruction (doisa, features, mips16, insn)
printf(" op1 = WORD64LO(op1);\n");
printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
printf(" DSPC = op1;\n");
- printf(" DELAYSLOT();\n");
+ if (insn->flags & LINK)
+ printf(" JALDELAYSLOT();\n");
+ else
+ printf(" DELAYSLOT();\n");
break ;
case BRANCH: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
diff --git a/sim/mips/interp.c b/sim/mips/interp.c
index d243d31..c344f0c 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -231,9 +231,6 @@ static ut_reg EPC = 0; /* Exception PC */
static FP_formats fpr_state[32];
#endif /* HASFPU */
-/* VR4300 CP0 configuration register: */
-static unsigned int CONFIG = 0;
-
/* The following are internal simulator state variables: */
static ut_reg IPC = 0; /* internal Instruction PC */
static ut_reg DSPC = 0; /* delay-slot PC */
@@ -257,13 +254,6 @@ static ut_reg DSPC = 0; /* delay-slot PC */
#define status_ERL (1 << 2) /* Error level */
#define status_RP (1 << 27) /* Reduced Power mode */
-#define config_EP_mask (0xF)
-#define config_EP_shift (27)
-#define config_EP_D (0x0)
-#define config_EP_DxxDxx (0x6)
-
-#define config_BE (1 << 15)
-
#define cause_BD ((unsigned)1 << 31) /* Exception in branch delay slot */
#if defined(HASFPU)
@@ -331,6 +321,7 @@ static ut_reg pending_slot_value[PSLOTS];
static void dotrace PARAMS((FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...));
static void sim_warning PARAMS((char *fmt,...));
extern void sim_error PARAMS((char *fmt,...));
+static void set_endianness PARAMS((void));
static void ColdReset PARAMS((void));
static int AddressTranslation PARAMS((uword64 vAddr,int IorD,int LorS,uword64 *pAddr,int *CCA,int host,int raw));
static void StoreMemory PARAMS((int CCA,int AccessLength,uword64 MemElem,uword64 pAddr,uword64 vAddr,int raw));
@@ -399,14 +390,9 @@ static ut_reg HLPC = 0;
/* UserMode */
#define UserMode ((((SR & status_KSU_mask) >> status_KSU_shift) == ksu_user) ? 1 : 0)
-/* BigEndianMem */
-/* Hardware configuration. Affects endianness of LoadMemory and
- StoreMemory and the endianness of Kernel and Supervisor mode
- execution. The value is 0 for little-endian; 1 for big-endian. */
-#define BigEndianMem ((CONFIG & config_BE) ? 1 : 0)
-/* NOTE: Problems will occur if the simulator memory model does not
- match the host program expectation. i.e. if the host is writing
- big-endian values to a little-endian memory model. */
+/* ByteSwapMem */
+/* This is true if the host and target have different endianness. */
+#define ByteSwapMem (!(state & simHOSTBE) != !(state & simBE))
/* ReverseEndian */
/* This mode is selected if in User mode with the RE bit being set in
@@ -418,8 +404,8 @@ static ut_reg HLPC = 0;
/* The endianness for load and store instructions (0=little;1=big). In
User mode this endianness may be switched by setting the state_RE
bit in the SR register. Thus, BigEndianCPU may be computed as
- (BigEndienMem EOR ReverseEndian). */
-#define BigEndianCPU (BigEndianMem ^ ReverseEndian) /* Already bits */
+ (!ByteSwapMem EOR ReverseEndian). */
+#define BigEndianCPU (!ByteSwapMem ^ ReverseEndian) /* Already bits */
#if !defined(FASTSIM) || defined(PROFILE)
/* At the moment these values will be the same, since we do not have
@@ -449,6 +435,7 @@ static 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 */
#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 rcexit = 0; /* _exit() reason code holder */
@@ -459,11 +446,19 @@ static unsigned int rcexit = 0; /* _exit() reason code holder */
state |= simDELAYSLOT;\
}
+#define JALDELAYSLOT() {\
+ DELAYSLOT ();\
+ state |= simJALDELAYSLOT;\
+ }
+
#define NULLIFY() {\
state &= ~simDELAYSLOT;\
state |= simSKIPNEXT;\
}
+#define INDELAYSLOT() ((state & simDELAYSLOT) != 0)
+#define INJALDELAYSLOT() ((state & simJALDELAYSLOT) != 0)
+
#define K0BASE (0x80000000)
#define K0SIZE (0x20000000)
#define K1BASE (0xA0000000)
@@ -544,6 +539,8 @@ sim_open (args)
state |= simHOSTBE; /* big-endian host */
}
+ set_endianness ();
+
#if defined(HASFPU)
/* Check that the host FPU conforms to IEEE 754-1985 for the SINGLE
and DOUBLE binary formats. This is a bit nasty, requiring that we
@@ -1057,7 +1054,7 @@ sim_write (addr,buffer,size)
/* We need to perform the following magic to ensure that that
bytes are written into same byte positions in the target memory
world, regardless of the endianness of the host. */
- if (BigEndianMem) {
+ if (!ByteSwapMem) {
value = ((uword64)(*buffer++) << 8);
value |= ((uword64)(*buffer++) << 0);
} else {
@@ -1074,7 +1071,7 @@ sim_write (addr,buffer,size)
int cca;
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
uword64 value;
- if (BigEndianMem) {
+ if (!ByteSwapMem) {
value = ((uword64)(*buffer++) << 24);
value |= ((uword64)(*buffer++) << 16);
value |= ((uword64)(*buffer++) << 8);
@@ -1095,7 +1092,7 @@ sim_write (addr,buffer,size)
int cca;
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW)) {
uword64 value;
- if (BigEndianMem) {
+ if (!ByteSwapMem) {
value = ((uword64)(*buffer++) << 56);
value |= ((uword64)(*buffer++) << 48);
value |= ((uword64)(*buffer++) << 40);
@@ -1278,7 +1275,7 @@ sim_info (verbose)
callback->printf_filtered(callback,"MIPS %d-bit simulator\n",(PROCESSOR_64BIT ? 64 : 32));
- callback->printf_filtered(callback,"%s endian memory model\n",(BigEndianMem ? "Big" : "Little"));
+ callback->printf_filtered(callback,"%s endian memory model\n",(state & simBE ? "Big" : "Little"));
callback->printf_filtered(callback,"0x%08X bytes of memory at 0x%08X%08X\n",(unsigned int)membank_size,WORD64HI(membank_base),WORD64LO(membank_base));
@@ -1962,67 +1959,37 @@ void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...
simulation, at the cost of increasing the image and source size. */
static unsigned int
-#ifdef _MSC_VER
xfer_direct_word(unsigned char *memory)
-#else
-xfer_direct_word(memory)
- unsigned char *memory;
-#endif
{
return *((unsigned int *)memory);
}
static uword64
-#ifdef _MSC_VER
xfer_direct_long(unsigned char *memory)
-#else
-xfer_direct_long(memory)
- unsigned char *memory;
-#endif
{
return *((uword64 *)memory);
}
static unsigned int
-#ifdef _MSC_VER
swap_direct_word(unsigned int data)
-#else
-swap_direct_word(data)
- unsigned int data;
-#endif
{
return data;
}
static uword64
-#ifdef _MSC_VER
swap_direct_long(uword64 data)
-#else
-swap_direct_long(data)
- uword64 data;
-#endif
{
return data;
}
static unsigned int
-#ifdef _MSC_VER
xfer_big_word(unsigned char *memory)
-#else
-xfer_big_word(memory)
- unsigned char *memory;
-#endif
{
return ((memory[0] << 24) | (memory[1] << 16) | (memory[2] << 8) | memory[3]);
}
static uword64
-#ifdef _MSC_VER
xfer_big_long(unsigned char *memory)
-#else
-xfer_big_long(memory)
- unsigned char *memory;
-#endif
{
return (((uword64)memory[0] << 56) | ((uword64)memory[1] << 48)
| ((uword64)memory[2] << 40) | ((uword64)memory[3] << 32)
@@ -2031,23 +1998,13 @@ xfer_big_long(memory)
}
static unsigned int
-#ifdef _MSC_VER
xfer_little_word(unsigned char *memory)
-#else
-xfer_little_word(memory)
- unsigned char *memory;
-#endif
{
return ((memory[3] << 24) | (memory[2] << 16) | (memory[1] << 8) | memory[0]);
}
static uword64
-#ifdef _MSC_VER
xfer_little_long(unsigned char *memory)
-#else
-xfer_little_long(memory)
- unsigned char *memory;
-#endif
{
return (((uword64)memory[7] << 56) | ((uword64)memory[6] << 48)
| ((uword64)memory[5] << 40) | ((uword64)memory[4] << 32)
@@ -2056,27 +2013,16 @@ xfer_little_long(memory)
}
static unsigned int
-#ifdef _MSC_VER
swap_word(unsigned int data)
-#else
-swap_word(data)
- unsigned int data;
-#endif
{
unsigned int result;
- result = data ^ ((data << 16) | (data >> 16));
- result &= ~0x00FF0000;
- data = (data << 24) | (data >> 8);
- return data ^ (result >> 8);
+ result = (((data & 0xff) << 24) | ((data & 0xff00) << 8)
+ | ((data >> 8) & 0xff00) | ((data >> 24) & 0xff));
+ return result;
}
static uword64
-#ifdef _MSC_VER
swap_long(uword64 data)
-#else
-swap_long(data)
- uword64 data;
-#endif
{
unsigned int tmphi = WORD64HI(data);
unsigned int tmplo = WORD64LO(data);
@@ -2091,6 +2037,36 @@ swap_long(data)
/*---------------------------------------------------------------------------*/
static void
+set_endianness ()
+{
+ /* 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. */
+ if (target_byte_order == 4321)
+ state |= simBE;
+
+ /* ??? This is a lot more code than is necessary to solve the problem.
+ It would be simpler to handle this like the SH simulator. */
+ if (!ByteSwapMem) {
+ 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;
+ }
+}
+
+static void
ColdReset()
{
/* RESET: Fixed PC address: */
@@ -2099,10 +2075,6 @@ ColdReset()
SR &= ~(status_SR | status_TS | status_RP);
SR |= (status_ERL | status_BEV);
- /* VR4300 starts in Big-Endian mode */
- CONFIG &= ~(config_EP_mask << config_EP_shift);
- CONFIG |= ((config_EP_D << config_EP_shift) | config_BE);
- /* TODO: The VR4300 CONFIG register is not modelled fully at the moment */
#if defined(HASFPU) && (GPRLEN == (64))
/* Cheat and allow access to the complete register set immediately: */
@@ -2127,35 +2099,6 @@ 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;
}
@@ -2353,7 +2296,7 @@ LoadMemory(CCA,AccessLength,pAddr,vAddr,IorD,raw)
extracts the required bytes. However, to keep performance
high we only load the required bytes into the relevant
slots. */
- if (BigEndianMem)
+ if (!ByteSwapMem)
switch (AccessLength) { /* big-endian memory */
case AccessLength_DOUBLEWORD :
value |= ((uword64)mem[index++] << 56);
@@ -2405,7 +2348,7 @@ LoadMemory(CCA,AccessLength,pAddr,vAddr,IorD,raw)
StoreMemory routines to avoid shifting the data before
returning or using it. */
if (!raw) { /* do nothing for raw accessess */
- if (BigEndianMem)
+ if (!ByteSwapMem)
value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
else /* little-endian only needs to be shifted up to the correct byte offset */
value <<= ((pAddr & LOADDRMASK) * 8);
@@ -2483,7 +2426,7 @@ StoreMemory(CCA,AccessLength,MemElem,pAddr,vAddr,raw)
printf("DBG: StoreMemory: offset = %d MemElem = 0x%08X%08X\n",(unsigned int)(pAddr & LOADDRMASK),WORD64HI(MemElem),WORD64LO(MemElem));
#endif /* DEBUG */
- if (BigEndianMem) {
+ if (!ByteSwapMem) {
if (raw)
shift = ((7 - AccessLength) * 8);
else /* real memory access */
@@ -2499,7 +2442,7 @@ StoreMemory(CCA,AccessLength,MemElem,pAddr,vAddr,raw)
printf("DBG: StoreMemory: shift = %d MemElem = 0x%08X%08X\n",shift,WORD64HI(MemElem),WORD64LO(MemElem));
#endif /* DEBUG */
- if (BigEndianMem) {
+ if (!ByteSwapMem) {
switch (AccessLength) { /* big-endian memory */
case AccessLength_DOUBLEWORD :
mem[index++] = (unsigned char)(MemElem >> 56);
@@ -4040,7 +3983,7 @@ simulate ()
printf("DBG: dsstate set before instruction execution - updating PC to 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
#endif /* DEBUG */
PC = DSPC;
- state &= ~simDELAYSLOT;
+ state &= ~(simDELAYSLOT | simJALDELAYSLOT);
}
if (MIPSISA < 4) { /* The following is only required on pre MIPS IV processors: */