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.
This commit is contained in:
parent
69159fad82
commit
a9f7253f64
@ -399,7 +399,7 @@ typedef struct instruction {
|
||||
|
||||
struct instruction MIPS_DECODE[] = {
|
||||
/* The instructions are alphabetical, and not in instruction bit-order: */
|
||||
{"ABS", 1,"01000110mmm00000dddddaaaaa000101",COP1, FPABS, (FP)},
|
||||
{"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1, FPABS, (FP)},
|
||||
{"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL,ADD, (WORD | WORD32 | OVERFLOW)}, /* rd = rs + rt */
|
||||
{"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1, FPADD, (FP)},
|
||||
{"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32 | OVERFLOW)},
|
||||
@ -835,7 +835,7 @@ process_instructions(doarch,features)
|
||||
printf("switch (num)\n") ;
|
||||
printf("{\n");
|
||||
|
||||
for (loop = 1; (loop < limit); loop++) {
|
||||
for (loop = 0; (loop < limit); loop++) {
|
||||
/* First check that the ISA number we are constructing for is
|
||||
valid, before checking if the instruction matches any of the
|
||||
architecture specific flags. NOTE: We allow a selected ISA of
|
||||
|
@ -382,6 +382,7 @@ int LOACCESS = 0;
|
||||
access to the pipeline cycle count information from the simulator
|
||||
engine. */
|
||||
unsigned int instruction_fetches = 0;
|
||||
unsigned int instruction_fetch_overflow = 0;
|
||||
unsigned int pipeline_ticks = 0;
|
||||
#endif
|
||||
|
||||
@ -417,9 +418,14 @@ unsigned int rcexit = 0; /* _exit() reason code holder */
|
||||
state |= simSKIPNEXT;\
|
||||
}
|
||||
|
||||
#define K0BASE (0x80000000)
|
||||
#define K0SIZE (0x20000000)
|
||||
#define K1BASE (0xA0000000)
|
||||
#define K1SIZE (0x20000000)
|
||||
|
||||
/* Very simple memory model to start with: */
|
||||
unsigned char *membank = NULL;
|
||||
ut_reg membank_base = 0xA0000000;
|
||||
ut_reg membank_base = K1BASE;
|
||||
unsigned membank_size = (1 << 20); /* (16 << 20); */ /* power-of-2 */
|
||||
|
||||
/* Simple run-time monitor support */
|
||||
@ -490,12 +496,18 @@ sim_open (args)
|
||||
trust the explicit manifests held in the source: */
|
||||
{
|
||||
unsigned int s[2];
|
||||
s[0] = 0x40805A5A;
|
||||
s[1] = 0x00000000;
|
||||
if (((float)4.01102924346923828125 != *(float *)s) || ((double)523.2939453125 != *(double *)s)) {
|
||||
s[state & simHOSTBE ? 0 : 1] = 0x40805A5A;
|
||||
s[state & simHOSTBE ? 1 : 0] = 0x00000000;
|
||||
|
||||
/* TODO: We need to cope with the simulated target and the host
|
||||
not having the same endianness. This will require the high and
|
||||
low words of a (double) to be swapped when converting between
|
||||
the host and the simulated target. */
|
||||
|
||||
if (((float)4.01102924346923828125 != *(float *)(s + ((state & simHOSTBE) ? 0 : 1))) || ((double)523.2939453125 != *(double *)s)) {
|
||||
fprintf(stderr,"The host executing the simulator does not seem to have IEEE 754-1985 std FP\n");
|
||||
fprintf(stderr,"*(float *)s = %f (4.01102924346923828125)\n",*(float *)s);
|
||||
fprintf(stderr,"*(double *)s = %f (523.2939453125)\n",*(double *)s);
|
||||
fprintf(stderr,"*(float *)s = %.20f (4.01102924346923828125)\n",*(float *)s);
|
||||
fprintf(stderr,"*(double *)s = %.20f (523.2939453125)\n",*(double *)s);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -677,7 +689,6 @@ Re-compile simulator with \"-DPROFILE\" to enable this option.\n");
|
||||
fprintf(stderr,"Not enough VM for monitor simulation (%d bytes)\n",monitor_size);
|
||||
} else {
|
||||
int loop;
|
||||
/* TODO: Provide support for PMON monitor */
|
||||
/* Entry into the IDT monitor is via fixed address vectors, and
|
||||
not using machine instructions. To avoid clashing with use of
|
||||
the MIPS TRAP system, we place our own (simulator specific)
|
||||
@ -689,6 +700,50 @@ Re-compile simulator with \"-DPROFILE\" to enable this option.\n");
|
||||
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
|
||||
StoreMemory(cca,AccessLength_WORD,(RSVD_INSTRUCTION | ((loop >> 2) & RSVD_INSTRUCTION_AMASK)),paddr,vaddr,isRAW);
|
||||
}
|
||||
/* The PMON monitor uses the same address space, but rather than
|
||||
branching into it the address of a routine is loaded. We can
|
||||
cheat for the moment, and direct the PMON routine to IDT style
|
||||
instructions within the monitor space. This relies on the IDT
|
||||
monitor not using the locations from 0xBFC00500 onwards as its
|
||||
entry points.*/
|
||||
for (loop = 0; (loop < 24); loop++)
|
||||
{
|
||||
uword64 vaddr = (monitor_base + 0x500 + (loop * 4));
|
||||
uword64 paddr;
|
||||
int cca;
|
||||
unsigned int value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
|
||||
switch (loop)
|
||||
{
|
||||
case 0: /* read */
|
||||
value = 7;
|
||||
break;
|
||||
|
||||
case 1: /* write */
|
||||
value = 8;
|
||||
break;
|
||||
|
||||
case 2: /* open */
|
||||
value = 6;
|
||||
break;
|
||||
|
||||
case 3: /* close */
|
||||
value = 10;
|
||||
break;
|
||||
|
||||
case 5: /* printf */
|
||||
value = ((0x500 - 16) / 8); /* not an IDT reason code */
|
||||
break;
|
||||
|
||||
case 8: /* cliexit */
|
||||
value = 17;
|
||||
break;
|
||||
}
|
||||
value = (monitor_base + (value * 8));
|
||||
if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
|
||||
StoreMemory(cca,AccessLength_WORD,value,paddr,vaddr,isRAW);
|
||||
else
|
||||
callback->printf_filtered(callback,"Failed to write to monitor space 0x%08X%08X\n",WORD64HI(vaddr),WORD64LO(vaddr));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(TRACE)
|
||||
@ -1110,7 +1165,10 @@ sim_info (verbose)
|
||||
callback->printf_filtered(callback,"0x%08X bytes of memory at 0x%08X%08X\n",(unsigned int)membank_size,WORD64HI(membank_base),WORD64LO(membank_base));
|
||||
|
||||
#if !defined(FASTSIM)
|
||||
callback->printf_filtered(callback,"Instruction fetches = %d\n",instruction_fetches);
|
||||
if (instruction_fetch_overflow != 0)
|
||||
callback->printf_filtered(callback,"Instruction fetches = 0x%08X%08X\n",instruction_fetch_overflow,instruction_fetches);
|
||||
else
|
||||
callback->printf_filtered(callback,"Instruction fetches = %d\n",instruction_fetches);
|
||||
callback->printf_filtered(callback,"Pipeline ticks = %d\n",pipeline_ticks);
|
||||
/* It would be a useful feature, if when performing multi-cycle
|
||||
simulations (rather than single-stepping) we keep the start and
|
||||
@ -1394,7 +1452,7 @@ sim_trace()
|
||||
/*-- Private simulator support interface ------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Simple monitor interface (currently setup for the IDT monitor) */
|
||||
/* Simple monitor interface (currently setup for the IDT and PMON monitors) */
|
||||
static void
|
||||
sim_monitor(reason)
|
||||
unsigned int reason;
|
||||
@ -1513,6 +1571,22 @@ sim_monitor(reason)
|
||||
}
|
||||
break;
|
||||
|
||||
case 158 : /* PMON printf */
|
||||
/* in: A0 = pointer to format string */
|
||||
/* A1 = optional argument 1 */
|
||||
/* A2 = optional argument 2 */
|
||||
/* A3 = optional argument 3 */
|
||||
/* out: void */
|
||||
{
|
||||
uword64 paddr;
|
||||
int cca;
|
||||
if (AddressTranslation(A0,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
|
||||
callback->printf_filtered(callback,(char *)((int)paddr),(int)A1,(int)A2,(int)A2);
|
||||
else
|
||||
callback->printf_filtered(callback,"WARNING: Attempt to pass pointer that does not reference simulated memory\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
callback->printf_filtered(callback,"TODO: sim_monitor(%d) : PC = 0x%08X%08X\n",reason,WORD64HI(IPC),WORD64LO(IPC));
|
||||
callback->printf_filtered(callback,"(Arguments : A0 = 0x%08X%08X : A1 = 0x%08X%08X : A2 = 0x%08X%08X : A3 = 0x%08X%08X)\n",WORD64HI(A0),WORD64LO(A0),WORD64HI(A1),WORD64LO(A1),WORD64HI(A2),WORD64LO(A2),WORD64HI(A3),WORD64LO(A3));
|
||||
@ -1730,6 +1804,19 @@ AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw)
|
||||
/* For a simple (flat) memory model, we simply pass virtual
|
||||
addressess through (mostly) unchanged. */
|
||||
vAddr &= 0xFFFFFFFF;
|
||||
|
||||
/* Treat the kernel memory spaces identically for the moment: */
|
||||
if ((membank_base == K1BASE) && (vAddr >= K0BASE) && (vAddr < (K0BASE + K0SIZE)))
|
||||
vAddr += (K1BASE - K0BASE);
|
||||
|
||||
/* Also assume that the K1BASE memory wraps. This is required to
|
||||
allow the PMON run-time __sizemem() routine to function (without
|
||||
having to provide exception simulation). NOTE: A kludge to work
|
||||
around the fact that the monitor memory is currently held in the
|
||||
K1BASE space. */
|
||||
if (((vAddr < monitor_base) || (vAddr >= (monitor_base + monitor_size))) && (vAddr >= K1BASE && vAddr < (K1BASE + K1SIZE)))
|
||||
vAddr = (K1BASE | (vAddr & (membank_size - 1)));
|
||||
|
||||
*pAddr = vAddr; /* default for isTARGET */
|
||||
*CCA = Uncached; /* not used for isHOST */
|
||||
|
||||
@ -1744,7 +1831,7 @@ AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw)
|
||||
*pAddr = (int)&monitor[((unsigned int)(vAddr - monitor_base) & (monitor_size - 1))];
|
||||
} else {
|
||||
#if 1 /* def DEBUG */
|
||||
callback->printf_filtered(callback,"Failed: AddressTranslation(0x%08X%08X,%s,%s,...);\n",WORD64HI(vAddr),WORD64LO(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "isSTORE" : "isLOAD"));
|
||||
callback->printf_filtered(callback,"Failed: AddressTranslation(0x%08X%08X,%s,%s,...) IPC = 0x%08X%08X\n",WORD64HI(vAddr),WORD64LO(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "isSTORE" : "isLOAD"),WORD64HI(IPC),WORD64LO(IPC));
|
||||
#endif /* DEBUG */
|
||||
res = 0; /* AddressTranslation has failed */
|
||||
*pAddr = -1;
|
||||
@ -2189,10 +2276,15 @@ CacheOp(op,pAddr,vAddr,instruction)
|
||||
uword64 vAddr;
|
||||
unsigned int instruction;
|
||||
{
|
||||
static int icache_warning = 0;
|
||||
static int dcache_warning = 0;
|
||||
|
||||
/* If CP0 is not useable (User or Supervisor mode) and the CP0
|
||||
enable bit in the Status Register is clear - a coprocessor
|
||||
unusable exception is taken. */
|
||||
#if 0
|
||||
callback->printf_filtered(callback,"TODO: Cache availability checking (PC = 0x%08X%08X)\n",WORD64HI(IPC),WORD64LO(IPC));
|
||||
#endif
|
||||
|
||||
switch (op & 0x3) {
|
||||
case 0: /* instruction cache */
|
||||
@ -2203,7 +2295,11 @@ CacheOp(op,pAddr,vAddr,instruction)
|
||||
case 4: /* Hit Invalidate */
|
||||
case 5: /* Fill */
|
||||
case 6: /* Hit Writeback */
|
||||
callback->printf_filtered(callback,"SIM Warning: Instruction CACHE operation %d to be coded\n",(op >> 2));
|
||||
if (!icache_warning)
|
||||
{
|
||||
callback->printf_filtered(callback,"SIM Warning: Instruction CACHE operation %d to be coded\n",(op >> 2));
|
||||
icache_warning = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2221,7 +2317,11 @@ CacheOp(op,pAddr,vAddr,instruction)
|
||||
case 4: /* Hit Invalidate */
|
||||
case 5: /* Hit Writeback Invalidate */
|
||||
case 6: /* Hit Writeback */
|
||||
callback->printf_filtered(callback,"SIM Warning: Data CACHE operation %d to be coded\n",(op >> 2));
|
||||
if (!dcache_warning)
|
||||
{
|
||||
callback->printf_filtered(callback,"SIM Warning: Data CACHE operation %d to be coded\n",(op >> 2));
|
||||
dcache_warning = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2611,6 +2711,36 @@ Equal(op1,op2,fmt)
|
||||
return(boolean);
|
||||
}
|
||||
|
||||
static uword64
|
||||
AbsoluteValue(op,fmt)
|
||||
uword64 op;
|
||||
FP_formats fmt;
|
||||
{
|
||||
uword64 result;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("DBG: AbsoluteValue: %s: op = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op),WORD64LO(op));
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* The format type should already have been checked: */
|
||||
switch (fmt) {
|
||||
case fmt_single:
|
||||
{
|
||||
unsigned int wop = (unsigned int)op;
|
||||
float tmp = ((float)fabs((double)*(float *)&wop));
|
||||
result = (uword64)*(unsigned int *)&tmp;
|
||||
}
|
||||
break;
|
||||
case fmt_double:
|
||||
{
|
||||
double tmp = (fabs(*(double *)&op));
|
||||
result = *(uword64 *)&tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static uword64
|
||||
Negate(op,fmt)
|
||||
uword64 op;
|
||||
@ -2691,7 +2821,7 @@ Sub(op1,op2,fmt)
|
||||
uword64 result;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("DBG: Sub: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64H(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
|
||||
printf("DBG: Sub: %s: op1 = 0x%08X%08X : op2 = 0x%08X%08X\n",DOFMT(fmt),WORD64HI(op1),WORD64LO(op1),WORD64HI(op2),WORD64LO(op2));
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* The registers must specify FPRs valid for operands of type
|
||||
@ -3311,8 +3441,15 @@ 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
|
||||
we have just overflowed: */
|
||||
if (instruction_fetches == 0)
|
||||
instruction_fetch_overflow++;
|
||||
#if defined(PROFILE)
|
||||
if ((state & simPROFILE) && ((instruction_fetches % profile_frequency) == 0) && profile_hist) {
|
||||
int n = ((unsigned int)(PC - profile_minpc) >> (profile_shift + 2));
|
||||
|
Loading…
Reference in New Issue
Block a user