Rewrite the mipsI/II/III pending-slot code.
authorAndrew Cagney <cagney@redhat.com>
Mon, 2 Feb 1998 13:49:17 +0000 (13:49 +0000)
committerAndrew Cagney <cagney@redhat.com>
Mon, 2 Feb 1998 13:49:17 +0000 (13:49 +0000)
sim/mips/ChangeLog
sim/mips/interp.c
sim/mips/sim-main.h

index ff698cd471ab928655afe1a88216450c72a651e7..a1dee765610f5d0c5cff033bdc320cc4785ea3cc 100644 (file)
@@ -1,3 +1,15 @@
+Tue Feb  3 00:10:50 1998  Andrew Cagney  <cagney@b1.cygnus.com>
+
+       * interp.c (ColdReset): Call PENDING_INVALIDATE.
+
+       * sim-main.h (ENGINE_ISSUE_PREFIX_HOOK): Call PENDING_TICK.
+
+       * interp.c (pending_tick): New function.  Deliver pending writes.
+
+       * sim-main.h (PENDING_FILL, PENDING_TICK, PENDING_SCHED,
+       PENDING_BIT, PENDING_INVALIDATE): Re-write pipeline code so that
+       it can handle mixed sized quantites and single bits.
+       
 Mon Feb  2 17:43:15 1998  Andrew Cagney  <cagney@b1.cygnus.com>
 
        * interp.c (oengine.h): Do not include when building with IGEN.
index 5b2f43f8dc9184af9d3ee911a3006c0c9ba67b35..095be7845f45976766c1eb68f2024ddd52471ee4 100644 (file)
@@ -1198,12 +1198,7 @@ ColdReset (SIM_DESC sd)
       
       /* Ensure that any instructions with pending register updates are
         cleared: */
-      {
-       int loop;
-       for (loop = 0; (loop < PSLOTS); loop++)
-         PENDING_SLOT_REG[loop] = (LAST_EMBED_REGNUM + 1);
-       PENDING_IN = PENDING_OUT = PENDING_TOTAL = 0;
-      }
+      PENDING_INVALIDATE();
       
       /* Initialise the FPU registers to the unknown state */
       if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
@@ -3308,73 +3303,8 @@ sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal)
       CANCELDELAYSLOT();
     }
 
-    if (MIPSISA < 4) { /* The following is only required on pre MIPS IV processors: */
-      /* Deal with pending register updates: */
-#ifdef DEBUG
-      printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
-#endif /* DEBUG */
-      if (PENDING_OUT != PENDING_IN) {
-        int loop;
-        int index = PENDING_OUT;
-        int total = PENDING_TOTAL;
-        if (PENDING_TOTAL == 0) {
-          fprintf(stderr,"FATAL: Mis-match on pending update pointers\n");
-          exit(1);
-        }
-        for (loop = 0; (loop < total); loop++) {
-#ifdef DEBUG
-          printf("DBG: BEFORE index = %d, loop = %d\n",index,loop);
-#endif /* DEBUG */
-          if (PENDING_SLOT_REG[index] != (LAST_EMBED_REGNUM + 1)) {
-#ifdef DEBUG
-            printf("pending_slot_count[%d] = %d\n",index,PENDING_SLOT_COUNT[index]);
-#endif /* DEBUG */
-            if (--(PENDING_SLOT_COUNT[index]) == 0) {
-#ifdef DEBUG
-              printf("pending_slot_reg[%d] = %d\n",index,PENDING_SLOT_REG[index]);
-              printf("pending_slot_value[%d] = 0x%s\n",index,pr_addr(PENDING_SLOT_VALUE[index]));
-#endif /* DEBUG */
-              if (PENDING_SLOT_REG[index] == COCIDX)
-               {
-                 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
-                   {
-                     SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
-                   }
-               }
-             else
-               {
-                 REGISTERS[PENDING_SLOT_REG[index]] = PENDING_SLOT_VALUE[index];
-                 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
-                   {
-                     /* The only time we have PENDING updates to FPU
-                        registers, is when performing binary transfers. This
-                        means we should update the register type field.  */
-                     if ((PENDING_SLOT_REG[index] >= FGRIDX) && (PENDING_SLOT_REG[index] < (FGRIDX + 32)))
-                       FPR_STATE[PENDING_SLOT_REG[index] - FGRIDX] = fmt_uninterpreted;
-                   }
-               }
-#ifdef DEBUG
-              printf("registers[%d] = 0x%s\n",PENDING_SLOT_REG[index],pr_addr(REGISTERS[PENDING_SLOT_REG[index]]));
-#endif /* DEBUG */
-              PENDING_SLOT_REG[index] = (LAST_EMBED_REGNUM + 1);
-              PENDING_OUT++;
-              if (PENDING_OUT == PSLOTS)
-               PENDING_OUT = 0;
-              PENDING_TOTAL--;
-            }
-          }
-#ifdef DEBUG
-          printf("DBG: AFTER  index = %d, loop = %d\n",index,loop);
-#endif /* DEBUG */
-          index++;
-          if (index == PSLOTS)
-           index = 0;
-        }
-      }
-#ifdef DEBUG
-      printf("DBG: EMPTY AFTER  pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL);
-#endif /* DEBUG */
-    }
+    if (MIPSISA < 4)
+      PENDING_TICK();
 
 #if !defined(FASTSIM)
     if (sim_events_tickn (sd, pipeline_count))
@@ -3448,5 +3378,72 @@ pr_uword64(addr)
 }
 
 
