@@ -187,6 +187,85 @@ namespace xsimd
187187 */
188188 using x86_cpuid_leaf0 = detail::x86_cpuid_highest_func<false >;
189189
190+ /* *
191+ * Known processor manufacturer ID strings returned by CPUID leaf 0.
192+ *
193+ * The 12-byte manufacturer ID is stored in EBX, EDX, ECX (in that order).
194+ * Some strings are shared across physical CPUs, emulators, and virtual machines.
195+ * Obscure, defunct, and soft-core CPUs are not represented; they map to `unknown`.
196+ *
197+ * @see https://en.wikipedia.org/wiki/CPUID
198+ */
199+ enum class x86_manufacturer
200+ {
201+ /* *
202+ * AMD ("AuthenticAMD", "AMD ISBETTER").
203+ *
204+ * "AMD ISBETTER" was used by early K5 engineering samples.
205+ */
206+ amd,
207+ /* *
208+ * Intel ("GenuineIntel", "GenuineIotel").
209+ *
210+ * "GenuineIotel" is a rare typo variant seen on some chips.
211+ */
212+ intel,
213+ /* *
214+ * VIA / Centaur ("CentaurHauls", "VIA VIA VIA ").
215+ *
216+ * Centaur Technology was acquired by VIA in 1999;
217+ * older chips report "CentaurHauls", newer ones "VIA VIA VIA ".
218+ */
219+ via,
220+ /* * Zhaoxin (" Shanghai "). */
221+ zhaoxin,
222+ /* * Hygon ("HygonGenuine"). */
223+ hygon,
224+ /* *
225+ * Transmeta ("TransmetaCPU", "GenuineTMx86").
226+ *
227+ * Two different ID strings were used across product lines.
228+ */
229+ transmeta,
230+ /* * MCST Elbrus ("E2K MACHINE "). */
231+ elbrus,
232+ /* * Microsoft Virtual PC / x86-to-ARM ("Virtual CPU "). */
233+ microsoft_vpc,
234+ /* * Unrecognized manufacturer ID string. */
235+ unknown,
236+ };
237+
238+ /* *
239+ * Parse a 12-byte CPUID manufacturer ID into an @ref x86_manufacturer value.
240+ *
241+ * The input is the raw character array returned by @ref x86_cpuid_leaf0::manufacturer_id_raw.
242+ * Unrecognized strings map to @ref x86_manufacturer::unknown.
243+ */
244+ inline x86_manufacturer x86_parse_manufacturer (const std::array<char , 12 >& id) noexcept
245+ {
246+ auto eq = [&id](const char (&s)[13 ]) noexcept -> bool
247+ {
248+ return std::memcmp (id.data (), s, 12 ) == 0 ;
249+ };
250+ if (eq (" GenuineIntel" ) || eq (" GenuineIotel" ))
251+ return x86_manufacturer::intel;
252+ if (eq (" AuthenticAMD" ) || eq (" AMD ISBETTER" ))
253+ return x86_manufacturer::amd;
254+ if (eq (" CentaurHauls" ) || eq (" VIA VIA VIA " ))
255+ return x86_manufacturer::via;
256+ if (eq (" Shanghai " ))
257+ return x86_manufacturer::zhaoxin;
258+ if (eq (" HygonGenuine" ))
259+ return x86_manufacturer::hygon;
260+ if (eq (" TransmetaCPU" ) || eq (" GenuineTMx86" ))
261+ return x86_manufacturer::transmeta;
262+ if (eq (" E2K MACHINE " ))
263+ return x86_manufacturer::elbrus;
264+ if (eq (" Virtual CPU " ))
265+ return x86_manufacturer::microsoft_vpc;
266+ return x86_manufacturer::unknown;
267+ };
268+
190269 struct x86_cpuid_leaf1_traits
191270 {
192271 static constexpr detail::x86_reg32_t leaf = 1 ;
@@ -492,6 +571,31 @@ namespace xsimd
492571 return xcr0 ().all_bits_set <x86_xcr0::xcr0::sse, x86_xcr0::xcr0::avx, x86_xcr0::xcr0::zmm_hi256>();
493572 }
494573
574+ /* *
575+ * The manufacturer ID string in a static array.
576+ *
577+ * This raw character array is case specific and may contain both leading
578+ * and trailing whitespaces.
579+ * It cannot be assumed to be null terminated.
580+ */
581+ inline auto manufacturer_id_raw () const noexcept
582+ {
583+ return leaf0 ().manufacturer_id_raw ();
584+ }
585+
586+ #if __cplusplus >= 201703L
587+ inline std::string_view manufacturer_id () const noexcept
588+ {
589+ return leaf0 ().manufacturer_id ();
590+ }
591+ #endif
592+
593+ /* * The manufacturer ID string parsed into known common vendors. */
594+ inline x86_manufacturer known_manufacturer () const noexcept
595+ {
596+ return x86_parse_manufacturer (manufacturer_id_raw ());
597+ }
598+
495599 /* *
496600 * Indicates whether the OS has enabled extended state management.
497601 *
0 commit comments