Mark Wielaard 97686e
commit 791fe5ecf909d573bcbf353b677b9404f9da0ed4
Mark Wielaard 97686e
Author: Mark Wielaard <mark@klomp.org>
Mark Wielaard 97686e
Date:   Mon May 27 22:19:27 2019 +0200
Mark Wielaard 97686e
Mark Wielaard 97686e
    Expose rdrand and f16c through cpuid also if the host only has avx.
Mark Wielaard 97686e
    
Mark Wielaard 97686e
    The amd64 CPUID dirtyhelpers are mostly static since they emulate some
Mark Wielaard 97686e
    existing CPU "family". The avx2 ("i7-4910MQ") CPUID variant however
Mark Wielaard 97686e
    can "dynamicly" enable rdrand and/or f16c if the host supports them.
Mark Wielaard 97686e
    Do the same for the avx_and_cx16 ("i5-2300") CPUID variant.
Mark Wielaard 97686e
    
Mark Wielaard 97686e
    https://bugs.kde.org/show_bug.cgi?id=408009
Mark Wielaard 97686e
Mark Wielaard 97686e
diff --git a/VEX/priv/guest_amd64_defs.h b/VEX/priv/guest_amd64_defs.h
Mark Wielaard 97686e
index 4f34b41..a5de527 100644
Mark Wielaard 97686e
--- a/VEX/priv/guest_amd64_defs.h
Mark Wielaard 97686e
+++ b/VEX/priv/guest_amd64_defs.h
Mark Wielaard 97686e
@@ -165,7 +165,9 @@ extern void  amd64g_dirtyhelper_storeF80le ( Addr/*addr*/, ULong/*data*/ );
Mark Wielaard 97686e
 extern void  amd64g_dirtyhelper_CPUID_baseline ( VexGuestAMD64State* st );
Mark Wielaard 97686e
 extern void  amd64g_dirtyhelper_CPUID_sse3_and_cx16 ( VexGuestAMD64State* st );
Mark Wielaard 97686e
 extern void  amd64g_dirtyhelper_CPUID_sse42_and_cx16 ( VexGuestAMD64State* st );
Mark Wielaard 97686e
-extern void  amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st );
Mark Wielaard 97686e
+extern void  amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st,
Mark Wielaard 97686e
+                                                     ULong hasF16C,
Mark Wielaard 97686e
+                                                     ULong hasRDRAND );
Mark Wielaard 97686e
 extern void  amd64g_dirtyhelper_CPUID_avx2 ( VexGuestAMD64State* st,
Mark Wielaard 97686e
                                              ULong hasF16C, ULong hasRDRAND );
Mark Wielaard 97686e
 
Mark Wielaard 97686e
diff --git a/VEX/priv/guest_amd64_helpers.c b/VEX/priv/guest_amd64_helpers.c
Mark Wielaard 97686e
index e4cf7e2..182bae0 100644
Mark Wielaard 97686e
--- a/VEX/priv/guest_amd64_helpers.c
Mark Wielaard 97686e
+++ b/VEX/priv/guest_amd64_helpers.c
Mark Wielaard 97686e
@@ -3141,8 +3141,11 @@ void amd64g_dirtyhelper_CPUID_sse42_and_cx16 ( VexGuestAMD64State* st )
Mark Wielaard 97686e
    address sizes   : 36 bits physical, 48 bits virtual
Mark Wielaard 97686e
    power management:
Mark Wielaard 97686e
 */
