]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Advertise LZCNT via CPUID for x86 (32-bit) clients
authorMartin Cermak <mcermak@redhat.com>
Thu, 4 Jun 2026 07:02:17 +0000 (09:02 +0200)
committerMartin Cermak <mcermak@redhat.com>
Thu, 4 Jun 2026 07:08:24 +0000 (09:08 +0200)
The LZCNT instruction is only recognized by a
x86 guest if the host CPU supports it.

https://bugs.kde.org/show_bug.cgi?id=520753

NEWS
VEX/priv/guest_x86_defs.h
VEX/priv/guest_x86_helpers.c
VEX/priv/guest_x86_toIR.c

diff --git a/NEWS b/NEWS
index dd86e0f67955734df3a63701c99ca0a748c23f27..308e312722c8ed061c470adb4016e84f333d3656 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -37,6 +37,7 @@ are not entered into bugzilla tend to get forgotten about or ignored.
 519613  Valgrind incorrectly unpacks the result of sys_port (port_getn)
         on error, leading to a ~60s wallclock time delay on every call
 520482  Advertise POPCNT on x86 via CPUID
+520753  Advertise LZCNT via CPUID for x86 (32-bit) clients
 520856  unhandled instruction bytes: 0x2E 0xFF 0x14 0x85
 520861  Update FAQ for C++ standard library
 
index 5394e8cea14d0dee596a0338a9287ccd58506085..c1cfe2b99cdfdad7bf91ecb9a0cf7a630f49f52f 100644 (file)
@@ -143,7 +143,7 @@ extern void  x86g_dirtyhelper_CPUID_sse0 ( VexGuestX86State* );
 extern void  x86g_dirtyhelper_CPUID_mmxext ( VexGuestX86State* );
 extern void  x86g_dirtyhelper_CPUID_sse1 ( VexGuestX86State* );
 extern void  x86g_dirtyhelper_CPUID_sse2 ( VexGuestX86State* );
-extern void  x86g_dirtyhelper_CPUID_sse3 ( VexGuestX86State* );
+extern void  x86g_dirtyhelper_CPUID_sse3 ( VexGuestX86State*, UInt );
 
 extern void  x86g_dirtyhelper_FINIT ( VexGuestX86State* );
 
index 4765c282ef8bcb2ac908f58f15d20c28727ed05f..548bec5a9889289c677017336f5195d4c62a7753 100644 (file)
@@ -2476,7 +2476,8 @@ void x86g_dirtyhelper_CPUID_sse2 ( VexGuestX86State* st )
    address sizes   : 36 bits physical, 48 bits virtual
    power management:
 */
-void x86g_dirtyhelper_CPUID_sse3 ( VexGuestX86State* st )
+void x86g_dirtyhelper_CPUID_sse3 ( VexGuestX86State* st,
+                                   UInt hasLZCNT )
 {
 #  define SET_ABCD(_a,_b,_c,_d)               \
       do { st->guest_EAX = (UInt)(_a);        \
@@ -2533,9 +2534,13 @@ void x86g_dirtyhelper_CPUID_sse3 ( VexGuestX86State* st )
       case 0x80000000:
          SET_ABCD(0x80000008, 0x00000000, 0x00000000, 0x00000000);
          break;
-      case 0x80000001:
-         SET_ABCD(0x00000000, 0x00000000, 0x00000001, 0x20100000);
+      case 0x80000001: {
+         UInt ecx_extra = 0;
+         ecx_extra = hasLZCNT ? (1U << 5) : 0;
+         SET_ABCD(0x00000000, 0x00000000, 0x00000001 | ecx_extra,
+                  0x20100000);
          break;
+         }
       case 0x80000002:
          SET_ABCD(0x65746e49, 0x2952286c, 0x726f4320, 0x4d542865);
          break;
index 7d1533d93e34ccc43a91ce9c45c319d9e53c53be..dc90656c79f9797035d5c856be55732428e394c2 100644 (file)
@@ -15525,8 +15525,15 @@ DisResult disInstr_X86_WRK (
             vpanic("disInstr(x86)(cpuid)");
 
          vassert(fName); vassert(fAddr);
-         d = unsafeIRDirty_0_N ( 0/*regparms*/, 
-                                 fName, fAddr, mkIRExprVec_1(IRExpr_GSPTR()) );
+         IRExpr** args = NULL;
+         if (fAddr == &x86g_dirtyhelper_CPUID_sse3) {
+            Bool hasLZCNT = (archinfo->hwcaps & VEX_HWCAPS_X86_LZCNT) != 0;
+            args = mkIRExprVec_2(IRExpr_GSPTR(),
+                                 mkIRExpr_HWord(hasLZCNT ? 1 : 0));
+         } else {
+            args = mkIRExprVec_1(IRExpr_GSPTR());
+         }
+         d = unsafeIRDirty_0_N ( 0/*regparms*/, fName, fAddr, args );
          /* declare guest state effects */
          d->nFxState = 4;
          vex_bzero(&d->fxState, sizeof(d->fxState));