2002-05-01 Chris Demetriou <cgd@broadcom.com>
authorChris Demetriou <cgd@google.com>
Wed, 1 May 2002 17:26:14 +0000 (17:26 +0000)
committerChris Demetriou <cgd@google.com>
Wed, 1 May 2002 17:26:14 +0000 (17:26 +0000)
        * cp1.c (store_fpr): Remove #ifdef'd out call to UndefinedResult
        which wouldn't compile anyway.
        * sim-main.h (unpredictable_action): New function prototype.
        (Unpredictable): Define to call igen function unpredictable().
        (NotWordValue): New macro to call igen function not_word_value().
        (UndefinedResult): Remove.
        * interp.c (undefined_result): Remove.
        (unpredictable_action): New function.
        * mips.igen (not_word_value, unpredictable): New functions.
        (ADD, ADDI, do_addiu, do_addu, BGEZAL, BGEZALL, BLTZAL, BLTZALL)
        (CLO, CLZ, MADD, MADDU, MSUB, MSUBU, MUL, do_mult, do_multu)
        (do_sra, do_srav, do_srl, do_srlv, SUB, do_subu): Invoke
        NotWordValue() to check for unpredictable inputs, then
        Unpredictable() to handle them.

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

index bdfd8a81dc67bcceb7687ae01da61d6aec938923..8f505c4f2803b2bd01b01f3d0f61c08c3c027e26 100644 (file)
@@ -1,3 +1,20 @@
+2002-05-01  Chris Demetriou  <cgd@broadcom.com>
+
+       * cp1.c (store_fpr): Remove #ifdef'd out call to UndefinedResult
+       which wouldn't compile anyway.
+       * sim-main.h (unpredictable_action): New function prototype.
+       (Unpredictable): Define to call igen function unpredictable().
+       (NotWordValue): New macro to call igen function not_word_value().
+       (UndefinedResult): Remove.
+       * interp.c (undefined_result): Remove.
+       (unpredictable_action): New function.
+       * mips.igen (not_word_value, unpredictable): New functions.
+       (ADD, ADDI, do_addiu, do_addu, BGEZAL, BGEZALL, BLTZAL, BLTZALL)
+       (CLO, CLZ, MADD, MADDU, MSUB, MSUBU, MUL, do_mult, do_multu)
+       (do_sra, do_srav, do_srl, do_srlv, SUB, do_subu): Invoke
+       NotWordValue() to check for unpredictable inputs, then
+       Unpredictable() to handle them.
+
 2002-02-24  Chris Demetriou  <cgd@broadcom.com>
 
        * mips.igen: Fix formatting of calls to Unpredictable().
index 9bd08f9ed6f8b567164574c5ff3322020c01f012..063c241c27746e4c17db34f86db47aa74f4a09c6 100644 (file)
@@ -279,10 +279,6 @@ store_fpr (SIM_DESC sd,
          break;
        }
     }
-#if defined(WARN_RESULT)
-  else
-    UndefinedResult ();
-#endif /* WARN_RESULT */
 
   if (err)
     SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()");
index 5bd61a8a824e32b72f23d82307d2154676a5e8c3..0c587e0a17da2866b3abe3b4d1186238761df9e8 100644 (file)
@@ -1869,28 +1869,31 @@ signal_exception (SIM_DESC sd,
 
 
 
-#if defined(WARN_RESULT)
-/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
-/* This function indicates that the result of the operation is
-   undefined. However, this should not affect the instruction
-   stream. All that is meant to happen is that the destination
-   register is set to an undefined result. To keep the simulator
-   simple, we just don't bother updating the destination register, so
-   the overall result will be undefined. If desired we can stop the
-   simulator by raising a pseudo-exception. */
-#define UndefinedResult() undefined_result (sd,cia)
-static void
-undefined_result(sd,cia)
-     SIM_DESC sd;
-     address_word cia;
+/* This function implements what the MIPS32 and MIPS64 ISAs define as
+   "UNPREDICTABLE" behaviour.
+
+   About UNPREDICTABLE behaviour they say: "UNPREDICTABLE results
+   may vary from processor implementation to processor implementation,
+   instruction to instruction, or as a function of time on the same
+   implementation or instruction.  Software can never depend on results
+   that are UNPREDICTABLE. ..."  (MIPS64 Architecture for Programmers
+   Volume II, The MIPS64 Instruction Set.  MIPS Document MD00087 revision
+   0.95, page 2.)
+  
+   For UNPREDICTABLE behaviour, we print a message, if possible print
+   the offending instructions mips.igen instruction name (provided by
+   the caller), and stop the simulator.
+
+   XXX FIXME: eventually, stopping the simulator should be made conditional
+   on a command-line option.  */
+void
+unpredictable_action(sim_cpu *cpu, address_word cia)
 {
-  sim_io_eprintf(sd,"UndefinedResult: PC = 0x%s\n",pr_addr(cia));
-#if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
-  state |= simSTOP;
-#endif
-  return;
+  SIM_DESC sd = CPU_STATE(cpu);
+
+  sim_io_eprintf(sd, "UNPREDICTABLE: PC = 0x%s\n", pr_addr (cia));
+  sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGABRT);
 }
