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 */
#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)
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));
/* 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
/* 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
#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 */
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)
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
/* 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 {
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);
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);
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));
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)
}
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)
}
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);
/*-- simulator engine -------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
+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()
{
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: */
}
#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;
}
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);
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);
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 */
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);
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: */