arm64: implement "mrs Xt, cntvct_el0" by pass-through to the host.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2900 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_arm64_defs.h b/priv/guest_arm64_defs.h
index 342312e..b8eb1ff 100644
--- a/priv/guest_arm64_defs.h
+++ b/priv/guest_arm64_defs.h
@@ -110,6 +110,11 @@
 //ZZ                               UInt resR1, UInt resR2 );
 
 
+/* --- DIRTY HELPERS --- */
+
+extern ULong arm64g_dirtyhelper_MRS_CNTVCT_EL0 ( void );
+
+
 /*---------------------------------------------------------*/
 /*--- Condition code stuff                              ---*/
 /*---------------------------------------------------------*/
diff --git a/priv/guest_arm64_helpers.c b/priv/guest_arm64_helpers.c
index eaa8d6f..5d2080e 100644
--- a/priv/guest_arm64_helpers.c
+++ b/priv/guest_arm64_helpers.c
@@ -677,6 +677,21 @@
 }
 
 
+/* CALLED FROM GENERATED CODE */
+/* DIRTY HELPER (non-referentially-transparent) */
+/* Horrible hack.  On non-arm64 platforms, return 0. */
+ULong arm64g_dirtyhelper_MRS_CNTVCT_EL0 ( void )
+{
+#  if defined(__aarch64__) && !defined(__arm__)
+   ULong w = 0x5555555555555555ULL; /* overwritten */
+   __asm__ __volatile__("mrs %0, cntvct_el0" : "=r"(w));
+   return w;
+#  else
+   return 0ULL;
+#  endif
+}
+
+
 /*---------------------------------------------------------------*/
 /*--- Flag-helpers translation-time function specialisers.    ---*/
 /*--- These help iropt specialise calls the above run-time    ---*/
diff --git a/priv/guest_arm64_toIR.c b/priv/guest_arm64_toIR.c
index 871c6a4..60ef7ea 100644
--- a/priv/guest_arm64_toIR.c
+++ b/priv/guest_arm64_toIR.c
@@ -5050,7 +5050,7 @@
    }
 
    /* ------------------ M{SR,RS} ------------------ */
-   /* Only handles the case where the system register is TPIDR_EL0.
+   /* ---- Cases for TPIDR_EL0 ----
       0xD51BD0 010 Rt   MSR tpidr_el0, rT
       0xD53BD0 010 Rt   MRS rT, tpidr_el0
    */
@@ -5067,7 +5067,7 @@
       }
       return True;
    }
-   /* Cases for FPCR 
+   /* ---- Cases for FPCR ----
       0xD51B44 000 Rt  MSR fpcr, rT
       0xD53B44 000 Rt  MSR rT, fpcr
    */
@@ -5084,7 +5084,7 @@
       }
       return True;
    }
-   /* Cases for FPSR 
+   /* ---- Cases for FPSR ----
       0xD51B44 001 Rt  MSR fpsr, rT
       0xD53B44 001 Rt  MSR rT, fpsr
       The only part of this we model is FPSR.QC.  All other bits
@@ -5122,7 +5122,7 @@
       }
       return True;
    }
-   /* Cases for NZCV
+   /* ---- Cases for NZCV ----
       D51B42 000 Rt  MSR nzcv, rT
       D53B42 000 Rt  MRS rT, nzcv
       The only parts of NZCV that actually exist are bits 31:28, which 
@@ -5146,7 +5146,7 @@
       }
       return True;
    }
-   /* Cases for DCZID_EL0
+   /* ---- Cases for DCZID_EL0 ----
       Don't support arbitrary reads and writes to this register.  Just
       return the value 16, which indicates that the DC ZVA instruction
       is not permitted, so we don't have to emulate it.
@@ -5158,7 +5158,7 @@
       DIP("mrs %s, dczid_el0 (FAKED)\n", nameIReg64orZR(tt));
       return True;
    }
-   /* Cases for CTR_EL0
+   /* ---- Cases for CTR_EL0 ----
       We just handle reads, and make up a value from the D and I line
       sizes in the VexArchInfo we are given, and patch in the following
       fields that the Foundation model gives ("natively"):
@@ -5184,6 +5184,28 @@
       DIP("mrs %s, ctr_el0\n", nameIReg64orZR(tt));
       return True;
    }
+   /* ---- Cases for CNTVCT_EL0 ----
+      This is a timestamp counter of some sort.  Support reads of it only
+      by passing through to the host.
+      D5 3B E0 010 Rt  MRS Xt, cntvct_el0
+   */
+   if ((INSN(31,0) & 0xFFFFFFE0) == 0xD53BE040) {
+      UInt     tt   = INSN(4,0);
+      IRTemp   val  = newTemp(Ity_I64);
+      IRExpr** args = mkIRExprVec_0();
+      IRDirty* d    = unsafeIRDirty_1_N ( 
+                         val, 
+                         0/*regparms*/, 
+                         "arm64g_dirtyhelper_MRS_CNTVCT_EL0",
+                         &arm64g_dirtyhelper_MRS_CNTVCT_EL0,
+                         args 
+                      );
+      /* execute the dirty call, dumping the result in val. */
+      stmt( IRStmt_Dirty(d) );
+      putIReg64orZR(tt, mkexpr(val));
+      DIP("mrs %s, cntvct_el0\n", nameIReg64orZR(tt));
+      return True;
+   }   
 
    /* ------------------ IC_IVAU ------------------ */
    /* D5 0B 75 001 Rt  ic ivau, rT