+void
+pending_tick (SIM_DESC sd,
+             sim_cpu *cpu,
+             address_word cia)
+{
+  if (PENDING_TRACE)                                                   
+    sim_io_printf (sd, "PENDING_DRAIN - pending_in = %d, pending_out = %d, pending_total = %d\n", PENDING_IN, PENDING_OUT, PENDING_TOTAL); 
+  if (PENDING_OUT != PENDING_IN)                                       
+    {                                                                  
+      int loop;                                                        
+      int index = PENDING_OUT;                                 
+      int total = PENDING_TOTAL;                                       
+      if (PENDING_TOTAL == 0)                                          
+       sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n"); 
+      for (loop = 0; (loop < total); loop++)                           
+       {                                                               
+         if (PENDING_SLOT_DEST[index] != NULL)                 
+           {                                                           
+             PENDING_SLOT_DELAY[index] -= 1;                           
+             if (PENDING_SLOT_DELAY[index] == 0)                       
+               {                                                       
+                 if (PENDING_SLOT_BIT[index] >= 0)                     
+                   switch (PENDING_SLOT_SIZE[index])                 
+                     {                                         
+                     case 32:                                  
+                       if (PENDING_SLOT_VALUE[index])          
+                         *(unsigned32*)PENDING_SLOT_DEST[index] |=     
+                           BIT32 (PENDING_SLOT_BIT[index]);            
+                       else                                            
+                         *(unsigned32*)PENDING_SLOT_DEST[index] &=     
+                           BIT32 (PENDING_SLOT_BIT[index]);            
+                       break;                                  
+                     case 64:                                  
+                       if (PENDING_SLOT_VALUE[index])          
+                         *(unsigned64*)PENDING_SLOT_DEST[index] |=     
+                           BIT64 (PENDING_SLOT_BIT[index]);            
+                       else                                            
+                         *(unsigned64*)PENDING_SLOT_DEST[index] &=     
+                           BIT64 (PENDING_SLOT_BIT[index]);            
+                       break;                                  
+                       break;                                  
+                     }
+                 else
+                   switch (PENDING_SLOT_SIZE[index])                 
+                     {                                         
+                     case 32:                                  
+                       *(unsigned32*)PENDING_SLOT_DEST[index] =        
+                         PENDING_SLOT_VALUE[index];                    
+                       break;                                  
+                     case 64:                                  
+                       *(unsigned64*)PENDING_SLOT_DEST[index] =        
+                         PENDING_SLOT_VALUE[index];                    
+                       break;                                  
+                     }                                                 
+               }                                                       
+             if (PENDING_OUT == index)                         
+               {                                                       
+                 PENDING_SLOT_DEST[index] = NULL;                      
+                 PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;             
+                 PENDING_TOTAL--;                                      
+               }                                                       
+           }                                                           
+       }                                                               
+      index = (index + 1) % PSLOTS;                                    
+    }                                                                  
+}
+
 /*---------------------------------------------------------------------------*/
 /*> EOF interp.c <*/
