For new IGEN simulators, rewrite checks validating correct use of the
authorAndrew Cagney <cagney@redhat.com>
Tue, 21 Apr 1998 01:17:58 +0000 (01:17 +0000)
committerAndrew Cagney <cagney@redhat.com>
Tue, 21 Apr 1998 01:17:58 +0000 (01:17 +0000)
HI/LO registers.  For old gencode simulator, delete all checks.

sim/mips/ChangeLog
sim/mips/gencode.c
sim/mips/interp.c
sim/mips/mips.igen
sim/mips/sim-main.h

index 8bc443c30563be9cdd51ec91220e8aeec2175c10..f1725ab4265b4e3f32cc2acd0d014b9ea18770d9 100644 (file)
@@ -1,3 +1,51 @@
+Mon Apr 20 11:26:55 1998  Andrew Cagney  <cagney@b1.cygnus.com>
+
+       * sim-main.h (struct hilo_access, struct hilo_history): Define,
+       contains HI/LO access history.
+       (struct _sim_cpu): Make hiaccess and loaccess of type hilo_access.
+       (HIACCESS, LOACCESS): Delete, replace with
+       (HIHISTORY, LOHISTORY): New macros.
+       (start-sanitize-r5900):
+       (struct sim_5900_cpu): Make hi1access, lo1access of type
+       hilo_access.
+       (HI1ACCESS, LO1ACCESS): Delete, replace with
+       (HI1HISTORY, LO1HISTORY): New macros.
+       (end-sanitize-r5900):
+       (CHECKHILO): Delete all, moved to mips.igen
+       
+       * gencode.c (build_instruction): Do not generate checks for
+       correct HI/LO register usage.
+
+       * interp.c (old_engine_run): Delete checks for correct HI/LO
+       register usage.
+
+       * mips.igen (check_mt_hilo, check_mf_hilo, check_op_hilo,
+       check_mf_cycles): New functions.
+       (do_mfhi, do_mflo, "mthi", "mtlo", do_ddiv, do_ddivu, do_div,
+       do_divu, domultx, do_mult, do_multu): Use.
+
+       * tx.igen ("madd", "maddu"): Use.
+       (start-sanitize-r5900):
+       
+       r5900.igen: Update all HI/LO checks.
+       ("mfhi1", "mflo1", "mthi1", "mthi1", "pmfhi", "pmflo", "pmfhl",
+       "pmthi", "pmtlo", "mpthl"): Check MF/MT HI/LO.
+       ("mult1", "div1", "divu1", "multu1", "madd1", "maddu1", "pdivbw",
+       "pdivuw", "pdivw", "phmaddh", "phmsubh", "pmaddh", "madduw",
+       "pmaddw", "pmsubh", "pmsubw", "pmulth", "pmultuw", "pmultw"):
+       Check HI/LO op.
+       (end-sanitize-r5900):
+       
+start-sanitize-sky
+Mon Apr 20 18:39:47 1998  Frank Ch. Eigler  <fche@cygnus.com>
+
+       * interp.c (decode_coproc): Correct CMFC2/QMTC2
+       GPR access.
+
+       * r5900.igen (LQ,SQ): Use a pair of 64-bit accesses
+       instead of a single 128-bit access.
+
+end-sanitize-sky
 start-sanitize-sky
 Fri Apr 17 14:50:39 1998  Frank Ch. Eigler  <fche@cygnus.com>
 
