Fri Apr 19 15:48:24 1996 James G. Smith <jsmith@cygnus.co.uk>
authorJackie Smith Cashion <jsmith@redhat.com>
Fri, 19 Apr 1996 14:53:16 +0000 (14:53 +0000)
committerJackie Smith Cashion <jsmith@redhat.com>
Fri, 19 Apr 1996 14:53:16 +0000 (14:53 +0000)
* gencode.c (process_instructions): Ensure FP ABS instruction
  recognised.
* interp.c (AbsoluteValue): Add routine. Also provide simple PMON
  system call support.

sim/mips/gencode.c
sim/mips/interp.c

index ef3e1b359416f2974cd9da5b3eeb30af8cb593d2..cf93115b69670659b6e1334c14efe88841682d9a 100644 (file)
@@ -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
index 120044169f62cc4e86ac1cdb613b204dd15cc506..cda45d656521e7791b5a941127daf6a5ea244772 100644 (file)
@@ -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));