index fdb023c4d8387ed225eb4ff67523b674c6afdd4d..9f15093a091c94e1d3841cc9968b114d247e5d0a 100644 (file)
@@ -285,6 +285,81 @@ GPR_<type>(R,I) - return, as lvalue, the I'th <type> of general register R
 
 
 
+/* The following is probably not used for MIPS IV onwards: */
+/* Slots for delayed register updates. For the moment we just have a
+   fixed number of slots (rather than a more generic, dynamic
+   system). This keeps the simulator fast. However, we only allow
+   for the register update to be delayed for a single instruction
+   cycle. */
+#define PSLOTS (8) /* Maximum number of instruction cycles */
+
+typedef struct _pending_write_queue {
+  int in;
+  int out;
+  int total;
+  int slot_delay[PSLOTS];
+  int slot_size[PSLOTS];
+  int slot_bit[PSLOTS];
+  void *slot_dest[PSLOTS];
+  unsigned64 slot_value[PSLOTS];
+} pending_write_queue;
+
+#ifndef PENDING_TRACE
+#define PENDING_TRACE 0
+#endif
+#define PENDING_IN ((CPU)->pending.in)
+#define PENDING_OUT ((CPU)->pending.out)
+#define PENDING_TOTAL ((CPU)->pending.total)
+#define PENDING_SLOT_SIZE ((CPU)->pending.slot_size)
+#define PENDING_SLOT_BIT ((CPU)->pending.slot_size)
+#define PENDING_SLOT_DELAY ((CPU)->pending.slot_delay)
+#define PENDING_SLOT_DEST ((CPU)->pending.slot_dest)
+#define PENDING_SLOT_VALUE ((CPU)->pending.slot_value)
+
+/* Invalidate the pending write queue, all pending writes are
+   discarded. */
+
+#define PENDING_INVALIDATE() \
+memset (&(CPU)->pending, 0, sizeof ((CPU)->pending))
+
+/* Schedule a write to DEST for N cycles time.  For 64 bit
+   destinations, schedule two writes.  For floating point registers,
+   the caller should schedule a write to both the dest register and
+   the FPR_STATE register.  When BIT is non-negative, only BIT of DEST
+   is updated. */
+
+#define PENDING_SCHED(DEST,VAL,DELAY,BIT)                              \
+  do {                                                                 \
+    if (PENDING_SLOT_DEST[PENDING_IN] != NULL)                         \
+      sim_engine_abort (SD, CPU, cia,                                  \
+                       "PENDING_SCHED - buffer overflow\n");           \
+    if (PENDING_TRACE)                                                 \
+      sim_io_printf (SD, "PENDING_SCHED - dest 0x%lx, val 0x%lx, pending_in %d, pending_out %d, pending_total %d\n", (unsigned long) (DEST), (unsigned long) (VAL), PENDING_IN, PENDING_OUT, PENDING_TOTAL); \
+    PENDING_SLOT_DELAY[PENDING_IN] = (DELAY) + 1;                      \
+    PENDING_SLOT_DEST[PENDING_IN] = &(DEST);                           \
+    PENDING_SLOT_VALUE[PENDING_IN] = (VAL);                            \
+    PENDING_SLOT_SIZE[PENDING_IN] = sizeof (DEST);                     \
+    PENDING_SLOT_BIT[PENDING_IN] = (BIT);                              \
+  } while (0)
+
+#define PENDING_WRITE(DEST,VAL,DELAY) PENDING_SCHED(DEST,VAL,DELAY,-1)
+#define PENDING_BIT(DEST,VAL,DELAY,BIT) PENDING_SCHED(DEST,VAL,DELAY,BIT)
+
+#define PENDING_TICK() pending_tick (SD, CPU, cia)
+
+#define PENDING_FLUSH() abort () /* think about this one */
+#define PENDING_FP() abort () /* think about this one */
+
+/* For backward compatibility */
+#define PENDING_FILL(R,VAL)                                            \
+{                                                                      \
+  if ((R) >= FGRIDX && (R) < FGRIDX + NR_FGR)                          \
+    PENDING_SCHED(FGR[(R) - FGRIDX], VAL, 2, -1);                      \
+  else                                                                 \
+    PENDING_SCHED(GPR[(R)], VAL, 2, -1);                               \
+}
+
+
 
 struct _sim_cpu {
 
@@ -337,6 +412,8 @@ struct _sim_cpu {
 
 #define ENGINE_ISSUE_PREFIX_HOOK() \
   { \
+    /* Perform any pending writes */ \
+    PENDING_TICK(); \
     /* Set previous flag, depending on current: */ \
     if (STATE & simPCOC0) \
      STATE |= simPCOC1; \
@@ -376,6 +453,7 @@ struct _sim_cpu {
 
 #define GPR     (&REGISTERS[0])
 #define GPR_SET(N,VAL) (REGISTERS[(N)] = (VAL))
+#define NR_FGR  (32)
 #define FGRIDX  (38)
 #define FGR     (&REGISTERS[FGRIDX])
 #define LO      (REGISTERS[33])
@@ -412,42 +490,7 @@ struct _sim_cpu {
   FP_formats fpr_state[32];
 #define FPR_STATE ((CPU)->fpr_state)
 
-
-  /* Slots for delayed register updates. For the moment we just have a
-     fixed number of slots (rather than a more generic, dynamic
-     system). This keeps the simulator fast. However, we only allow
-     for the register update to be delayed for a single instruction
-     cycle. */
-#define PSLOTS (5) /* Maximum number of instruction cycles */
-  int pending_in;
-  int pending_out;
-  int pending_total;
-  int pending_slot_count[PSLOTS];
-  int pending_slot_reg[PSLOTS];
-  unsigned_word pending_slot_value[PSLOTS];
-#define PENDING_IN ((CPU)->pending_in)
-#define PENDING_OUT ((CPU)->pending_out)
-#define PENDING_TOTAL ((CPU)->pending_total)
-#define PENDING_SLOT_COUNT ((CPU)->pending_slot_count)
-#define PENDING_SLOT_REG ((CPU)->pending_slot_reg)
-#define PENDING_SLOT_VALUE ((CPU)->pending_slot_value)
-
-  /* The following are not used for MIPS IV onwards: */
-#define PENDING_FILL(r,v) {\
-/* printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL); */\
-                            if (PENDING_SLOT_REG[PENDING_IN] != (LAST_EMBED_REGNUM + 1))\
-                             sim_io_eprintf(sd,"Attempt to over-write pending value\n");\
-                            PENDING_SLOT_COUNT[PENDING_IN] = 2;\
-                            PENDING_SLOT_REG[PENDING_IN] = (r);\
-                            PENDING_SLOT_VALUE[PENDING_IN] = (uword64)(v);\
-/*printf("DBG: FILL        reg %d value = 0x%s\n",(r),pr_addr(v));*/\
-                            PENDING_TOTAL++;\
-                            PENDING_IN++;\
-                            if (PENDING_IN == PSLOTS)\
-                             PENDING_IN = 0;\
-/*printf("DBG: FILL AFTER  pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL);*/\
-                          }
-
+  pending_write_queue pending;
 
   /* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic
      read-write instructions. It is set when a linked load occurs. It
@@ -737,4 +780,6 @@ unsigned32 ifetch32 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, addres
 void dotrace PARAMS ((SIM_DESC sd, sim_cpu *cpu, FILE *tracefh, int type, SIM_ADDR address, int width, char *comment, ...));
 FILE *tracefh;
 
+void pending_tick PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia));
+
 #endif