For NEC 4100/4300 project
* gencode.c (build_instruction, case JUMP): Truncate PC to 32 bits. * interp.c (CHECKHILO): Define away. (simSIGINT): New macro. (membank_size): Increase from 1MB to 2MB. (control_c): New function. (sim_resume): Rename parameter signal to signal_number. Add local variable prev. Call signal before and after simulate. (sim_stop_reason): Add simSIGINT support. (sim_warning, sim_error, dotrace, SignalException): Define as stdarg functions always. (sim_warning): Delete call to SignalException. Do call printf_filtered if logfh is NULL. (AddressTranslation): Add #ifdef DEBUG around debugging message and a call to sim_warning.
This commit is contained in:
parent
42aa243574
commit
6429b29698
|
@ -1,3 +1,25 @@
|
|||
Tue Dec 10 11:32:04 1996 Jim Wilson <wilson@cygnus.com>
|
||||
|
||||
* gencode.c (build_instruction, case JUMP): Truncate PC to 32 bits.
|
||||
* interp.c (CHECKHILO): Define away.
|
||||
(simSIGINT): New macro.
|
||||
(membank_size): Increase from 1MB to 2MB.
|
||||
(control_c): New function.
|
||||
(sim_resume): Rename parameter signal to signal_number. Add local
|
||||
variable prev. Call signal before and after simulate.
|
||||
(sim_stop_reason): Add simSIGINT support.
|
||||
(sim_warning, sim_error, dotrace, SignalException): Define as stdarg
|
||||
functions always.
|
||||
(sim_warning): Delete call to SignalException. Do call printf_filtered
|
||||
if logfh is NULL.
|
||||
(AddressTranslation): Add #ifdef DEBUG around debugging message and
|
||||
a call to sim_warning.
|
||||
|
||||
Wed Nov 27 11:53:50 1996 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* gencode.c (process_instructions): If ! proc64, skip DOUBLEWORD
|
||||
16 bit instructions.
|
||||
|
||||
Tue Nov 26 11:53:12 1996 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
Add support for mips16 (16 bit MIPS implementation):
|
||||
|
|
|
@ -1862,6 +1862,9 @@ build_instruction (doisa, features, mips16, insn)
|
|||
if (insn->flags & NOT)
|
||||
printf(" op1 ^= 1;\n");
|
||||
|
||||
printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
|
||||
printf(" so we just truncate it to 32 bits here. */\n");
|
||||
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");
|
||||
|
|
|
@ -375,7 +375,12 @@ static int LOACCESS = 0;
|
|||
following operation are spotted. */
|
||||
static ut_reg HLPC = 0;
|
||||
|
||||
/* TODO: The 4300 has interlocks so we should not need to warn of the possible over-write (CHECK THIS) */
|
||||
/* ??? 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
|
||||
/* 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
|
||||
|
@ -384,6 +389,7 @@ static ut_reg HLPC = 0;
|
|||
if ((HIACCESS != 0) || (LOACCESS != 0))\
|
||||
sim_warning("%s over-writing HI and LO registers values (PC = 0x%08X%08X HLPC = 0x%08X%08X)\n",(s),(unsigned int)(PC>>32),(unsigned int)(PC&0xFFFFFFFF),(unsigned int)(HLPC>>32),(unsigned int)(HLPC&0xFFFFFFFF));\
|
||||
}
|
||||
#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
|
||||
|
@ -442,6 +448,7 @@ static unsigned int pipeline_ticks = 0;
|
|||
#define simSKIPNEXT (1 << 25) /* 0 = do nothing; 1 = skip instruction */
|
||||
#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 */
|
||||
|
||||
static unsigned int state = 0;
|
||||
static unsigned int rcexit = 0; /* _exit() reason code holder */
|
||||
|
@ -465,7 +472,11 @@ static unsigned int rcexit = 0; /* _exit() reason code holder */
|
|||
/* Very simple memory model to start with: */
|
||||
static unsigned char *membank = NULL;
|
||||
static ut_reg membank_base = K1BASE;
|
||||
static unsigned membank_size = (1 << 20); /* (16 << 20); */ /* power-of-2 */
|
||||
/* The ddb.ld linker script loads text at K1BASE+1MB, and the idt.ld linker
|
||||
script loads text at K1BASE+128KB. We allocate 2MB, so that we have a
|
||||
minimum of 1 MB available for the user process. We must have memory
|
||||
above _end in order for sbrk to work. */
|
||||
static unsigned membank_size = (2 << 20);
|
||||
|
||||
/* Simple run-time monitor support */
|
||||
static unsigned char *monitor = NULL;
|
||||
|
@ -478,6 +489,7 @@ static FILE *logfh = NULL;
|
|||
#if defined(TRACE)
|
||||
static char *tracefile = "trace.din"; /* default filename for trace log */
|
||||
static FILE *tracefh = NULL;
|
||||
static void open_trace PARAMS((void));
|
||||
#endif /* TRACE */
|
||||
|
||||
#if defined(PROFILE)
|
||||
|
@ -818,18 +830,26 @@ Re-compile simulator with \"-DPROFILE\" to enable this option.\n");
|
|||
}
|
||||
|
||||
#if defined(TRACE)
|
||||
if (state & simTRACE) {
|
||||
if (state & simTRACE)
|
||||
open_trace();
|
||||
#endif /* TRACE */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(TRACE)
|
||||
static void
|
||||
open_trace()
|
||||
{
|
||||
tracefh = fopen(tracefile,"wb+");
|
||||
if (tracefh == NULL) {
|
||||
if (tracefh == NULL)
|
||||
{
|
||||
sim_warning("Failed to create file \"%s\", writing trace information to stderr.",tracefile);
|
||||
tracefh = stderr;
|
||||
}
|
||||
}
|
||||
#endif /* TRACE */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* For the profile writing, we write the data in the host
|
||||
endianness. This unfortunately means we are assuming that the
|
||||
profile file we create is processed on the same host executing the
|
||||
|
@ -954,11 +974,23 @@ sim_close (quitting)
|
|||
}
|
||||
|
||||
void
|
||||
sim_resume (step,signal)
|
||||
int step, signal;
|
||||
control_c (sig, code, scp, addr)
|
||||
int sig;
|
||||
int code;
|
||||
char *scp;
|
||||
char *addr;
|
||||
{
|
||||
state |= (simSTOP | simSIGINT);
|
||||
}
|
||||
|
||||
void
|
||||
sim_resume (step,signal_number)
|
||||
int step, signal_number;
|
||||
{
|
||||
void (*prev) ();
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("DBG: sim_resume entered: step = %d, signal = %d (membank = 0x%08X)\n",step,signal,membank);
|
||||
printf("DBG: sim_resume entered: step = %d, signal = %d (membank = 0x%08X)\n",step,signal_number,membank);
|
||||
#endif /* DEBUG */
|
||||
|
||||
if (step)
|
||||
|
@ -971,7 +1003,12 @@ sim_resume (step,signal)
|
|||
/* Start executing instructions from the current state (set
|
||||
explicitly by register updates, or by sim_create_inferior): */
|
||||
|
||||
prev = signal (SIGINT, control_c);
|
||||
|
||||
simulate();
|
||||
|
||||
signal (SIGINT, prev);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1222,11 +1259,14 @@ sim_stop_reason (reason,sigrc)
|
|||
#endif
|
||||
*reason = sim_exited;
|
||||
*sigrc = rcexit;
|
||||
} else if (state & simSIGINT) {
|
||||
*reason = sim_stopped;
|
||||
*sigrc = SIGINT;
|
||||
} else { /* assume single-stepping */
|
||||
*reason = sim_stopped;
|
||||
*sigrc = SIGTRAP;
|
||||
}
|
||||
state &= ~(simEXCEPTION | simEXIT);
|
||||
state &= ~(simEXCEPTION | simEXIT | simSIGINT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1516,8 +1556,11 @@ sim_trace()
|
|||
|
||||
#if defined(TRACE)
|
||||
/* Ensure tracing is enabled, if available */
|
||||
if (tracefh != NULL)
|
||||
if (tracefh == NULL)
|
||||
{
|
||||
open_trace();
|
||||
state |= simTRACE;
|
||||
}
|
||||
#endif /* TRACE */
|
||||
|
||||
state &= ~(simSTOP | simSTEP); /* execute until event */
|
||||
|
@ -1766,44 +1809,37 @@ sim_monitor(reason)
|
|||
}
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
sim_warning(char *fmt,...)
|
||||
#else
|
||||
sim_warning(fmt)
|
||||
char *fmt;
|
||||
#endif
|
||||
{
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
|
||||
va_start (ap,fmt);
|
||||
if (logfh != NULL) {
|
||||
#if 1
|
||||
fprintf(logfh,"SIM Warning: ");
|
||||
fprintf(logfh,fmt,ap);
|
||||
fprintf(logfh,"\n");
|
||||
#else /* we should provide a method of routing log messages to the simulator output stream */
|
||||
callback->printf_filtered(callback,"SIM Warning: ");
|
||||
callback->printf_filtered(callback,fmt,ap);
|
||||
#endif
|
||||
}
|
||||
vsprintf (buf, fmt, ap);
|
||||
va_end (ap);
|
||||
SignalException(SimulatorFault,"");
|
||||
|
||||
if (logfh != NULL) {
|
||||
fprintf(logfh,"SIM Warning: %s\n", buf);
|
||||
} else {
|
||||
callback->printf_filtered(callback,"SIM Warning: %s\n", buf);
|
||||
}
|
||||
/* This used to call SignalException with a SimulatorFault, but that causes
|
||||
the simulator to exit, and that is inappropriate for a warning. */
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
sim_error(char *fmt,...)
|
||||
#else
|
||||
sim_error(fmt)
|
||||
char *fmt;
|
||||
#endif
|
||||
{
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
|
||||
va_start (ap,fmt);
|
||||
callback->printf_filtered(callback,"SIM Error: ");
|
||||
callback->printf_filtered(callback,fmt,ap);
|
||||
vsprintf (buf, fmt, ap);
|
||||
va_end (ap);
|
||||
SignalException(SimulatorFault,"");
|
||||
|
||||
callback->printf_filtered(callback,"SIM Error: %s", buf);
|
||||
SignalException (SimulatorFault, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1888,23 +1924,16 @@ getnum(value)
|
|||
|
||||
|
||||
static
|
||||
#ifdef _MSC_VER
|
||||
void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...)
|
||||
#else
|
||||
void dotrace(tracefh,type,address,width,comment)
|
||||
FILE *tracefh;
|
||||
int type;
|
||||
SIM_ADDR address;
|
||||
int width;
|
||||
char *comment;
|
||||
#endif
|
||||
{
|
||||
if (state & simTRACE) {
|
||||
va_list ap;
|
||||
fprintf(tracefh,"%d %08x%08x ; width %d ; ",
|
||||
type,(unsigned long)(address>>32),(unsigned long)(address&0xffffffff),width);
|
||||
type,
|
||||
sizeof (address) > 4 ? (unsigned long)(address>>32) : 0,
|
||||
(unsigned long)(address&0xffffffff),width);
|
||||
va_start(ap,comment);
|
||||
fprintf(tracefh,comment,ap);
|
||||
vfprintf(tracefh,comment,ap);
|
||||
va_end(ap);
|
||||
fprintf(tracefh,"\n");
|
||||
}
|
||||
|
@ -2195,15 +2224,21 @@ AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw)
|
|||
if (host)
|
||||
*pAddr = (int)&monitor[((unsigned int)(vAddr - monitor_base) & (monitor_size - 1))];
|
||||
} else {
|
||||
#if 1 /* def DEBUG */
|
||||
#ifdef DEBUG
|
||||
sim_warning("Failed: AddressTranslation(0x%08X%08X,%s,%s,...) IPC = 0x%08X%08X",WORD64HI(vAddr),WORD64LO(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "isSTORE" : "isLOAD"),WORD64HI(IPC),WORD64LO(IPC));
|
||||
#endif /* DEBUG */
|
||||
res = 0; /* AddressTranslation has failed */
|
||||
*pAddr = (SIM_ADDR)-1;
|
||||
if (!raw) /* only generate exceptions on real memory transfers */
|
||||
SignalException((LorS == isSTORE) ? AddressStore : AddressLoad);
|
||||
#ifdef DEBUG
|
||||
else
|
||||
/* This is a normal occurance during gdb operation, for instance trying
|
||||
to print parameters at function start before they have been setup,
|
||||
and hence we should not print a warning except when debugging the
|
||||
simulator. */
|
||||
sim_warning("AddressTranslation for %s %s from 0x%08X%08X failed",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),WORD64HI(vAddr),WORD64LO(vAddr));
|
||||
#endif
|
||||
}
|
||||
|
||||
return(res);
|
||||
|
@ -2280,7 +2315,9 @@ LoadMemory(CCA,AccessLength,pAddr,vAddr,IorD,raw)
|
|||
|
||||
/* If instruction fetch then we need to check that the two lo-order
|
||||
bits are zero, otherwise raise a InstructionFetch exception: */
|
||||
if ((IorD == isINSTRUCTION) && ((pAddr & 0x3) != 0))
|
||||
if ((IorD == isINSTRUCTION)
|
||||
&& ((pAddr & 0x3) != 0)
|
||||
&& (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
|
||||
SignalException(InstructionFetch);
|
||||
else {
|
||||
unsigned int index;
|
||||
|
@ -2537,12 +2574,7 @@ SyncOperation(stype)
|
|||
that aborts the instruction. The instruction operation pseudocode
|
||||
will never see a return from this function call. */
|
||||
static void
|
||||
#ifdef _MSC_VER
|
||||
SignalException (int exception,...)
|
||||
#else
|
||||
SignalException(exception)
|
||||
int exception;
|
||||
#endif
|
||||
{
|
||||
/* Ensure that any active atomic read/modify/write operation will fail: */
|
||||
LLBIT = 0;
|
||||
|
@ -3857,7 +3889,9 @@ simulate ()
|
|||
callback->printf_filtered(callback,"DBG: DSPC = 0x%08X%08X\n",WORD64HI(DSPC),WORD64LO(DSPC));
|
||||
#endif /* DEBUG */
|
||||
|
||||
if (AddressTranslation(PC,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) { /* Copy the action of the LW instruction */
|
||||
if (AddressTranslation(PC,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) {
|
||||
if ((vaddr & 1) == 0) {
|
||||
/* Copy the action of the LW instruction */
|
||||
unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
|
||||
unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
|
||||
uword64 value;
|
||||
|
@ -3866,6 +3900,20 @@ simulate ()
|
|||
value = LoadMemory(cca,AccessLength_WORD,paddr,vaddr,isINSTRUCTION,isREAL);
|
||||
byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
|
||||
instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
|
||||
} else {
|
||||
/* Copy the action of the LH instruction */
|
||||
unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 1) : 0);
|
||||
unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 1) : 0);
|
||||
uword64 value;
|
||||
unsigned int byte;
|
||||
paddr = (((paddr & ~ (uword64) 1) & ~LOADDRMASK)
|
||||
| (((paddr & ~ (uword64) 1) & LOADDRMASK) ^ (reverse << 1)));
|
||||
value = LoadMemory(cca, AccessLength_HALFWORD,
|
||||
paddr & ~ (uword64) 1,
|
||||
vaddr, isINSTRUCTION, isREAL);
|
||||
byte = (((vaddr &~ (uword64) 1) & LOADDRMASK) ^ (bigend << 1));
|
||||
instruction = ((value >> (8 * byte)) & 0xFFFF);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,"Cannot translate address for PC = 0x%08X%08X failed\n",WORD64HI(PC),WORD64LO(PC));
|
||||
exit(1);
|
||||
|
@ -3897,7 +3945,10 @@ simulate ()
|
|||
/* This is required by exception processing, to ensure that we can
|
||||
cope with exceptions in the delay slots of branches that may
|
||||
already have changed the PC. */
|
||||
if ((vaddr & 1) == 0)
|
||||
PC += 4; /* increment ready for the next fetch */
|
||||
else
|
||||
PC += 2;
|
||||
/* NOTE: If we perform a delay slot change to the PC, this
|
||||
increment is not requuired. However, it would make the
|
||||
simulator more complicated to try and avoid this small hit. */
|
||||
|
|
Loading…
Reference in New Issue