index 44fac70846184ae1f6075dee127455a43d10f3a8..becc194433018df99b1aa8f9af9e69a27b0063c7 100644 (file)
@@ -2527,9 +2527,6 @@ build_instruction (doisa, features, mips16, insn)
      {
      char* pipe = (insn->flags & PIPE1) ? "1" : "";
 
-     if (features & FEATURE_WARN_LOHI) {
-       printf("   CHECKHILO(\"Multiplication\");\n");
-     }
      printf("   {\n");
      if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
        printf("   uword64 mid;\n");
@@ -2578,9 +2575,6 @@ build_instruction (doisa, features, mips16, insn)
       int boolU = (insn->flags & UNSIGNED);
       char* pipe = (insn->flags & PIPE1) ? "1" : "";
 
-      if (features & FEATURE_WARN_LOHI) {
-        printf("   CHECKHILO(\"Division\");\n");
-      }
       printf("   {\n");
 
       if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
@@ -2697,14 +2691,8 @@ build_instruction (doisa, features, mips16, insn)
        if (insn->flags & LEFT)
        printf("   GPR[destreg] = %s%s;\n",regname,(pipe1 ? "1" : ""));
        else {
-        if (features & FEATURE_WARN_LOHI) {
-          printf("   if (%s%sACCESS != 0)\n",regname,(pipe1 ? "1" : ""));
-          printf("     sim_io_eprintf(sd,\"MT (move-to) over-writing %s register value\\n\");\n",regname);
-        }
         printf("   %s%s = op1;\n",regname,(pipe1 ? "1" : ""));
        }
-       if (features & FEATURE_WARN_LOHI)
-       printf("   %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname,(pipe1 ? "1" : ""));
      } else
       if (insn->flags & SHIFT16)
        printf("   GPR[destreg] = (op2 << 16);\n");
@@ -2813,9 +2801,6 @@ build_instruction (doisa, features, mips16, insn)
      /* Some of this code is shared with the standard multiply
        routines, so an effort should be made to merge where
        possible. */
-     if (features & FEATURE_WARN_LOHI) {
-       printf("   CHECKHILO(\"Multiply-Add\");\n");
-     }
      if (features & FEATURE_WARN_RESULT) {
        /* Give user a warning if either op1 or op2 are not 16bit signed integers */
        printf("   if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
index 8f45da9fd9748dd7aa0b627382e632d3db619c69..612b73b1a1d955379a56705b93487f544cf08e68 100644 (file)
@@ -3300,8 +3300,8 @@ decode_coproc (SIM_DESC sd,
                read_vu_vec_reg(&(vu0_device.regs), id, 1, A4_16(& xyzw, 2));
                read_vu_vec_reg(&(vu0_device.regs), id, 2, A4_16(& xyzw, 1));
                read_vu_vec_reg(&(vu0_device.regs), id, 3, A4_16(& xyzw, 0));
-               xyzw = T2H_16(xyzw);
-               memcpy(& GPR[rt], & xyzw, sizeof(xyzw));
+               GPR[rt] = T2H_8(* A8_16(& xyzw, 1));
+               GPR1[rt] = T2H_8(* A8_16(& xyzw, 0));
              }
            else /* CFC2 */
              {
@@ -3334,8 +3334,8 @@ decode_coproc (SIM_DESC sd,
            /* perform VU register address */
            if(i_25_21 == 0x05) /* QMTC2 */
              {
-               unsigned_16 xyzw;
-               memcpy(& xyzw, & GPR[rt], sizeof(xyzw));
+               unsigned_16 xyzw = U16_8(GPR1[rt], GPR[rt]);
+
                xyzw = H2T_16(xyzw);
                /* one word at a time, argh! */
                write_vu_vec_reg(&(vu0_device.regs), id, 0, A4_16(& xyzw, 3));
@@ -3624,20 +3624,6 @@ sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal)
 #error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU"
 #endif
 
-#if defined(WARN_LOHI)
-      /* Decrement the HI/LO validity ticks */
-      if (HIACCESS > 0)
-       HIACCESS--;
-      if (LOACCESS > 0)
-       LOACCESS--;
-      /* start-sanitize-r5900 */
-      if (HI1ACCESS > 0)
-       HI1ACCESS--;
-      if (LO1ACCESS > 0)
-       LO1ACCESS--;
-      /* end-sanitize-r5900 */
-#endif /* WARN_LOHI */
-
       /* For certain MIPS architectures, GPR[0] is hardwired to zero. We
          should check for it being changed. It is better doing it here,
          than within the simulator, since it will help keep the simulator
index 7b4102c7daac63354e9fdf10826bfb93e5896e77..89c1986defe9ac73723ab8de2db90e0dd2f9f71d 100644 (file)
 
 
 
+// Helper:
+// 
+// Check that an access to a HI/LO register meets timing requirements
+//
+// The following requirements exist:
+//
+//   -  A MT {HI,LO} update was not immediatly preceeded by a MF {HI,LO} read
+//   -  A OP {HI,LO} update was not immediatly preceeded by a MF {HI,LO} read
+//   -  A MF {HI,LO} read was not corrupted by a preceeding MT{LO,HI} update
+//      corruption occures when MT{LO,HI} is preceeded by a OP {HI,LO}.
+//
+
+:function:::int:check_mf_cycles:hilo_history *history, signed64 time, const char *new
+{
+  if (history->mf.timestamp + 3 > time)
+    {
+      sim_engine_abort (SD, CPU, CIA, "HILO: %s: %s at 0x%08lx too close to MF at 0x%08lx\n",
+                       itable[MY_INDEX].name,
+                       new, (long) CIA,
+                       (long) history->mf.cia);      
+      return 0;
+    }
+  return 1;
+}
+
+:function:::int:check_mt_hilo:hilo_history *history
+{
+  signed64 time = sim_events_time (SD);
+  int ok = check_mf_cycles (SD_, history, time, "MT");
+  history->mt.timestamp = time;
+  history->mt.cia = CIA;
+  return ok;
+}
+
+:function:::int:check_mf_hilo:hilo_history *history, hilo_history *peer
+{
+  signed64 time = sim_events_time (SD);
+  int ok = 1;
+  if (peer != NULL
+      && peer->mt.timestamp > history->op.timestamp
+      && history->mf.timestamp < history->op.timestamp)
+    {
+      /* The peer has been written to since the last OP yet we have
+         not */
+      sim_engine_abort (SD, CPU, CIA, "HILO: %s: MF at 0x%08lx following OP at 0x%08lx corrupted by MT at 0x%08lx\n",
+                       itable[MY_INDEX].name,
+                       (long) CIA,
+                       (long) history->op.cia,
+                       (long) peer->mt.cia);      
+      ok = 0;
+    }
+  history->mf.timestamp = time;
+  history->mf.cia = CIA;
+  return ok;
+}
+
+:function:::int:check_op_hilo:hilo_history *hi, hilo_history *lo
+*mipsI,mipsII,mipsIII,mipsIV:
+*vr5000:
+// start-sanitize-vr4320
+*vr4320:
+// end-sanitize-vr4320
+// start-sanitize-vr5400
+*vr5400:
+// end-sanitize-vr5400
+*r3900:
+// start-sanitize-tx19
+*tx19:
+// end-sanitize-tx19
+// start-sanitize-r5900
+*r5900:
+// end-sanitize-r5900
+{
+  signed64 time = sim_events_time (SD);
+  int ok = (check_mf_cycles (SD_, hi, time, "OP")
+           && check_mf_cycles (SD_, lo, time, "OP"));
+  hi->op.timestamp = time;
+  lo->op.timestamp = time;
+  hi->op.cia = CIA;
+  lo->op.cia = CIA;
+  return ok;
+}
+
+
+
 //
 // Mips Architecture:
 //
 
 :function:64::void:do_ddiv:int rs, int rt
 {
+  check_op_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
-  CHECKHILO ("Division");
   {
     signed64 n = GPR[rs];
     signed64 d = GPR[rt];
 
 :function:64::void:do_ddivu:int rs, int rt
 {
+  check_op_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
-  CHECKHILO ("Division");
   {
     unsigned64 n = GPR[rs];
     unsigned64 d = GPR[rt];
 
 :function:::void:do_div:int rs, int rt
 {
+  check_op_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
-  CHECKHILO("Division");
   {
     signed32 n = GPR[rs];
     signed32 d = GPR[rt];
 
 :function:::void:do_divu:int rs, int rt
 {
+  check_op_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
-  CHECKHILO ("Division");
   {
     unsigned32 n = GPR[rs];
     unsigned32 d = GPR[rt];
   int sign;
   unsigned64 op1 = GPR[rs];
   unsigned64 op2 = GPR[rt];
+  check_op_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
-  CHECKHILO ("Multiplication");
   /* make signed multiply unsigned */ 
   sign = 0;
   if (signed_p)
 
 :function:::void:do_mfhi:int rd
 {
+  check_mf_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT1 (HI);
   GPR[rd] = HI;
   TRACE_ALU_RESULT (GPR[rd]);
-#if 0
-  HIACCESS = 3;
-#endif
 }
 
 000000,0000000000,5.RD,00000,010000:SPECIAL:32::MFHI
 
 :function:::void:do_mflo:int rd
 {
+  check_mf_hilo (SD_, LOHISTORY, HIHISTORY);
   TRACE_ALU_INPUT1 (LO);
   GPR[rd] = LO;
   TRACE_ALU_RESULT (GPR[rd]);
-#if 0
-  LOACCESS = 3; /* 3rd instruction will be safe */
-#endif
 }
 
 000000,0000000000,5.RD,00000,010010:SPECIAL:32::MFLO
 *tx19:
 // end-sanitize-tx19
 {
-#if 0
-  if (HIACCESS != 0)
-    sim_io_eprintf (sd, "MT (move-to) over-writing HI register value\n");
-#endif
+  check_mt_hilo (SD_, HIHISTORY);
   HI = GPR[RS];
-#if 0
-  HIACCESS = 3; /* 3rd instruction will be safe */
-#endif
 }
 
 
 *tx19:
 // end-sanitize-tx19
 {
-#if 0
-  if (LOACCESS != 0)
-    sim_io_eprintf (sd, "MT (move-to) over-writing LO register value\n");
-#endif
+  check_mt_hilo (SD_, LOHISTORY);
   LO = GPR[RS];
-#if 0
-  LOACCESS = 3; /* 3rd instruction will be safe */
-#endif
 }
 
 
 :function:::void:do_mult:int rs, int rt, int rd
 {
   signed64 prod;
+  check_op_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
-  CHECKHILO ("Multiplication");
   prod = (((signed64)(signed32) GPR[rs])
          * ((signed64)(signed32) GPR[rt]));
   LO = EXTEND32 (VL4_8 (prod));
 :function:::void:do_multu:int rs, int rt, int rd
 {
   unsigned64 prod;
+  check_op_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
-  CHECKHILO ("Multiplication");
   prod = (((unsigned64)(unsigned32) GPR[rs])
          * ((unsigned64)(unsigned32) GPR[rt]));
   LO = EXTEND32 (VL4_8 (prod));
 // start-sanitize-vr5400
 *vr5400:
 // end-sanitize-vr5400
-// start-sanitize-r5900
-*r5900:
-// end-sanitize-r5900
 *r3900:
 // start-sanitize-tx19
 *tx19:
index 594a9f789ad073fde10af80207f2d3963c867a31..9a8cd153c142fc6cd228e6dc67f47e199969dfc1 100644 (file)
@@ -170,6 +170,30 @@ convert (SD, CPU, cia, rm, op, from, to)
 
 
 
+/* HI/LO register accesses */
+
+/* For some MIPS targets, the HI/LO registers have certain timing
+   restrictions in that, for instance, a read of a HI register must be
+   separated by at least three instructions from a preceeding read.
+
+   The struct below is used to record the last access by each of A MT,
+   MF or other OP instruction to a HI/LO register.  See mips.igen for
+   more details. */
+
+typedef struct _hilo_access {
+  signed64 timestamp;
+  address_word cia;
+} hilo_access;
+
+typedef struct _hilo_history {
+  hilo_access mt;
+  hilo_access mf;
+  hilo_access op;
+} hilo_history;
+
+
+
+
 /* Integer ALU operations: */
 
 #include "sim-alu.h"
@@ -204,6 +228,17 @@ enum {
   R5900_FCSR_SU = BIT (3),
 };
 
+/* Table 10-1 FP format values.
+   Note: some of these bits are different to what is found in a
+   standard MIPS manual. */
+enum {
+  R5900_EXPMAX = 128,
+  R5900_EXPMIN = -127,
+  R5900_EXPBIAS = 127,
+};
+
+
+
 typedef struct _sim_r5900_cpu {
 
   /* The R5900 has 32 x 128bit general purpose registers.
@@ -237,16 +272,10 @@ typedef struct _sim_r5900_cpu {
 
   /* See comments below about needing to count cycles between updating
      and setting HI/LO registers */
-  int hi1access;
-  int lo1access;
-#define HI1ACCESS ((CPU)->r5900.hi1access)
-#define LO1ACCESS ((CPU)->r5900.lo1access)
-#if 0
-#define CHECKHILO(s) {\
-  if ((HIACCESS != 0) || (LOACCESS != 0) || (HI1ACCESS != 0) || (LO1ACCESS != 0))\
-    sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\
-}
-#endif
+  hilo_history hi1_history;
+#define HI1HISTORY (&(CPU)->r5900.hi1_history)
+  hilo_history lo1_history;
+#define LO1HISTORY (&(CPU)->r5900.lo1_history)
 
 } sim_r5900_cpu;
 
@@ -601,34 +630,15 @@ struct _sim_cpu {
 #define LLBIT ((CPU)->llbit)
 
 
-/* The HIACCESS and LOACCESS counts are used to ensure that
-   corruptions caused by using the HI or LO register to close to a
-   following operation are spotted. */
-
-  int hiaccess;
-  int loaccess;
-#define HIACCESS ((CPU)->hiaccess)
-#define LOACCESS ((CPU)->loaccess)
-
-#if 0
-  unsigned_word HLPC;
-  /* 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 them use the value read and raise a warning to notify the
-     user: */
-#define CHECKHILO(s) {\
-  if ((HIACCESS != 0) || (LOACCESS != 0)) \
-    sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\
-}
-#endif
+/* The HIHISTORY and LOHISTORY timestamps are used to ensure that
+   corruptions caused by using the HI or LO register too close to a
+   following operation is spotted. See mips.igen for more details. */
+
+  hilo_history hi_history;
+#define HIHISTORY (&(CPU)->hi_history)
+  hilo_history lo_history;
+#define LOHISTORY (&(CPU)->lo_history)
 
-#if !defined CHECKHILO
-  /* 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.  */
-#define CHECKHILO(s)
-#endif
 
   /* start-sanitize-r5900 */
   sim_r5900_cpu r5900;