From: Martin Cermak Date: Thu, 4 Jun 2026 07:02:17 +0000 (+0200) Subject: Advertise LZCNT via CPUID for x86 (32-bit) clients X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fe54163b23c770ff0e32afed57eb8d1620ee245f;p=thirdparty%2Fvalgrind.git Advertise LZCNT via CPUID for x86 (32-bit) clients 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 --- diff --git a/NEWS b/NEWS index dd86e0f67..308e31272 100644 --- 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 diff --git a/VEX/priv/guest_x86_defs.h b/VEX/priv/guest_x86_defs.h index 5394e8cea..c1cfe2b99 100644 --- a/VEX/priv/guest_x86_defs.h +++ b/VEX/priv/guest_x86_defs.h @@ -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* ); diff --git a/VEX/priv/guest_x86_helpers.c b/VEX/priv/guest_x86_helpers.c index 4765c282e..548bec5a9 100644 --- a/VEX/priv/guest_x86_helpers.c +++ b/VEX/priv/guest_x86_helpers.c @@ -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; diff --git a/VEX/priv/guest_x86_toIR.c b/VEX/priv/guest_x86_toIR.c index 7d1533d93..dc90656c7 100644 --- a/VEX/priv/guest_x86_toIR.c +++ b/VEX/priv/guest_x86_toIR.c @@ -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));