* 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.
This commit is contained in:
Ian Lance Taylor
1996-12-16 20:01:15 +00:00
parent e85f2fbd15
commit aaff84371e
3 changed files with 95 additions and 119 deletions

View File

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

View File

@ -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,6 +1867,9 @@ 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");
if (insn->flags & LINK)
printf(" JALDELAYSLOT();\n");
else
printf(" DELAYSLOT();\n");
break ;

View File

@ -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);
@ -2090,6 +2036,36 @@ swap_long(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()
{
@ -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: */