-#endif /* WARN_RESULT */
 
 
 /*-- co-processor support routines ------------------------------------------*/
index 7cb9d10af06343c6d1e2f9cb5e94e53b3d3f78be..cd96766d88528164752dbdcba0012e51b2e6aee7 100644 (file)
 }
 
 
+// Helper:
+//
+// Check that a 32-bit register value is properly sign-extended.
+// (See NotWordValue in ISA spec.)
+//
+
+:function:::int:not_word_value:unsigned_word value
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*vr4100:
+*vr5000:
+*r3900:
+{
+  /* For historical simulator compatibility (until documentation is
+     found that makes these operations unpredictable on some of these
+     architectures), this check never returns true.  */
+  return 0;
+}
+
+:function:::int:not_word_value:unsigned_word value
+*mips32:
+{
+  /* On MIPS32, since registers are 32-bits, there's no check to be done.  */
+  return 0;
+}
+
+:function:::int:not_word_value:unsigned_word value
+*mips64:
+{
+  return ((value >> 32) != (value & 0x80000000 ? 0xFFFFFFFF : 0));
+}
+
+
+// Helper:
+//
+// Handle UNPREDICTABLE operation behaviour.  The goal here is to prevent
+// theoretically portable code which invokes non-portable behaviour from
+// running with no indication of the portability issue.
+// (See definition of UNPREDICTABLE in ISA spec.)
+//
+
+:function:::void:unpredictable:
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*vr4100:
+*vr5000:
+*r3900:
+{
+}
+
+:function:::void:unpredictable:
+*mips32:
+*mips64:
+{
+  unpredictable_action (CPU, CIA);
+}
+
+
 // Helper:
 //
 // Check that an access to a HI/LO register meets timing requirements
 *vr5000:
 *r3900:
 {
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
   {
     ALU32_BEGIN (GPR[RS]);
 *vr5000:
 *r3900:
 {
+  if (NotWordValue (GPR[RS]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[RS], EXTEND16 (IMMEDIATE));
   {
     ALU32_BEGIN (GPR[RS]);
 
 :function:::void:do_addiu:int rs, int rt, unsigned16 immediate
 {
+  if (NotWordValue (GPR[rs]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate));
   GPR[rt] = EXTEND32 (GPR[rs] + EXTEND16 (immediate));
   TRACE_ALU_RESULT (GPR[rt]);
 
 :function:::void:do_addu:int rs, int rt, int rd
 {
+  if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
   GPR[rd] = EXTEND32 (GPR[rs] + GPR[rt]);
   TRACE_ALU_RESULT (GPR[rd]);
 {
   address_word offset = EXTEND16 (OFFSET) << 2;
   check_branch_bug ();
+  if (RS == 31)
+    Unpredictable ();
   RA = (CIA + 8);
   if ((signed_word) GPR[RS] >= 0)
     {
 {
   address_word offset = EXTEND16 (OFFSET) << 2;
   check_branch_bug ();
+  if (RS == 31)
+    Unpredictable ();
   RA = (CIA + 8);
   /* NOTE: The branch occurs AFTER the next instruction has been
      executed */
 {
   address_word offset = EXTEND16 (OFFSET) << 2;
   check_branch_bug ();
+  if (RS == 31)
+    Unpredictable ();
   RA = (CIA + 8);
   /* NOTE: The branch occurs AFTER the next instruction has been
      executed */
 {
   address_word offset = EXTEND16 (OFFSET) << 2;
   check_branch_bug ();
+  if (RS == 31)
+    Unpredictable ();
   RA = (CIA + 8);
   if ((signed_word) GPR[RS] < 0)
     {
   unsigned32 i, mask;
   if (RT != RD)
     Unpredictable ();
+  if (NotWordValue (GPR[RS]))
+    Unpredictable ();
   TRACE_ALU_INPUT1 (GPR[RS]);
   for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i)
     {
   unsigned32 i, mask;
   if (RT != RD)
     Unpredictable ();
+  if (NotWordValue (GPR[RS]))
+    Unpredictable ();
   TRACE_ALU_INPUT1 (GPR[RS]);
   for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i)
     {
 {
   signed64 temp;
   check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
   temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
           + ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS])));
 {
   unsigned64 temp;
   check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
   temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
           + ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT])));
 {
   signed64 temp;
   check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
   temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
           - ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS])));
 {
   unsigned64 temp;
   check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
   temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
           - ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT])));
 *mips64:
 {
   signed64 prod;
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
   prod = (((signed64)(signed32) GPR[RS])
           * ((signed64)(signed32) GPR[RT]));
 {
   signed64 prod;
   check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+  if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
   prod = (((signed64)(signed32) GPR[rs])
          * ((signed64)(signed32) GPR[rt]));
 {
   unsigned64 prod;
   check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+  if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
   prod = (((unsigned64)(unsigned32) GPR[rs])
          * ((unsigned64)(unsigned32) GPR[rt]));
 :function:::void:do_sra:int rt, int rd, int shift
 {
   signed32 temp = (signed32) GPR[rt] >> shift;
+  if (NotWordValue (GPR[rt]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[rt], shift);
   GPR[rd] = EXTEND32 (temp);
   TRACE_ALU_RESULT (GPR[rd]);
 {
   int s = MASKED (GPR[rs], 4, 0);
   signed32 temp = (signed32) GPR[rt] >> s;
+  if (NotWordValue (GPR[rt]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[rt], s);
   GPR[rd] = EXTEND32 (temp);
   TRACE_ALU_RESULT (GPR[rd]);
 :function:::void:do_srl:int rt, int rd, int shift
 {
   unsigned32 temp = (unsigned32) GPR[rt] >> shift;
+  if (NotWordValue (GPR[rt]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[rt], shift);
   GPR[rd] = EXTEND32 (temp);
   TRACE_ALU_RESULT (GPR[rd]);
 {
   int s = MASKED (GPR[rs], 4, 0);
   unsigned32 temp = (unsigned32) GPR[rt] >> s;
+  if (NotWordValue (GPR[rt]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[rt], s);
   GPR[rd] = EXTEND32 (temp);
   TRACE_ALU_RESULT (GPR[rd]);
 *vr5000:
 *r3900:
 {
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
   {
     ALU32_BEGIN (GPR[RS]);
 
 :function:::void:do_subu:int rs, int rt, int rd
 {
+  if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+    Unpredictable ();
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
   GPR[rd] = EXTEND32 (GPR[rs] - GPR[rt]);
   TRACE_ALU_RESULT (GPR[rd]);
index 7c34888658c6584d68bda9e1cd09c737ae17d5af..4373c008794cf1cb61cb0fdc40bbc6bf466d4592 100644 (file)
@@ -771,8 +771,9 @@ INLINE_SIM_MAIN (void) prefetch PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word
 #define Prefetch(CCA,pAddr,vAddr,DATA,hint) \
 prefetch (SD, CPU, cia, CCA, pAddr, vAddr, DATA, hint)
 
-#define UndefinedResult()
-#define Unpredictable()
+void unpredictable_action (sim_cpu *cpu, address_word cia);
+#define NotWordValue(val)      not_word_value (SD_, (val))
+#define Unpredictable()                unpredictable (SD_)
 
 INLINE_SIM_MAIN (unsigned32) ifetch32 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr));
 #define IMEM32(CIA) ifetch32 (SD, CPU, (CIA), (CIA))