From bddcc3721c7ab1f88094617fb28572b771e77d6f Mon Sep 17 00:00:00 2001 From: Mykola Hohsadze Date: Wed, 26 Oct 2022 17:13:15 +0300 Subject: [PATCH] Add REP instructions detection (#282) --- include/cpuinfo_x86.h | 14 +++++++++++--- src/impl_x86__base_implementation.inl | 10 +++++++++- test/cpuinfo_x86_test.cc | 23 +++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/cpuinfo_x86.h b/include/cpuinfo_x86.h index 6a78de5..12f4e9d 100644 --- a/include/cpuinfo_x86.h +++ b/include/cpuinfo_x86.h @@ -100,9 +100,13 @@ typedef struct { int ss : 1; int adx : 1; int lzcnt : 1; // Note: this flag is called ABM for AMD, LZCNT for Intel. - int gfni: 1; - int movdiri: 1; - int movdir64b: 1; + int gfni : 1; + int movdiri : 1; + int movdir64b : 1; + int fs_rep_mov : 1; // Fast short REP MOV + int fz_rep_movsb : 1; // Fast zero-length REP MOVSB + int fs_rep_stosb : 1; // Fast short REP STOSB + int fs_rep_cmpsb_scasb : 1; // Fast short REP CMPSB/SCASB // Make sure to update X86FeaturesEnum below if you add a field here. } X86Features; @@ -262,6 +266,10 @@ typedef enum { X86_GFNI, X86_MOVDIRI, X86_MOVDIR64B, + X86_FS_REP_MOV, + X86_FZ_REP_MOVSB, + X86_FS_REP_STOSB, + X86_FS_REP_CMPSB_SCASB, X86_LAST_, } X86FeaturesEnum; diff --git a/src/impl_x86__base_implementation.inl b/src/impl_x86__base_implementation.inl index 473b638..fefbc6b 100644 --- a/src/impl_x86__base_implementation.inl +++ b/src/impl_x86__base_implementation.inl @@ -315,6 +315,10 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info, features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10); features->movdiri = IsBitSet(leaf_7.ecx, 27); features->movdir64b = IsBitSet(leaf_7.ecx, 28); + features->fs_rep_mov = IsBitSet(leaf_7.edx, 4); + features->fz_rep_movsb = IsBitSet(leaf_7_1.eax, 10); + features->fs_rep_stosb = IsBitSet(leaf_7_1.eax, 11); + features->fs_rep_cmpsb_scasb = IsBitSet(leaf_7_1.eax, 12); features->adx = IsBitSet(leaf_7.ebx, 19); features->lzcnt = IsBitSet(leaf_80000001.ecx, 5); @@ -1901,7 +1905,11 @@ CacheInfo GetX86CacheInfo(void) { LINE(X86_LZCNT, lzcnt, , , ) \ LINE(X86_GFNI, gfni, , , ) \ LINE(X86_MOVDIRI, movdiri, , , ) \ - LINE(X86_MOVDIR64B, movdir64b, , , ) + LINE(X86_MOVDIR64B, movdir64b, , , ) \ + LINE(X86_FS_REP_MOV, fs_rep_mov, , , ) \ + LINE(X86_FZ_REP_MOVSB, fz_rep_movsb, , , ) \ + LINE(X86_FS_REP_STOSB, fs_rep_stosb, , , ) \ + LINE(X86_FS_REP_CMPSB_SCASB, fs_rep_cmpsb_scasb, , , ) #define INTROSPECTION_PREFIX X86 #define INTROSPECTION_ENUM_PREFIX X86 #include "define_introspection.inl" diff --git a/test/cpuinfo_x86_test.cc b/test/cpuinfo_x86_test.cc index c9015e3..da63ec1 100644 --- a/test/cpuinfo_x86_test.cc +++ b/test/cpuinfo_x86_test.cc @@ -1048,6 +1048,29 @@ TEST_F(CpuidX86Test, INTEL_TREMONT_JASPER_LAKE_MOVDR) { EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ATOM_TMT); } +// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel0090672_AlderLake_LC_BC_CPUID01.txt +TEST_F(CpuidX86Test, INTEL_ALDER_LAKE_REP) { + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x00090672, 0x00800800, 0x7FFAFBFF, 0xBFEBFBFF}}, + {{0x00000007, 0}, Leaf{0x00000001, 0x239CA7EB, 0x98C027AC, 0xFC1CC410}}, + {{0x00000007, 1}, Leaf{0x00400810, 0x00000000, 0x00000000, 0x00000000}}, + }); + + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0x97); + EXPECT_TRUE(info.features.erms); + EXPECT_TRUE(info.features.fs_rep_mov); + EXPECT_FALSE(info.features.fz_rep_movsb); + EXPECT_TRUE(info.features.fs_rep_stosb); + EXPECT_FALSE(info.features.fs_rep_cmpsb_scasb); + + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ADL); +} + // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0100FA0_K10_Thuban_CPUID.txt TEST_F(CpuidX86Test, AMD_THUBAN_CACHE_INFO) { cpu().SetLeaves({