Mark Wielaard 97686e
-void amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st )
Mark Wielaard 97686e
+void amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st,
Mark Wielaard 97686e
+                                             ULong hasF16C, ULong hasRDRAND )
Mark Wielaard 97686e
 {
Mark Wielaard 97686e
+   vassert((hasF16C >> 1) == 0ULL);
Mark Wielaard 97686e
+   vassert((hasRDRAND >> 1) == 0ULL);
Mark Wielaard 97686e
 #  define SET_ABCD(_a,_b,_c,_d)                \
Mark Wielaard 97686e
       do { st->guest_RAX = (ULong)(_a);        \
Mark Wielaard 97686e
            st->guest_RBX = (ULong)(_b);        \
Mark Wielaard 97686e
@@ -3157,9 +3160,14 @@ void amd64g_dirtyhelper_CPUID_avx_and_cx16 ( VexGuestAMD64State* st )
Mark Wielaard 97686e
       case 0x00000000:
Mark Wielaard 97686e
          SET_ABCD(0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69);
Mark Wielaard 97686e
          break;
Mark Wielaard 97686e
-      case 0x00000001:
Mark Wielaard 97686e
-         SET_ABCD(0x000206a7, 0x00100800, 0x1f9ae3bf, 0xbfebfbff);
Mark Wielaard 97686e
+      case 0x00000001: {
Mark Wielaard 97686e
+         // As a baseline, advertise neither F16C (ecx:29) nor RDRAND (ecx:30),
Mark Wielaard 97686e
+         // but patch in support for them as directed by the caller.
Mark Wielaard 97686e
+         UInt ecx_extra
Mark Wielaard 97686e
+            = (hasF16C ? (1U << 29) : 0) | (hasRDRAND ? (1U << 30) : 0);
Mark Wielaard 97686e
+         SET_ABCD(0x000206a7, 0x00100800, (0x1f9ae3bf | ecx_extra), 0xbfebfbff);
Mark Wielaard 97686e
          break;
Mark Wielaard 97686e
+      }
Mark Wielaard 97686e
       case 0x00000002:
Mark Wielaard 97686e
          SET_ABCD(0x76035a01, 0x00f0b0ff, 0x00000000, 0x00ca0000);
Mark Wielaard 97686e
          break;
Mark Wielaard 97686e
diff --git a/VEX/priv/guest_amd64_toIR.c b/VEX/priv/guest_amd64_toIR.c
Mark Wielaard 97686e
index 56e992c..96dee38 100644
Mark Wielaard 97686e
--- a/VEX/priv/guest_amd64_toIR.c
Mark Wielaard 97686e
+++ b/VEX/priv/guest_amd64_toIR.c
Mark Wielaard 97686e
@@ -22007,7 +22007,8 @@ Long dis_ESC_0F (
Mark Wielaard 97686e
 
Mark Wielaard 97686e
       vassert(fName); vassert(fAddr);
Mark Wielaard 97686e
       IRExpr** args = NULL;
Mark Wielaard 97686e
-      if (fAddr == &amd64g_dirtyhelper_CPUID_avx2) {
Mark Wielaard 97686e
+      if (fAddr == &amd64g_dirtyhelper_CPUID_avx2
Mark Wielaard 97686e
+          || fAddr == &amd64g_dirtyhelper_CPUID_avx_and_cx16) {
Mark Wielaard 97686e
          Bool hasF16C   = (archinfo->hwcaps & VEX_HWCAPS_AMD64_F16C) != 0;
Mark Wielaard 97686e
          Bool hasRDRAND = (archinfo->hwcaps & VEX_HWCAPS_AMD64_RDRAND) != 0;
Mark Wielaard 97686e
          args = mkIRExprVec_3(IRExpr_GSPTR(),
Mark Wielaard 97686e
diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c
Mark Wielaard 97686e
index 3536e57..56a28d1 100644
Mark Wielaard 97686e
--- a/coregrind/m_machine.c
Mark Wielaard 97686e
+++ b/coregrind/m_machine.c
Mark Wielaard 97686e
@@ -1076,10 +1076,10 @@ Bool VG_(machine_get_hwcaps)( void )
Mark Wielaard 97686e
         have_avx2 = (ebx & (1<<5)) != 0; /* True => have AVX2 */
Mark Wielaard 97686e
      }
Mark Wielaard 97686e
 
Mark Wielaard 97686e
-     /* Sanity check for RDRAND and F16C.  These don't actually *need* AVX2, but
Mark Wielaard 97686e
-        it's convenient to restrict them to the AVX2 case since the simulated
Mark Wielaard 97686e
-        CPUID we'll offer them on has AVX2 as a base. */
Mark Wielaard 97686e
-     if (!have_avx2) {
Mark Wielaard 97686e
+     /* Sanity check for RDRAND and F16C.  These don't actually *need* AVX, but
Mark Wielaard 97686e
+        it's convenient to restrict them to the AVX case since the simulated
Mark Wielaard 97686e
+        CPUID we'll offer them on has AVX as a base. */
Mark Wielaard 97686e
+     if (!have_avx) {
Mark Wielaard 97686e
         have_f16c   = False;
Mark Wielaard 97686e
         have_rdrand = False;
Mark Wielaard 97686e
      }