From 74bf612b8f33937cc33dcea46baabf2bf56eb9ee Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 18 May 2020 05:58:41 -0700
Subject: [PATCH] x86: Move cpuinfo.h from libgcc to common/config/i386
Move cpuinfo.h from libgcc to common/config/i386 so that get_intel_cpu
can be shared by libgcc, GCC driver and gcc.target/i386/builtin_target.c
to detect the specific type of Intel and AMD CPUs:
1. Use the same enum processor_features in libgcc and x86 backend.
2. Add more processor features to enum processor_features.
3. Add M_VENDOR, M_CPU_TYPE and M_CPU_SUBTYPE in i386-builtins.c to
avoid duplication in.
4. Use cpu_indicator_init, has_cpu_feature, get_amd_cpu and get_intel_cpu
in driver-i386.c and builtin_target.c.
gcc/
PR target/95259
* common/config/i386/cpuinfo-builtins.h: Moved from
libgcc/config/i386/cpuinfo.h.
(processor_vendor): Add VENDOR_CENTAUR, VENDOR_CYRIX, VENDOR_NSC
and BUILTIN_VENDOR_MAX.
(processor_types): Add BUILTIN_CPU_TYPE_MAX.
(processor_features): Add FEATURE_3DNOW, FEATURE_3DNOWP,
FEATURE_ADX, FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT,
FEATURE_CLWB, FEATURE_CLZERO, FEATURE_CMPXCHG16B,
FEATURE_CMPXCHG8B, FEATURE_ENQCMD, FEATURE_F16C,
FEATURE_FSGSBASE, FEATURE_FXSAVE, FEATURE_HLE, FEATURE_IBT,
FEATURE_LAHF_LM, FEATURE_LM, FEATURE_LWP, FEATURE_LZCNT,
FEATURE_MOVBE, FEATURE_MOVDIR64B, FEATURE_MOVDIRI,
FEATURE_MWAITX, FEATURE_OSPKE, FEATURE_OSXSAVE, FEATURE_PCONFIG,
FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
FEATURE_XSAVEOPT, FEATURE_XSAVES and CPU_FEATURE_MAX.
(__processor_model): Moved to cpuinfo.h.
(__cpu_model): Removed.
(__cpu_features2): Likewise.
(SIZE_OF_CPU_FEATURES): New.
* common/config/i386/cpuinfo.h: Moved from
libgcc/config/i386/cpuinfo.c.
(__processor_model): Moved from libgcc/config/i386/cpuinfo.h.
(__processor_model2): New.
(CHECK___builtin_cpu_is): New. Defined as empty if not defined.
(has_cpu_feature): New function.
(set_cpu_feature): Likewise.
(get_amd_cpu): Moved from libgcc/config/i386/cpuinfo.c. Use
CHECK___builtin_cpu_is. Return AMD CPU name.
(get_intel_cpu): Moved from libgcc/config/i386/cpuinfo.c. Use
Use CHECK___builtin_cpu_is. Return Intel CPU name.
(get_available_features): Moved from libgcc/config/i386/cpuinfo.c.
Also check FEATURE_3DNOW, FEATURE_3DNOWP, FEATURE_ADX,
FEATURE_ABM, FEATURE_CLDEMOTE, FEATURE_CLFLUSHOPT, FEATURE_CLWB,
FEATURE_CLZERO, FEATURE_CMPXCHG16B, FEATURE_CMPXCHG8B,
FEATURE_ENQCMD, FEATURE_F16C, FEATURE_FSGSBASE, FEATURE_FXSAVE,
FEATURE_HLE, FEATURE_IBT, FEATURE_LAHF_LM, FEATURE_LM,
FEATURE_LWP, FEATURE_LZCNT, FEATURE_MOVBE, FEATURE_MOVDIR64B,
FEATURE_MOVDIRI, FEATURE_MWAITX, FEATURE_OSPKE, FEATURE_OSXSAVE,
FEATURE_PCONFIG, FEATURE_PKU, FEATURE_PREFETCHWT1, FEATURE_PRFCHW,
FEATURE_PTWRITE, FEATURE_RDPID, FEATURE_RDRND, FEATURE_RDSEED,
FEATURE_RTM, FEATURE_SERIALIZE, FEATURE_SGX, FEATURE_SHA,
FEATURE_SHSTK, FEATURE_TBM, FEATURE_TSXLDTRK, FEATURE_VAES,
FEATURE_WAITPKG, FEATURE_WBNOINVD, FEATURE_XSAVE, FEATURE_XSAVEC,
FEATURE_XSAVEOPT and FEATURE_XSAVES
(cpu_indicator_init): Moved from libgcc/config/i386/cpuinfo.c.
Also update cpu_model2.
* config/i386/driver-i386.c: Include
"common/config/i386/cpuinfo.h".
(host_detect_local_cpu): Call cpu_indicator_init to get CPU
features. Use has_cpu_feature to detect processor features.
Call get_amd_cpu to get AMD CPU name. Call get_intel_cpu to
get Intel CPU name.
* config/i386/i386-builtins.c: Include
"common/config/i386/cpuinfo-builtins.h".
(processor_features): Removed. Replace F_XXX with FEATURE_XXX.
(processor_model): Removed.
(_arch_names_table): Use "const int" on model.
(M_CPU_TYPE_START): New.
(M_CPU_SUBTYPE_START): Likewise.
(M_VENDOR): Likewise.
(M_CPU_TYPE): Likewise.
(M_CPU_SUBTYPE): Likewise.
(arch_names_table): Replace M_XXX with M_VENDOR, M_CPU_TYPE and
M_CPU_SUBTYPE.
(isa_names_table): Add more ISAs from enum processor_features.
(fold_builtin_cpu): Change __cpu_features2 to an array.
gcc/testsuite/
PR target/95259
* gcc.target/i386/builtin_target.c: Include <stdlib.h> and
../../../common/config/i386/cpuinfo.h.
(check_amd_cpu_model): Removed.
(check_intel_cpu_model): Likewise,
(CHECK___builtin_cpu_is): New.
(gcc_assert): New. Defined as assert.
(gcc_unreachable): New. Defined as abort.
(inline): New. Defined as empty.
(check_features): Use has_cpu_feature to check processor features.
(check_detailed): Call cpu_indicator_init. Always call
check_features. Call get_amd_cpu instead of check_amd_cpu_model.
Call get_intel_cpu instead of check_intel_cpu_model.
libgcc/
PR target/95259
* config/i386/cpuinfo.c: Include "common/config/i386/cpuinfo.h".
(__cpu_features2): Changed to array.
(get_amd_cpu): Moved to ... gcc/common/config/i386/cpuinfo.h.
(get_intel_cpu): Likewise.
(get_available_features): Likewise.
(__cpu_indicator_init): Call cpu_indicator_init.
* config/i386/cpuinfo.h: Moved to
gcc/common/config/i386/cpuinfo-builtins.h.
---
.../common/config/i386/cpuinfo-builtins.h | 70 +-
gcc/common/config/i386/cpuinfo.h | 834 ++++++++++++++++++
gcc/config/i386/driver-i386.c | 598 ++++---------
gcc/config/i386/i386-builtins.c | 339 ++++---
.../gcc.target/i386/builtin_target.c | 500 ++++-------
libgcc/config/i386/cpuinfo.c | 464 +---------
6 files changed, 1416 insertions(+), 1389 deletions(-)
rename libgcc/config/i386/cpuinfo.h => gcc/common/config/i386/cpuinfo-builtins.h (71%)
create mode 100644 gcc/common/config/i386/cpuinfo.h
similarity index 71%
rename from libgcc/config/i386/cpuinfo.h
rename to gcc/common/config/i386/cpuinfo-builtins.h
@@ -30,6 +30,10 @@ enum processor_vendor
VENDOR_INTEL = 1,
VENDOR_AMD,
VENDOR_OTHER,
+ VENDOR_CENTAUR,
+ VENDOR_CYRIX,
+ VENDOR_NSC,
+ BUILTIN_VENDOR_MAX = VENDOR_OTHER,
VENDOR_MAX
};
@@ -45,13 +49,14 @@ enum processor_types
INTEL_SILVERMONT,
INTEL_KNL,
AMD_BTVER1,
- AMD_BTVER2,
+ AMD_BTVER2,
AMDFAM17H,
INTEL_KNM,
INTEL_GOLDMONT,
INTEL_GOLDMONT_PLUS,
INTEL_TREMONT,
- CPU_TYPE_MAX
+ CPU_TYPE_MAX,
+ BUILTIN_CPU_TYPE_MAX = CPU_TYPE_MAX
};
enum processor_subtypes
@@ -123,14 +128,57 @@ enum processor_features
FEATURE_AVX512VNNI,
FEATURE_AVX512BITALG,
FEATURE_AVX512BF16,
- FEATURE_AVX512VP2INTERSECT
+ FEATURE_AVX512VP2INTERSECT,
+ FEATURE_3DNOW,
+ FEATURE_3DNOWP,
+ FEATURE_ADX,
+ FEATURE_ABM,
+ FEATURE_CLDEMOTE,
+ FEATURE_CLFLUSHOPT,
+ FEATURE_CLWB,
+ FEATURE_CLZERO,
+ FEATURE_CMPXCHG16B,
+ FEATURE_CMPXCHG8B,
+ FEATURE_ENQCMD,
+ FEATURE_F16C,
+ FEATURE_FSGSBASE,
+ FEATURE_FXSAVE,
+ FEATURE_HLE,
+ FEATURE_IBT,
+ FEATURE_LAHF_LM,
+ FEATURE_LM,
+ FEATURE_LWP,
+ FEATURE_LZCNT,
+ FEATURE_MOVBE,
+ FEATURE_MOVDIR64B,
+ FEATURE_MOVDIRI,
+ FEATURE_MWAITX,
+ FEATURE_OSPKE,
+ FEATURE_OSXSAVE,
+ FEATURE_PCONFIG,
+ FEATURE_PKU,
+ FEATURE_PREFETCHWT1,
+ FEATURE_PRFCHW,
+ FEATURE_PTWRITE,
+ FEATURE_RDPID,
+ FEATURE_RDRND,
+ FEATURE_RDSEED,
+ FEATURE_RTM,
+ FEATURE_SERIALIZE,
+ FEATURE_SGX,
+ FEATURE_SHA,
+ FEATURE_SHSTK,
+ FEATURE_TBM,
+ FEATURE_TSXLDTRK,
+ FEATURE_VAES,
+ FEATURE_WAITPKG,
+ FEATURE_WBNOINVD,
+ FEATURE_XSAVE,
+ FEATURE_XSAVEC,
+ FEATURE_XSAVEOPT,
+ FEATURE_XSAVES,
+ CPU_FEATURE_MAX
};
-extern struct __processor_model
-{
- unsigned int __cpu_vendor;
- unsigned int __cpu_type;
- unsigned int __cpu_subtype;
- unsigned int __cpu_features[1];
-} __cpu_model;
-extern unsigned int __cpu_features2;
+/* Size of __cpu_features2 array in libgcc/config/i386/cpuinfo.c. */
+#define SIZE_OF_CPU_FEATURES ((CPU_FEATURE_MAX - 1) / 32)
new file mode 100644
@@ -0,0 +1,834 @@
+/* Get CPU type and Features for x86 processors.
+ Copyright (C) 2012-2020 Free Software Foundation, Inc.
+ Contributed by Sriraman Tallam (tmsriram@google.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "cpuinfo-builtins.h"
+
+struct __processor_model
+{
+ unsigned int __cpu_vendor;
+ unsigned int __cpu_type;
+ unsigned int __cpu_subtype;
+ unsigned int __cpu_features[1];
+};
+
+struct __processor_model2
+{
+ unsigned int __cpu_family;
+ unsigned int __cpu_model;
+ unsigned int __cpu_max_level;
+ unsigned int __cpu_ext_level;
+};
+
+#ifndef CHECK___builtin_cpu_is
+# define CHECK___builtin_cpu_is(cpu)
+#endif
+
+/* Return non-zero if the processor has feature F. */
+
+static inline int
+has_cpu_feature (struct __processor_model *cpu_model,
+ unsigned int *cpu_features2,
+ enum processor_features f)
+{
+ unsigned int i;
+ if (f < 32)
+ return cpu_model->__cpu_features[0] & (1U << (f & 31));
+ for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+ if (f < (32 + 32 + i * 32))
+ return cpu_features2[i] & (1U << ((f - (32 + i * 32)) & 31));
+ gcc_unreachable ();
+}
+
+static inline void
+set_cpu_feature (struct __processor_model *cpu_model,
+ unsigned int *cpu_features2,
+ enum processor_features f)
+{
+ unsigned int i;
+ if (f < 32)
+ {
+ cpu_model->__cpu_features[0] |= (1U << (f & 31));
+ return;
+ }
+ for (i = 0; i < SIZE_OF_CPU_FEATURES; i++)
+ if (f < (32 + 32 + i * 32))
+ {
+ cpu_features2[i] |= (1U << ((f - (32 + i * 32)) & 31));
+ return;
+ }
+ gcc_unreachable ();
+}
+
+/* Get the specific type of AMD CPU and return AMD CPU name. Return
+ NULL for unknown AMD CPU. */
+
+static inline const char *
+get_amd_cpu (struct __processor_model *cpu_model,
+ struct __processor_model2 *cpu_model2,
+ unsigned int *cpu_features2)
+{
+ const char *cpu = NULL;
+ unsigned int family = cpu_model2->__cpu_family;
+ unsigned int model = cpu_model2->__cpu_model;
+
+ switch (family)
+ {
+ case 0x10:
+ /* AMD Family 10h. */
+ cpu = "amdfam10";
+ cpu_model->__cpu_type = AMDFAM10H;
+ switch (model)
+ {
+ case 0x2:
+ /* Barcelona. */
+ CHECK___builtin_cpu_is ("amdfam10h");
+ CHECK___builtin_cpu_is ("barcelona");
+ cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
+ break;
+ case 0x4:
+ /* Shanghai. */
+ CHECK___builtin_cpu_is ("amdfam10h");
+ CHECK___builtin_cpu_is ("shanghai");
+ cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
+ break;
+ case 0x8:
+ /* Istanbul. */
+ CHECK___builtin_cpu_is ("amdfam10h");
+ CHECK___builtin_cpu_is ("istanbul");
+ cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x14:
+ /* AMD Family 14h "btver1". */
+ cpu = "btver1";
+ CHECK___builtin_cpu_is ("btver1");
+ cpu_model->__cpu_type = AMD_BTVER1;
+ break;
+ case 0x15:
+ /* AMD Family 15h "Bulldozer". */
+ cpu_model->__cpu_type = AMDFAM15H;
+ if (model == 0x2)
+ {
+ /* Bulldozer version 2 "Piledriver" */
+ cpu = "bdver2";
+ CHECK___builtin_cpu_is ("bdver2");
+ cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+ }
+ else if (model <= 0xf)
+ {
+ /* Bulldozer version 1. */
+ cpu = "bdver1";
+ CHECK___builtin_cpu_is ("bdver1");
+ cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+ }
+ else if (model <= 0x2f)
+ {
+ /* Bulldozer version 2 "Piledriver" */
+ cpu = "bdver2";
+ CHECK___builtin_cpu_is ("bdver2");
+ cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+ }
+ else if (model <= 0x4f)
+ {
+ /* Bulldozer version 3 "Steamroller" */
+ cpu = "bdver3";
+ CHECK___builtin_cpu_is ("bdver3");
+ cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+ }
+ else if (model <= 0x7f)
+ {
+ /* Bulldozer version 4 "Excavator" */
+ cpu = "bdver4";
+ CHECK___builtin_cpu_is ("bdver4");
+ cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+ }
+ else if (has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_AVX2))
+ {
+ cpu = "bdver4";
+ CHECK___builtin_cpu_is ("bdver4");
+ cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
+ }
+ else if (has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_XSAVEOPT))
+ {
+ cpu = "bdver3";
+ CHECK___builtin_cpu_is ("bdver3");
+ cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
+ }
+ else if (has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_BMI))
+ {
+ cpu = "bdver2";
+ CHECK___builtin_cpu_is ("bdver2");
+ cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
+ }
+ else if (has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_XOP))
+ {
+ cpu = "bdver1";
+ CHECK___builtin_cpu_is ("bdver1");
+ cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
+ }
+ break;
+ case 0x16:
+ /* AMD Family 16h "btver2" */
+ cpu = "btver2";
+ CHECK___builtin_cpu_is ("btver2");
+ cpu_model->__cpu_type = AMD_BTVER2;
+ break;
+ case 0x17:
+ cpu_model->__cpu_type = AMDFAM17H;
+ if (model <= 0x1f)
+ {
+ /* AMD family 17h version 1. */
+ cpu = "znver1";
+ CHECK___builtin_cpu_is ("znver1");
+ cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+ }
+ else if (model >= 0x30)
+ {
+ cpu = "znver2";
+ CHECK___builtin_cpu_is ("znver2");
+ cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+ }
+ else if (has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_CLWB))
+ {
+ cpu = "znver2";
+ CHECK___builtin_cpu_is ("znver2");
+ cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
+ }
+ else if (has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_CLZERO))
+ {
+ cpu = "znver1";
+ CHECK___builtin_cpu_is ("znver1");
+ cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return cpu;
+}
+
+/* Get the specific type of Intel CPU and return Intel CPU name. Return
+ NULL for unknown Intel CPU. */
+
+static inline const char *
+get_intel_cpu (struct __processor_model *cpu_model,
+ struct __processor_model2 *cpu_model2,
+ unsigned int *cpu_features2,
+ unsigned int brand_id)
+{
+ const char *cpu = NULL;
+
+ /* Parse family and model only for brand ID 0 and model 6. */
+ if (brand_id != 0 || cpu_model2->__cpu_family != 0x6)
+ return cpu;
+
+ switch (cpu_model2->__cpu_model)
+ {
+ case 0x1c:
+ case 0x26:
+ /* Bonnell. */
+ cpu = "bonnell";
+ CHECK___builtin_cpu_is ("atom");
+ cpu_model->__cpu_type = INTEL_BONNELL;
+ break;
+ case 0x37:
+ case 0x4a:
+ case 0x4d:
+ case 0x5d:
+ /* Silvermont. */
+ case 0x4c:
+ case 0x5a:
+ case 0x75:
+ /* Airmont. */
+ cpu = "silvermont";
+ CHECK___builtin_cpu_is ("silvermont");
+ cpu_model->__cpu_type = INTEL_SILVERMONT;
+ break;
+ case 0x5c:
+ case 0x5f:
+ /* Goldmont. */
+ cpu = "goldmont";
+ CHECK___builtin_cpu_is ("goldmont");
+ cpu_model->__cpu_type = INTEL_GOLDMONT;
+ break;
+ case 0x7a:
+ /* Goldmont Plus. */
+ cpu = "goldmont-plus";
+ CHECK___builtin_cpu_is ("goldmont-plus");
+ cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
+ break;
+ case 0x86:
+ case 0x96:
+ case 0x9c:
+ /* Tremont. */
+ cpu = "tremont";
+ CHECK___builtin_cpu_is ("tremont");
+ cpu_model->__cpu_type = INTEL_TREMONT;
+ break;
+ case 0x57:
+ /* Knights Landing. */
+ cpu = "knl";
+ CHECK___builtin_cpu_is ("knl");
+ cpu_model->__cpu_type = INTEL_KNL;
+ break;
+ case 0x85:
+ /* Knights Mill. */
+ cpu = "knm";
+ CHECK___builtin_cpu_is ("knm");
+ cpu_model->__cpu_type = INTEL_KNM;
+ break;
+ case 0x1a:
+ case 0x1e:
+ case 0x1f:
+ case 0x2e:
+ /* Nehalem. */
+ cpu = "nehalem";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("nehalem");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
+ break;
+ case 0x25:
+ case 0x2c:
+ case 0x2f:
+ /* Westmere. */
+ cpu = "westmere";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("westmere");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
+ break;
+ case 0x2a:
+ case 0x2d:
+ /* Sandy Bridge. */
+ cpu = "sandybridge";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("sandybridge");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
+ break;
+ case 0x3a:
+ case 0x3e:
+ /* Ivy Bridge. */
+ cpu = "ivybridge";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("ivybridge");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
+ break;
+ case 0x3c:
+ case 0x3f:
+ case 0x45:
+ case 0x46:
+ /* Haswell. */
+ cpu = "haswell";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("haswell");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
+ break;
+ case 0x3d:
+ case 0x47:
+ case 0x4f:
+ case 0x56:
+ /* Broadwell. */
+ cpu = "broadwell";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("broadwell");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
+ break;
+ case 0x4e:
+ case 0x5e:
+ /* Skylake. */
+ case 0x8e:
+ case 0x9e:
+ /* Kaby Lake. */
+ case 0xa5:
+ case 0xa6:
+ /* Comet Lake. */
+ cpu = "skylake";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("skylake");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
+ break;
+ case 0x55:
+ CHECK___builtin_cpu_is ("corei7");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ if (has_cpu_feature (cpu_model, cpu_features2,
+ FEATURE_AVX512VNNI))
+ {
+ /* Cascade Lake. */
+ cpu = "cascadelake";
+ CHECK___builtin_cpu_is ("cascadelake");
+ cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
+ }
+ else
+ {
+ /* Skylake with AVX-512 support. */
+ cpu = "skylake-avx512";
+ CHECK___builtin_cpu_is ("skylake-avx512");
+ cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
+ }
+ break;
+ case 0x66:
+ /* Cannon Lake. */
+ cpu = "cannonlake";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("cannonlake");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
+ break;
+ case 0x6a:
+ case 0x6c:
+ /* Ice Lake server. */
+ cpu = "icelake-server";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("icelake-server");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
+ break;
+ case 0x7e:
+ case 0x7d:
+ case 0x9d:
+ /* Ice Lake client. */
+ cpu = "icelake-client";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("icelake-client");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
+ break;
+ case 0x8c:
+ case 0x8d:
+ /* Tiger Lake. */
+ cpu = "tigerlake";
+ CHECK___builtin_cpu_is ("corei7");
+ CHECK___builtin_cpu_is ("tigerlake");
+ cpu_model->__cpu_type = INTEL_COREI7;
+ cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
+ break;
+ case 0x17:
+ case 0x1d:
+ /* Penryn. */
+ case 0x0f:
+ /* Merom. */
+ cpu = "core2";
+ CHECK___builtin_cpu_is ("core2");
+ cpu_model->__cpu_type = INTEL_CORE2;
+ break;
+ default:
+ break;
+ }
+
+ return cpu;
+}
+
+/* ECX and EDX are output of CPUID at level one. */
+static inline void
+get_available_features (struct __processor_model *cpu_model,
+ struct __processor_model2 *cpu_model2,
+ unsigned int *cpu_features2,
+ unsigned int ecx, unsigned int edx)
+{
+ unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
+ unsigned int eax, ebx;
+ unsigned int ext_level;
+
+ /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
+#define XCR_XFEATURE_ENABLED_MASK 0x0
+#define XSTATE_FP 0x1
+#define XSTATE_SSE 0x2
+#define XSTATE_YMM 0x4
+#define XSTATE_OPMASK 0x20
+#define XSTATE_ZMM 0x40
+#define XSTATE_HI_ZMM 0x80
+
+#define XCR_AVX_ENABLED_MASK \
+ (XSTATE_SSE | XSTATE_YMM)
+#define XCR_AVX512F_ENABLED_MASK \
+ (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
+
+ /* Check if AVX and AVX512 are usable. */
+ int avx_usable = 0;
+ int avx512_usable = 0;
+ if ((ecx & bit_OSXSAVE))
+ {
+ /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
+ ZMM16-ZMM31 states are supported by OSXSAVE. */
+ unsigned int xcrlow;
+ unsigned int xcrhigh;
+ __asm__ (".byte 0x0f, 0x01, 0xd0"
+ : "=a" (xcrlow), "=d" (xcrhigh)
+ : "c" (XCR_XFEATURE_ENABLED_MASK));
+ if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
+ {
+ avx_usable = 1;
+ avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
+ == XCR_AVX512F_ENABLED_MASK);
+ }
+ }
+
+#define set_feature(f) \
+ set_cpu_feature (cpu_model, cpu_features2, f)
+
+ if (edx & bit_CMOV)
+ set_feature (FEATURE_CMOV);
+ if (edx & bit_MMX)
+ set_feature (FEATURE_MMX);
+ if (edx & bit_SSE)
+ set_feature (FEATURE_SSE);
+ if (edx & bit_SSE2)
+ set_feature (FEATURE_SSE2);
+ if (edx & bit_CMPXCHG8B)
+ set_feature (FEATURE_CMPXCHG8B);
+ if (edx & bit_FXSAVE)
+ set_feature (FEATURE_FXSAVE);
+
+ if (ecx & bit_POPCNT)
+ set_feature (FEATURE_POPCNT);
+ if (ecx & bit_AES)
+ set_feature (FEATURE_AES);
+ if (ecx & bit_PCLMUL)
+ set_feature (FEATURE_PCLMUL);
+ if (ecx & bit_SSE3)
+ set_feature (FEATURE_SSE3);
+ if (ecx & bit_SSSE3)
+ set_feature (FEATURE_SSSE3);
+ if (ecx & bit_SSE4_1)
+ set_feature (FEATURE_SSE4_1);
+ if (ecx & bit_SSE4_2)
+ set_feature (FEATURE_SSE4_2);
+ if (ecx & bit_OSXSAVE)
+ set_feature (FEATURE_OSXSAVE);
+ if (ecx & bit_CMPXCHG16B)
+ set_feature (FEATURE_CMPXCHG16B);
+ if (ecx & bit_MOVBE)
+ set_feature (FEATURE_MOVBE);
+ if (ecx & bit_AES)
+ set_feature (FEATURE_AES);
+ if (ecx & bit_F16C)
+ set_feature (FEATURE_F16C);
+ if (ecx & bit_RDRND)
+ set_feature (FEATURE_RDRND);
+ if (ecx & bit_XSAVE)
+ set_feature (FEATURE_XSAVE);
+ if (avx_usable)
+ {
+ if (ecx & bit_AVX)
+ set_feature (FEATURE_AVX);
+ if (ecx & bit_FMA)
+ set_feature (FEATURE_FMA);
+ }
+
+ /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
+ if (max_cpuid_level >= 7)
+ {
+ __cpuid_count (7, 0, eax, ebx, ecx, edx);
+ if (ebx & bit_BMI)
+ set_feature (FEATURE_BMI);
+ if (ebx & bit_SGX)
+ set_feature (FEATURE_SGX);
+ if (ebx & bit_HLE)
+ set_feature (FEATURE_HLE);
+ if (ebx & bit_RTM)
+ set_feature (FEATURE_RTM);
+ if (avx_usable)
+ {
+ if (ebx & bit_AVX2)
+ set_feature (FEATURE_AVX2);
+ if (ecx & bit_VPCLMULQDQ)
+ set_feature (FEATURE_VPCLMULQDQ);
+ }
+ if (ebx & bit_BMI2)
+ set_feature (FEATURE_BMI2);
+ if (ebx & bit_FSGSBASE)
+ set_feature (FEATURE_FSGSBASE);
+ if (ebx & bit_RDSEED)
+ set_feature (FEATURE_RDSEED);
+ if (ebx & bit_ADX)
+ set_feature (FEATURE_ADX);
+ if (ebx & bit_SHA)
+ set_feature (FEATURE_SHA);
+ if (ebx & bit_CLFLUSHOPT)
+ set_feature (FEATURE_CLFLUSHOPT);
+ if (ebx & bit_CLWB)
+ set_feature (FEATURE_CLWB);
+ if (ecx & bit_PREFETCHWT1)
+ set_feature (FEATURE_PREFETCHWT1);
+ if (ecx & bit_OSPKE)
+ set_feature (FEATURE_OSPKE);
+ if (ecx & bit_RDPID)
+ set_feature (FEATURE_RDPID);
+ if (ecx & bit_VAES)
+ set_feature (FEATURE_VAES);
+ if (ecx & bit_GFNI)
+ set_feature (FEATURE_GFNI);
+ if (ecx & bit_MOVDIRI)
+ set_feature (FEATURE_MOVDIRI);
+ if (ecx & bit_MOVDIR64B)
+ set_feature (FEATURE_MOVDIR64B);
+ if (ecx & bit_ENQCMD)
+ set_feature (FEATURE_ENQCMD);
+ if (ecx & bit_CLDEMOTE)
+ set_feature (FEATURE_CLDEMOTE);
+ if (ecx & bit_WAITPKG)
+ set_feature (FEATURE_WAITPKG);
+ if (ecx & bit_SHSTK)
+ set_feature (FEATURE_SHSTK);
+ if (edx & bit_SERIALIZE)
+ set_feature (FEATURE_SERIALIZE);
+ if (edx & bit_TSXLDTRK)
+ set_feature (FEATURE_TSXLDTRK);
+ if (edx & bit_PCONFIG)
+ set_feature (FEATURE_PCONFIG);
+ if (edx & bit_IBT)
+ set_feature (FEATURE_IBT);
+ if (avx512_usable)
+ {
+ if (ebx & bit_AVX512F)
+ set_feature (FEATURE_AVX512F);
+ if (ebx & bit_AVX512VL)
+ set_feature (FEATURE_AVX512VL);
+ if (ebx & bit_AVX512BW)
+ set_feature (FEATURE_AVX512BW);
+ if (ebx & bit_AVX512DQ)
+ set_feature (FEATURE_AVX512DQ);
+ if (ebx & bit_AVX512CD)
+ set_feature (FEATURE_AVX512CD);
+ if (ebx & bit_AVX512PF)
+ set_feature (FEATURE_AVX512PF);
+ if (ebx & bit_AVX512ER)
+ set_feature (FEATURE_AVX512ER);
+ if (ebx & bit_AVX512IFMA)
+ set_feature (FEATURE_AVX512IFMA);
+ if (ecx & bit_AVX512VBMI)
+ set_feature (FEATURE_AVX512VBMI);
+ if (ecx & bit_AVX512VBMI2)
+ set_feature (FEATURE_AVX512VBMI2);
+ if (ecx & bit_AVX512VNNI)
+ set_feature (FEATURE_AVX512VNNI);
+ if (ecx & bit_AVX512BITALG)
+ set_feature (FEATURE_AVX512BITALG);
+ if (ecx & bit_AVX512VPOPCNTDQ)
+ set_feature (FEATURE_AVX512VPOPCNTDQ);
+ if (edx & bit_AVX5124VNNIW)
+ set_feature (FEATURE_AVX5124VNNIW);
+ if (edx & bit_AVX5124FMAPS)
+ set_feature (FEATURE_AVX5124FMAPS);
+ if (edx & bit_AVX512VP2INTERSECT)
+ set_feature (FEATURE_AVX512VP2INTERSECT);
+
+ __cpuid_count (7, 1, eax, ebx, ecx, edx);
+ if (eax & bit_AVX512BF16)
+ set_feature (FEATURE_AVX512BF16);
+ }
+ }
+
+ /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
+ if (max_cpuid_level >= 0xd)
+ {
+ __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
+ if (eax & bit_XSAVEOPT)
+ set_feature (FEATURE_XSAVEOPT);
+ if (eax & bit_XSAVEC)
+ set_feature (FEATURE_XSAVEC);
+ if (eax & bit_XSAVES)
+ set_feature (FEATURE_XSAVES);
+ }
+
+ /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
+ if (max_cpuid_level >= 0x14)
+ {
+ __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
+ if (ebx & bit_PTWRITE)
+ set_feature (FEATURE_PTWRITE);
+ }
+
+ /* Check cpuid level of extended features. */
+ __cpuid (0x80000000, ext_level, ebx, ecx, edx);
+
+ cpu_model2->__cpu_ext_level = ext_level;
+
+ if (ext_level >= 0x80000001)
+ {
+ __cpuid (0x80000001, eax, ebx, ecx, edx);
+
+ if (ecx & bit_SSE4a)
+ set_feature (FEATURE_SSE4_A);
+ if (ecx & bit_LAHF_LM)
+ set_feature (FEATURE_LAHF_LM);
+ if (ecx & bit_ABM)
+ set_feature (FEATURE_ABM);
+ if (ecx & bit_LWP)
+ set_feature (FEATURE_LWP);
+ if (ecx & bit_TBM)
+ set_feature (FEATURE_TBM);
+ if (ecx & bit_LZCNT)
+ set_feature (FEATURE_LZCNT);
+ if (ecx & bit_PRFCHW)
+ set_feature (FEATURE_PRFCHW);
+ if (ecx & bit_MWAITX)
+ set_feature (FEATURE_MWAITX);
+
+ if (edx & bit_LM)
+ set_feature (FEATURE_LM);
+ if (edx & bit_3DNOWP)
+ set_feature (FEATURE_3DNOWP);
+ if (edx & bit_3DNOW)
+ set_feature (FEATURE_3DNOW);
+
+ if (avx_usable)
+ {
+ if (ecx & bit_FMA4)
+ set_feature (FEATURE_FMA4);
+ if (ecx & bit_XOP)
+ set_feature (FEATURE_XOP);
+ }
+ }
+
+ if (ext_level >= 0x80000008)
+ {
+ __cpuid (0x80000008, eax, ebx, ecx, edx);
+ if (ebx & bit_CLZERO)
+ set_feature (FEATURE_CLZERO);
+ if (ebx & bit_WBNOINVD)
+ set_feature (FEATURE_WBNOINVD);
+ }
+
+#undef set_feature
+}
+
+static inline int
+cpu_indicator_init (struct __processor_model *cpu_model,
+ struct __processor_model2 *cpu_model2,
+ unsigned int *cpu_features2)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ int max_level;
+ unsigned int vendor;
+ unsigned int model, family, brand_id;
+ unsigned int extended_model, extended_family;
+
+ /* This function needs to run just once. */
+ if (cpu_model->__cpu_vendor)
+ return 0;
+
+ /* Assume cpuid insn present. Run in level 0 to get vendor id. */
+ if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
+ {
+ cpu_model->__cpu_vendor = VENDOR_OTHER;
+ return -1;
+ }
+
+ vendor = ebx;
+ max_level = eax;
+
+ if (max_level < 1)
+ {
+ cpu_model->__cpu_vendor = VENDOR_OTHER;
+ return -1;
+ }
+
+ if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ {
+ cpu_model->__cpu_vendor = VENDOR_OTHER;
+ return -1;
+ }
+
+ cpu_model2->__cpu_max_level = max_level;
+
+ model = (eax >> 4) & 0x0f;
+ family = (eax >> 8) & 0x0f;
+ brand_id = ebx & 0xff;
+ extended_model = (eax >> 12) & 0xf0;
+ extended_family = (eax >> 20) & 0xff;
+
+ if (vendor == signature_INTEL_ebx)
+ {
+ /* Adjust model and family for Intel CPUS. */
+ if (family == 0x0f)
+ {
+ family += extended_family;
+ model += extended_model;
+ }
+ else if (family == 0x06)
+ model += extended_model;
+
+ cpu_model2->__cpu_family = family;
+ cpu_model2->__cpu_model = model;
+
+ /* Find available features. */
+ get_available_features (cpu_model, cpu_model2, cpu_features2,
+ ecx, edx);
+ /* Get CPU type. */
+ get_intel_cpu (cpu_model, cpu_model2, cpu_features2, brand_id);
+ cpu_model->__cpu_vendor = VENDOR_INTEL;
+ }
+ else if (vendor == signature_AMD_ebx)
+ {
+ /* Adjust model and family for AMD CPUS. */
+ if (family == 0x0f)
+ {
+ family += extended_family;
+ model += extended_model;
+ }
+
+ cpu_model2->__cpu_family = family;
+ cpu_model2->__cpu_model = model;
+
+ /* Find available features. */
+ get_available_features (cpu_model, cpu_model2, cpu_features2,
+ ecx, edx);
+ /* Get CPU type. */
+ get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
+ cpu_model->__cpu_vendor = VENDOR_AMD;
+ }
+ else if (vendor == signature_CENTAUR_ebx)
+ cpu_model->__cpu_vendor = VENDOR_CENTAUR;
+ else if (vendor == signature_CYRIX_ebx)
+ cpu_model->__cpu_vendor = VENDOR_CYRIX;
+ else if (vendor == signature_NSC_ebx)
+ cpu_model->__cpu_vendor = VENDOR_NSC;
+ else
+ cpu_model->__cpu_vendor = VENDOR_OTHER;
+
+ gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
+ gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
+ gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
+
+ return 0;
+}
@@ -28,6 +28,7 @@ const char *host_detect_local_cpu (int argc, const char **argv);
#if defined(__GNUC__) && (__GNUC__ >= 5 || !defined(__PIC__))
#include "cpuid.h"
+#include "common/config/i386/cpuinfo.h"
struct cache_desc
{
@@ -388,7 +389,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
const char *cache = "";
const char *options = "";
- unsigned int eax, ebx, ecx, edx;
+ unsigned int ebx, ecx, edx;
unsigned int max_level, ext_level;
@@ -399,41 +400,40 @@ const char *host_detect_local_cpu (int argc, const char **argv)
unsigned int has_cmpxchg8b, has_cmov, has_mmx, has_sse, has_sse2;
/* Extended features */
- unsigned int has_lahf_lm = 0, has_sse4a = 0;
- unsigned int has_longmode = 0, has_3dnowp = 0, has_3dnow = 0;
- unsigned int has_movbe = 0, has_sse4_1 = 0, has_sse4_2 = 0;
- unsigned int has_popcnt = 0, has_aes = 0, has_avx = 0, has_avx2 = 0;
- unsigned int has_pclmul = 0, has_abm = 0, has_lwp = 0;
- unsigned int has_fma = 0, has_fma4 = 0, has_xop = 0;
- unsigned int has_bmi = 0, has_bmi2 = 0, has_tbm = 0, has_lzcnt = 0;
- unsigned int has_hle = 0, has_rtm = 0, has_sgx = 0;
- unsigned int has_pconfig = 0, has_wbnoinvd = 0;
- unsigned int has_rdrnd = 0, has_f16c = 0, has_fsgsbase = 0;
- unsigned int has_rdseed = 0, has_prfchw = 0, has_adx = 0;
- unsigned int has_osxsave = 0, has_fxsr = 0, has_xsave = 0, has_xsaveopt = 0;
- unsigned int has_avx512er = 0, has_avx512pf = 0, has_avx512cd = 0;
- unsigned int has_avx512f = 0, has_sha = 0, has_prefetchwt1 = 0;
- unsigned int has_clflushopt = 0, has_xsavec = 0, has_xsaves = 0;
- unsigned int has_avx512dq = 0, has_avx512bw = 0, has_avx512vl = 0;
- unsigned int has_avx512vbmi = 0, has_avx512ifma = 0, has_clwb = 0;
- unsigned int has_mwaitx = 0, has_clzero = 0, has_pku = 0, has_rdpid = 0;
- unsigned int has_avx5124fmaps = 0, has_avx5124vnniw = 0;
- unsigned int has_gfni = 0, has_avx512vbmi2 = 0;
- unsigned int has_avx512bitalg = 0;
- unsigned int has_avx512vpopcntdq = 0;
- unsigned int has_shstk = 0;
- unsigned int has_avx512vnni = 0, has_vaes = 0;
- unsigned int has_vpclmulqdq = 0;
- unsigned int has_avx512vp2intersect = 0;
- unsigned int has_movdiri = 0, has_movdir64b = 0;
- unsigned int has_enqcmd = 0;
- unsigned int has_waitpkg = 0;
- unsigned int has_cldemote = 0;
- unsigned int has_avx512bf16 = 0;
- unsigned int has_serialize = 0;
- unsigned int has_tsxldtrk = 0;
-
- unsigned int has_ptwrite = 0;
+ unsigned int has_lahf_lm, has_sse4a;
+ unsigned int has_longmode, has_3dnowp, has_3dnow;
+ unsigned int has_movbe, has_sse4_1, has_sse4_2;
+ unsigned int has_popcnt, has_aes, has_avx, has_avx2;
+ unsigned int has_pclmul, has_abm, has_lwp;
+ unsigned int has_fma, has_fma4, has_xop;
+ unsigned int has_bmi, has_bmi2, has_tbm, has_lzcnt;
+ unsigned int has_hle, has_rtm, has_sgx;
+ unsigned int has_pconfig, has_wbnoinvd;
+ unsigned int has_rdrnd, has_f16c, has_fsgsbase;
+ unsigned int has_rdseed, has_prfchw, has_adx;
+ unsigned int has_fxsr, has_xsave, has_xsaveopt;
+ unsigned int has_avx512er, has_avx512pf, has_avx512cd;
+ unsigned int has_avx512f, has_sha, has_prefetchwt1;
+ unsigned int has_clflushopt, has_xsavec, has_xsaves;
+ unsigned int has_avx512dq, has_avx512bw, has_avx512vl;
+ unsigned int has_avx512vbmi, has_avx512ifma, has_clwb;
+ unsigned int has_mwaitx, has_clzero, has_pku, has_rdpid;
+ unsigned int has_avx5124fmaps, has_avx5124vnniw;
+ unsigned int has_gfni, has_avx512vbmi2;
+ unsigned int has_avx512bitalg;
+ unsigned int has_avx512vpopcntdq;
+ unsigned int has_shstk;
+ unsigned int has_avx512vnni, has_vaes;
+ unsigned int has_vpclmulqdq;
+ unsigned int has_avx512vp2intersect;
+ unsigned int has_movdiri, has_movdir64b;
+ unsigned int has_enqcmd;
+ unsigned int has_waitpkg;
+ unsigned int has_cldemote;
+ unsigned int has_avx512bf16;
+ unsigned int has_serialize;
+ unsigned int has_tsxldtrk;
+ unsigned int has_ptwrite;
bool arch;
@@ -447,210 +447,114 @@ const char *host_detect_local_cpu (int argc, const char **argv)
if (!arch && strcmp (argv[0], "tune"))
return NULL;
- max_level = __get_cpuid_max (0, &vendor);
- if (max_level < 1)
- goto done;
-
- __cpuid (1, eax, ebx, ecx, edx);
-
- model = (eax >> 4) & 0x0f;
- family = (eax >> 8) & 0x0f;
- if (vendor == signature_INTEL_ebx
- || vendor == signature_AMD_ebx)
- {
- unsigned int extended_model, extended_family;
-
- extended_model = (eax >> 12) & 0xf0;
- extended_family = (eax >> 20) & 0xff;
- if (family == 0x0f)
- {
- family += extended_family;
- model += extended_model;
- }
- else if (family == 0x06)
- model += extended_model;
- }
-
- has_sse3 = ecx & bit_SSE3;
- has_ssse3 = ecx & bit_SSSE3;
- has_sse4_1 = ecx & bit_SSE4_1;
- has_sse4_2 = ecx & bit_SSE4_2;
- has_avx = ecx & bit_AVX;
- has_osxsave = ecx & bit_OSXSAVE;
- has_cmpxchg16b = ecx & bit_CMPXCHG16B;
- has_movbe = ecx & bit_MOVBE;
- has_popcnt = ecx & bit_POPCNT;
- has_aes = ecx & bit_AES;
- has_pclmul = ecx & bit_PCLMUL;
- has_fma = ecx & bit_FMA;
- has_f16c = ecx & bit_F16C;
- has_rdrnd = ecx & bit_RDRND;
- has_xsave = ecx & bit_XSAVE;
-
- has_cmpxchg8b = edx & bit_CMPXCHG8B;
- has_cmov = edx & bit_CMOV;
- has_mmx = edx & bit_MMX;
- has_fxsr = edx & bit_FXSAVE;
- has_sse = edx & bit_SSE;
- has_sse2 = edx & bit_SSE2;
-
- if (max_level >= 7)
- {
- __cpuid_count (7, 0, eax, ebx, ecx, edx);
-
- has_bmi = ebx & bit_BMI;
- has_sgx = ebx & bit_SGX;
- has_hle = ebx & bit_HLE;
- has_rtm = ebx & bit_RTM;
- has_avx2 = ebx & bit_AVX2;
- has_bmi2 = ebx & bit_BMI2;
- has_fsgsbase = ebx & bit_FSGSBASE;
- has_rdseed = ebx & bit_RDSEED;
- has_adx = ebx & bit_ADX;
- has_avx512f = ebx & bit_AVX512F;
- has_avx512er = ebx & bit_AVX512ER;
- has_avx512pf = ebx & bit_AVX512PF;
- has_avx512cd = ebx & bit_AVX512CD;
- has_sha = ebx & bit_SHA;
- has_clflushopt = ebx & bit_CLFLUSHOPT;
- has_clwb = ebx & bit_CLWB;
- has_avx512dq = ebx & bit_AVX512DQ;
- has_avx512bw = ebx & bit_AVX512BW;
- has_avx512vl = ebx & bit_AVX512VL;
- has_avx512ifma = ebx & bit_AVX512IFMA;
-
- has_prefetchwt1 = ecx & bit_PREFETCHWT1;
- has_avx512vbmi = ecx & bit_AVX512VBMI;
- has_pku = ecx & bit_OSPKE;
- has_avx512vbmi2 = ecx & bit_AVX512VBMI2;
- has_avx512vnni = ecx & bit_AVX512VNNI;
- has_rdpid = ecx & bit_RDPID;
- has_gfni = ecx & bit_GFNI;
- has_vaes = ecx & bit_VAES;
- has_vpclmulqdq = ecx & bit_VPCLMULQDQ;
- has_avx512bitalg = ecx & bit_AVX512BITALG;
- has_avx512vpopcntdq = ecx & bit_AVX512VPOPCNTDQ;
- has_movdiri = ecx & bit_MOVDIRI;
- has_movdir64b = ecx & bit_MOVDIR64B;
- has_enqcmd = ecx & bit_ENQCMD;
- has_cldemote = ecx & bit_CLDEMOTE;
-
- has_avx5124vnniw = edx & bit_AVX5124VNNIW;
- has_avx5124fmaps = edx & bit_AVX5124FMAPS;
- has_avx512vp2intersect = edx & bit_AVX512VP2INTERSECT;
- has_serialize = edx & bit_SERIALIZE;
- has_tsxldtrk = edx & bit_TSXLDTRK;
-
- has_shstk = ecx & bit_SHSTK;
- has_pconfig = edx & bit_PCONFIG;
- has_waitpkg = ecx & bit_WAITPKG;
-
- __cpuid_count (7, 1, eax, ebx, ecx, edx);
- has_avx512bf16 = eax & bit_AVX512BF16;
- }
-
- if (max_level >= 13)
- {
- __cpuid_count (13, 1, eax, ebx, ecx, edx);
-
- has_xsaveopt = eax & bit_XSAVEOPT;
- has_xsavec = eax & bit_XSAVEC;
- has_xsaves = eax & bit_XSAVES;
- }
-
- if (max_level >= 0x14)
- {
- __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
-
- has_ptwrite = ebx & bit_PTWRITE;
- }
+ struct __processor_model cpu_model = { };
+ struct __processor_model2 cpu_model2 = { };
+ unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { };
- /* Check cpuid level of extended features. */
- __cpuid (0x80000000, ext_level, ebx, ecx, edx);
-
- if (ext_level >= 0x80000001)
- {
- __cpuid (0x80000001, eax, ebx, ecx, edx);
-
- has_lahf_lm = ecx & bit_LAHF_LM;
- has_sse4a = ecx & bit_SSE4a;
- has_abm = ecx & bit_ABM;
- has_lwp = ecx & bit_LWP;
- has_fma4 = ecx & bit_FMA4;
- has_xop = ecx & bit_XOP;
- has_tbm = ecx & bit_TBM;
- has_lzcnt = ecx & bit_LZCNT;
- has_prfchw = ecx & bit_PRFCHW;
-
- has_longmode = edx & bit_LM;
- has_3dnowp = edx & bit_3DNOWP;
- has_3dnow = edx & bit_3DNOW;
- has_mwaitx = ecx & bit_MWAITX;
- }
-
- if (ext_level >= 0x80000008)
- {
- __cpuid (0x80000008, eax, ebx, ecx, edx);
- has_clzero = ebx & bit_CLZERO;
- has_wbnoinvd = ebx & bit_WBNOINVD;
- }
-
- /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
-#define XCR_XFEATURE_ENABLED_MASK 0x0
-#define XSTATE_FP 0x1
-#define XSTATE_SSE 0x2
-#define XSTATE_YMM 0x4
-#define XSTATE_OPMASK 0x20
-#define XSTATE_ZMM 0x40
-#define XSTATE_HI_ZMM 0x80
-
-#define XCR_AVX_ENABLED_MASK \
- (XSTATE_SSE | XSTATE_YMM)
-#define XCR_AVX512F_ENABLED_MASK \
- (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
-
- if (has_osxsave)
- asm (".byte 0x0f; .byte 0x01; .byte 0xd0"
- : "=a" (eax), "=d" (edx)
- : "c" (XCR_XFEATURE_ENABLED_MASK));
- else
- eax = 0;
+ if (cpu_indicator_init (&cpu_model, &cpu_model2, cpu_features2) != 0)
+ goto done;
- /* Check if AVX registers are supported. */
- if ((eax & XCR_AVX_ENABLED_MASK) != XCR_AVX_ENABLED_MASK)
- {
- has_avx = 0;
- has_avx2 = 0;
- has_fma = 0;
- has_fma4 = 0;
- has_f16c = 0;
- has_xop = 0;
- has_xsave = 0;
- has_xsaveopt = 0;
- has_xsaves = 0;
- has_xsavec = 0;
- }
+ vendor = cpu_model.__cpu_vendor;
+ family = cpu_model2.__cpu_family;
+ model = cpu_model2.__cpu_model;
+ max_level = cpu_model2.__cpu_max_level;
+ ext_level = cpu_model2.__cpu_ext_level;
- /* Check if AVX512F registers are supported. */
- if ((eax & XCR_AVX512F_ENABLED_MASK) != XCR_AVX512F_ENABLED_MASK)
- {
- has_avx512f = 0;
- has_avx512er = 0;
- has_avx512pf = 0;
- has_avx512cd = 0;
- has_avx512dq = 0;
- has_avx512bw = 0;
- has_avx512vl = 0;
- }
+ /* Extended features */
+#define has_feature(f) \
+ has_cpu_feature (&cpu_model, cpu_features2, f)
+ has_cmov = has_feature (FEATURE_CMOV);
+ has_mmx = has_feature (FEATURE_MMX);
+ has_popcnt = has_feature (FEATURE_POPCNT);
+ has_sse = has_feature (FEATURE_SSE);
+ has_sse2 = has_feature (FEATURE_SSE2);
+ has_sse3 = has_feature (FEATURE_SSE3);
+ has_ssse3 = has_feature (FEATURE_SSSE3);
+ has_sse4_1 = has_feature (FEATURE_SSE4_1);
+ has_sse4_2 = has_feature (FEATURE_SSE4_2);
+ has_avx = has_feature (FEATURE_AVX);
+ has_avx2 = has_feature (FEATURE_AVX2);
+ has_sse4a = has_feature (FEATURE_SSE4_A);
+ has_fma4 = has_feature (FEATURE_FMA4);
+ has_xop = has_feature (FEATURE_XOP);
+ has_fma = has_feature (FEATURE_FMA);
+ has_avx512f = has_feature (FEATURE_AVX512F);
+ has_bmi = has_feature (FEATURE_BMI);
+ has_bmi2 = has_feature (FEATURE_BMI2);
+ has_aes = has_feature (FEATURE_AES);
+ has_pclmul = has_feature (FEATURE_PCLMUL);
+ has_avx512vl = has_feature (FEATURE_AVX512VL);
+ has_avx512bw = has_feature (FEATURE_AVX512BW);
+ has_avx512dq = has_feature (FEATURE_AVX512DQ);
+ has_avx512cd = has_feature (FEATURE_AVX512CD);
+ has_avx512er = has_feature (FEATURE_AVX512ER);
+ has_avx512pf = has_feature (FEATURE_AVX512PF);
+ has_avx512vbmi = has_feature (FEATURE_AVX512VBMI);
+ has_avx512ifma = has_feature (FEATURE_AVX512IFMA);
+ has_avx5124vnniw = has_feature (FEATURE_AVX5124VNNIW);
+ has_avx5124fmaps = has_feature (FEATURE_AVX5124FMAPS);
+ has_avx512vpopcntdq = has_feature (FEATURE_AVX512VPOPCNTDQ);
+ has_avx512vbmi2 = has_feature (FEATURE_AVX512VBMI2);
+ has_gfni = has_feature (FEATURE_GFNI);
+ has_vpclmulqdq = has_feature (FEATURE_VPCLMULQDQ);
+ has_avx512vnni = has_feature (FEATURE_AVX512VNNI);
+ has_avx512bitalg = has_feature (FEATURE_AVX512BITALG);
+ has_avx512bf16 = has_feature (FEATURE_AVX512BF16);
+ has_avx512vp2intersect = has_feature (FEATURE_AVX512VP2INTERSECT);
+ has_3dnow = has_feature (FEATURE_3DNOW);
+ has_3dnowp = has_feature (FEATURE_3DNOWP);
+ has_adx = has_feature (FEATURE_ADX);
+ has_abm = has_feature (FEATURE_ABM);
+ has_cldemote = has_feature (FEATURE_CLDEMOTE);
+ has_clflushopt = has_feature (FEATURE_CLFLUSHOPT);
+ has_clwb = has_feature (FEATURE_CLWB);
+ has_clzero = has_feature (FEATURE_CLZERO);
+ has_cmpxchg16b = has_feature (FEATURE_CMPXCHG16B);
+ has_cmpxchg8b = has_feature (FEATURE_CMPXCHG8B);
+ has_enqcmd = has_feature (FEATURE_ENQCMD);
+ has_f16c = has_feature (FEATURE_F16C);
+ has_fsgsbase = has_feature (FEATURE_FSGSBASE);
+ has_fxsr = has_feature (FEATURE_FXSAVE);
+ has_hle = has_feature (FEATURE_HLE);
+ has_lahf_lm = has_feature (FEATURE_LAHF_LM);
+ has_longmode = has_feature (FEATURE_LM);
+ has_lwp = has_feature (FEATURE_LWP);
+ has_lzcnt = has_feature (FEATURE_LZCNT);
+ has_movbe = has_feature (FEATURE_MOVBE);
+ has_movdir64b = has_feature (FEATURE_MOVDIR64B);
+ has_movdiri = has_feature (FEATURE_MOVDIRI);
+ has_mwaitx = has_feature (FEATURE_MWAITX);
+ has_pconfig = has_feature (FEATURE_PCONFIG);
+ has_pku = has_feature (FEATURE_PKU);
+ has_prefetchwt1 = has_feature (FEATURE_PREFETCHWT1);
+ has_prfchw = has_feature (FEATURE_PRFCHW);
+ has_ptwrite = has_feature (FEATURE_PTWRITE);
+ has_rdpid = has_feature (FEATURE_RDPID);
+ has_rdrnd = has_feature (FEATURE_RDRND);
+ has_rdseed = has_feature (FEATURE_RDSEED);
+ has_rtm = has_feature (FEATURE_RTM);
+ has_serialize = has_feature (FEATURE_SERIALIZE);
+ has_sgx = has_feature (FEATURE_SGX);
+ has_sha = has_feature (FEATURE_SHA);
+ has_shstk = has_feature (FEATURE_SHSTK);
+ has_tbm = has_feature (FEATURE_TBM);
+ has_tsxldtrk = has_feature (FEATURE_TSXLDTRK);
+ has_vaes = has_feature (FEATURE_VAES);
+ has_waitpkg = has_feature (FEATURE_WAITPKG);
+ has_wbnoinvd = has_feature (FEATURE_WBNOINVD);
+ has_xsave = has_feature (FEATURE_XSAVE);
+ has_xsavec = has_feature (FEATURE_XSAVEC);
+ has_xsaveopt = has_feature (FEATURE_XSAVEOPT);
+ has_xsaves = has_feature (FEATURE_XSAVES);
if (!arch)
{
- if (vendor == signature_AMD_ebx
- || vendor == signature_CENTAUR_ebx
- || vendor == signature_CYRIX_ebx
- || vendor == signature_NSC_ebx)
+ if (vendor == VENDOR_AMD
+ || vendor == VENDOR_CENTAUR
+ || vendor == VENDOR_CYRIX
+ || vendor == VENDOR_NSC)
cache = detect_caches_amd (ext_level);
- else if (vendor == signature_INTEL_ebx)
+ else if (vendor == VENDOR_INTEL)
{
bool xeon_mp = (family == 15 && model == 6);
cache = detect_caches_intel (xeon_mp, max_level,
@@ -658,7 +562,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
}
}
- if (vendor == signature_AMD_ebx)
+ if (vendor == VENDOR_AMD)
{
unsigned int name;
@@ -668,36 +572,22 @@ const char *host_detect_local_cpu (int argc, const char **argv)
else
name = 0;
- if (name == signature_NSC_ebx)
- processor = PROCESSOR_GEODE;
- else if (has_movbe && family == 22)
- processor = PROCESSOR_BTVER2;
- else if (has_clwb)
- processor = PROCESSOR_ZNVER2;
- else if (has_clzero)
- processor = PROCESSOR_ZNVER1;
- else if (has_avx2)
- processor = PROCESSOR_BDVER4;
- else if (has_xsaveopt)
- processor = PROCESSOR_BDVER3;
- else if (has_bmi)
- processor = PROCESSOR_BDVER2;
- else if (has_xop)
- processor = PROCESSOR_BDVER1;
- else if (has_sse4a && has_ssse3)
- processor = PROCESSOR_BTVER1;
- else if (has_sse4a)
- processor = PROCESSOR_AMDFAM10;
- else if (has_sse2 || has_longmode)
- processor = PROCESSOR_K8;
- else if (has_3dnowp && family == 6)
- processor = PROCESSOR_ATHLON;
- else if (has_mmx)
- processor = PROCESSOR_K6;
- else
- processor = PROCESSOR_PENTIUM;
+ cpu = get_amd_cpu (&cpu_model, &cpu_model2, cpu_features2);
+ if (cpu == NULL)
+ {
+ if (name == signature_NSC_ebx)
+ processor = PROCESSOR_GEODE;
+ else if (has_sse2 || has_longmode)
+ processor = PROCESSOR_K8;
+ else if (has_3dnowp && family == 6)
+ processor = PROCESSOR_ATHLON;
+ else if (has_mmx)
+ processor = PROCESSOR_K6;
+ else
+ processor = PROCESSOR_PENTIUM;
+ }
}
- else if (vendor == signature_CENTAUR_ebx)
+ else if (vendor == VENDOR_CENTAUR)
{
processor = PROCESSOR_GENERIC;
@@ -749,7 +639,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
/* Default. */
break;
case PROCESSOR_I486:
- if (arch && vendor == signature_CENTAUR_ebx)
+ if (arch && vendor == VENDOR_CENTAUR)
{
if (model >= 6)
cpu = "c3";
@@ -769,145 +659,23 @@ const char *host_detect_local_cpu (int argc, const char **argv)
cpu = "pentium";
break;
case PROCESSOR_PENTIUMPRO:
- switch (model)
+ cpu = get_intel_cpu (&cpu_model, &cpu_model2, cpu_features2, 0);
+ if (cpu == NULL)
{
- case 0x1c:
- case 0x26:
- /* Bonnell. */
- cpu = "bonnell";
- break;
- case 0x37:
- case 0x4a:
- case 0x4d:
- case 0x5d:
- /* Silvermont. */
- case 0x4c:
- case 0x5a:
- case 0x75:
- /* Airmont. */
- cpu = "silvermont";
- break;
- case 0x5c:
- case 0x5f:
- /* Goldmont. */
- cpu = "goldmont";
- break;
- case 0x7a:
- /* Goldmont Plus. */
- cpu = "goldmont-plus";
- break;
- case 0x86:
- case 0x96:
- case 0x9c:
- /* Tremont. */
- cpu = "tremont";
- break;
- case 0x0f:
- /* Merom. */
- case 0x17:
- case 0x1d:
- /* Penryn. */
- cpu = "core2";
- break;
- case 0x1a:
- case 0x1e:
- case 0x1f:
- case 0x2e:
- /* Nehalem. */
- cpu = "nehalem";
- break;
- case 0x25:
- case 0x2c:
- case 0x2f:
- /* Westmere. */
- cpu = "westmere";
- break;
- case 0x2a:
- case 0x2d:
- /* Sandy Bridge. */
- cpu = "sandybridge";
- break;
- case 0x3a:
- case 0x3e:
- /* Ivy Bridge. */
- cpu = "ivybridge";
- break;
- case 0x3c:
- case 0x3f:
- case 0x45:
- case 0x46:
- /* Haswell. */
- cpu = "haswell";
- break;
- case 0x3d:
- case 0x47:
- case 0x4f:
- case 0x56:
- /* Broadwell. */
- cpu = "broadwell";
- break;
- case 0x4e:
- case 0x5e:
- /* Skylake. */
- case 0x8e:
- case 0x9e:
- /* Kaby Lake. */
- case 0xa5:
- case 0xa6:
- /* Comet Lake. */
- cpu = "skylake";
- break;
- case 0x55:
- if (has_avx512vnni)
- /* Cascade Lake. */
- cpu = "cascadelake";
- else
- /* Skylake with AVX-512. */
- cpu = "skylake-avx512";
- break;
- case 0x6a:
- case 0x6c:
- /* Ice Lake server. */
- cpu = "icelake-server";
- break;
- case 0x7e:
- case 0x7d:
- case 0x9d:
- /* Ice Lake client. */
- cpu = "icelake-client";
- break;
- case 0x8c:
- case 0x8d:
- /* Tiger Lake. */
- cpu = "tigerlake";
- break;
- case 0x57:
- /* Knights Landing. */
- cpu = "knl";
- break;
- case 0x66:
- /* Cannon Lake. */
- cpu = "cannonlake";
- break;
- case 0x85:
- /* Knights Mill. */
- cpu = "knm";
- break;
- default:
if (arch)
{
/* This is unknown family 0x6 CPU. */
if (has_avx)
- {
- /* Assume Tiger Lake */
- if (has_avx512vp2intersect)
- cpu = "tigerlake";
- /* Assume Cooper Lake */
- else if (has_avx512bf16)
- cpu = "cooperlake";
- /* Assume Ice Lake Server. */
- else if (has_wbnoinvd)
- cpu = "icelake-server";
+ {
+ /* Assume Tiger Lake */
+ if (has_avx512vp2intersect)
+ cpu = "tigerlake";
+ /* Assume Cooper Lake */
+ else if (has_avx512bf16)
+ cpu = "cooperlake";
+ /* Assume Ice Lake Server. */
+ else if (has_wbnoinvd)
+ cpu = "icelake-server";
/* Assume Ice Lake. */
else if (has_avx512bitalg)
cpu = "icelake-client";
@@ -970,7 +738,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
cpu = "x86-64";
else if (has_sse3)
{
- if (vendor == signature_CENTAUR_ebx)
+ if (vendor == VENDOR_CENTAUR)
/* C7 / Eden "Esther" */
cpu = "c7";
else
@@ -982,7 +750,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
cpu = "pentium-m";
else if (has_sse)
{
- if (vendor == signature_CENTAUR_ebx)
+ if (vendor == VENDOR_CENTAUR)
{
if (model >= 9)
/* Eden "Nehemiah" */
@@ -1004,7 +772,6 @@ const char *host_detect_local_cpu (int argc, const char **argv)
else
/* For -mtune, we default to -mtune=generic. */
cpu = "generic";
- break;
}
break;
case PROCESSOR_PENTIUM4:
@@ -1036,7 +803,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
case PROCESSOR_K8:
if (arch)
{
- if (vendor == signature_CENTAUR_ebx)
+ if (vendor == VENDOR_CENTAUR)
{
if (has_sse4_1)
/* Nano 3000 | Nano dual / quad core | Eden X4 */
@@ -1060,33 +827,6 @@ const char *host_detect_local_cpu (int argc, const char **argv)
/* For -mtune, we default to -mtune=k8 */
cpu = "k8";
break;
- case PROCESSOR_AMDFAM10:
- cpu = "amdfam10";
- break;
- case PROCESSOR_BDVER1:
- cpu = "bdver1";
- break;
- case PROCESSOR_BDVER2:
- cpu = "bdver2";
- break;
- case PROCESSOR_BDVER3:
- cpu = "bdver3";
- break;
- case PROCESSOR_BDVER4:
- cpu = "bdver4";
- break;
- case PROCESSOR_ZNVER1:
- cpu = "znver1";
- break;
- case PROCESSOR_ZNVER2:
- cpu = "znver2";
- break;
- case PROCESSOR_BTVER1:
- cpu = "btver1";
- break;
- case PROCESSOR_BTVER2:
- cpu = "btver2";
- break;
default:
/* Use something reasonable. */
@@ -90,6 +90,7 @@ along with GCC; see the file COPYING3. If not see
#include "debug.h"
#include "dwarf2out.h"
#include "i386-builtins.h"
+#include "common/config/i386/cpuinfo-builtins.h"
#undef BDESC
#undef BDESC_FIRST
@@ -1872,147 +1873,66 @@ enum feature_priority
P_PROC_AVX512F
};
-/* This is the order of bit-fields in __processor_features in cpuinfo.c */
-enum processor_features
-{
- F_CMOV = 0,
- F_MMX,
- F_POPCNT,
- F_SSE,
- F_SSE2,
- F_SSE3,
- F_SSSE3,
- F_SSE4_1,
- F_SSE4_2,
- F_AVX,
- F_AVX2,
- F_SSE4_A,
- F_FMA4,
- F_XOP,
- F_FMA,
- F_AVX512F,
- F_BMI,
- F_BMI2,
- F_AES,
- F_PCLMUL,
- F_AVX512VL,
- F_AVX512BW,
- F_AVX512DQ,
- F_AVX512CD,
- F_AVX512ER,
- F_AVX512PF,
- F_AVX512VBMI,
- F_AVX512IFMA,
- F_AVX5124VNNIW,
- F_AVX5124FMAPS,
- F_AVX512VPOPCNTDQ,
- F_AVX512VBMI2,
- F_GFNI,
- F_VPCLMULQDQ,
- F_AVX512VNNI,
- F_AVX512BITALG,
- F_AVX512BF16,
- F_AVX512VP2INTERSECT,
- F_MAX
-};
-
-/* These are the values for vendor types and cpu types and subtypes
- in cpuinfo.c. Cpu types and subtypes should be subtracted by
- the corresponding start value. */
-enum processor_model
-{
- M_INTEL = 1,
- M_AMD,
- M_CPU_TYPE_START,
- M_INTEL_BONNELL,
- M_INTEL_CORE2,
- M_INTEL_COREI7,
- M_AMDFAM10H,
- M_AMDFAM15H,
- M_INTEL_SILVERMONT,
- M_INTEL_KNL,
- M_AMD_BTVER1,
- M_AMD_BTVER2,
- M_AMDFAM17H,
- M_INTEL_KNM,
- M_INTEL_GOLDMONT,
- M_INTEL_GOLDMONT_PLUS,
- M_INTEL_TREMONT,
- M_CPU_SUBTYPE_START,
- M_INTEL_COREI7_NEHALEM,
- M_INTEL_COREI7_WESTMERE,
- M_INTEL_COREI7_SANDYBRIDGE,
- M_AMDFAM10H_BARCELONA,
- M_AMDFAM10H_SHANGHAI,
- M_AMDFAM10H_ISTANBUL,
- M_AMDFAM15H_BDVER1,
- M_AMDFAM15H_BDVER2,
- M_AMDFAM15H_BDVER3,
- M_AMDFAM15H_BDVER4,
- M_AMDFAM17H_ZNVER1,
- M_INTEL_COREI7_IVYBRIDGE,
- M_INTEL_COREI7_HASWELL,
- M_INTEL_COREI7_BROADWELL,
- M_INTEL_COREI7_SKYLAKE,
- M_INTEL_COREI7_SKYLAKE_AVX512,
- M_INTEL_COREI7_CANNONLAKE,
- M_INTEL_COREI7_ICELAKE_CLIENT,
- M_INTEL_COREI7_ICELAKE_SERVER,
- M_AMDFAM17H_ZNVER2,
- M_INTEL_COREI7_CASCADELAKE,
- M_INTEL_COREI7_TIGERLAKE,
- M_INTEL_COREI7_COOPERLAKE
-};
-
struct _arch_names_table
{
const char *const name;
- const enum processor_model model;
+ const int model;
};
+/* These are the values for vendor types, cpu types and subtypes in
+ cpuinfo.h. Cpu types and subtypes should be subtracted by the
+ corresponding start value. */
+
+#define M_CPU_TYPE_START (BUILTIN_VENDOR_MAX)
+#define M_CPU_SUBTYPE_START \
+ (M_CPU_TYPE_START + BUILTIN_CPU_TYPE_MAX)
+#define M_VENDOR(a) (a)
+#define M_CPU_TYPE(a) (M_CPU_TYPE_START + a)
+#define M_CPU_SUBTYPE(a) (M_CPU_SUBTYPE_START + a)
+
static const _arch_names_table arch_names_table[] =
{
- {"amd", M_AMD},
- {"intel", M_INTEL},
- {"atom", M_INTEL_BONNELL},
- {"slm", M_INTEL_SILVERMONT},
- {"core2", M_INTEL_CORE2},
- {"corei7", M_INTEL_COREI7},
- {"nehalem", M_INTEL_COREI7_NEHALEM},
- {"westmere", M_INTEL_COREI7_WESTMERE},
- {"sandybridge", M_INTEL_COREI7_SANDYBRIDGE},
- {"ivybridge", M_INTEL_COREI7_IVYBRIDGE},
- {"haswell", M_INTEL_COREI7_HASWELL},
- {"broadwell", M_INTEL_COREI7_BROADWELL},
- {"skylake", M_INTEL_COREI7_SKYLAKE},
- {"skylake-avx512", M_INTEL_COREI7_SKYLAKE_AVX512},
- {"cannonlake", M_INTEL_COREI7_CANNONLAKE},
- {"icelake-client", M_INTEL_COREI7_ICELAKE_CLIENT},
- {"icelake-server", M_INTEL_COREI7_ICELAKE_SERVER},
- {"cascadelake", M_INTEL_COREI7_CASCADELAKE},
- {"tigerlake", M_INTEL_COREI7_TIGERLAKE},
- {"cooperlake", M_INTEL_COREI7_COOPERLAKE},
- {"bonnell", M_INTEL_BONNELL},
- {"silvermont", M_INTEL_SILVERMONT},
- {"goldmont", M_INTEL_GOLDMONT},
- {"goldmont-plus", M_INTEL_GOLDMONT_PLUS},
- {"tremont", M_INTEL_TREMONT},
- {"knl", M_INTEL_KNL},
- {"knm", M_INTEL_KNM},
- {"amdfam10h", M_AMDFAM10H},
- {"barcelona", M_AMDFAM10H_BARCELONA},
- {"shanghai", M_AMDFAM10H_SHANGHAI},
- {"istanbul", M_AMDFAM10H_ISTANBUL},
- {"btver1", M_AMD_BTVER1},
- {"amdfam15h", M_AMDFAM15H},
- {"bdver1", M_AMDFAM15H_BDVER1},
- {"bdver2", M_AMDFAM15H_BDVER2},
- {"bdver3", M_AMDFAM15H_BDVER3},
- {"bdver4", M_AMDFAM15H_BDVER4},
- {"btver2", M_AMD_BTVER2},
- {"amdfam17h", M_AMDFAM17H},
- {"znver1", M_AMDFAM17H_ZNVER1},
- {"znver2", M_AMDFAM17H_ZNVER2},
+ {"amd", M_VENDOR (VENDOR_AMD)},
+ {"intel", M_VENDOR (VENDOR_INTEL)},
+ {"atom", M_CPU_TYPE (INTEL_BONNELL)},
+ {"slm", M_CPU_TYPE (INTEL_SILVERMONT)},
+ {"core2", M_CPU_TYPE (INTEL_CORE2)},
+ {"corei7", M_CPU_TYPE (INTEL_COREI7)},
+ {"nehalem", M_CPU_SUBTYPE (INTEL_COREI7_NEHALEM)},
+ {"westmere", M_CPU_SUBTYPE (INTEL_COREI7_WESTMERE)},
+ {"sandybridge", M_CPU_SUBTYPE (INTEL_COREI7_SANDYBRIDGE)},
+ {"ivybridge", M_CPU_SUBTYPE (INTEL_COREI7_IVYBRIDGE)},
+ {"haswell", M_CPU_SUBTYPE (INTEL_COREI7_HASWELL)},
+ {"broadwell", M_CPU_SUBTYPE (INTEL_COREI7_BROADWELL)},
+ {"skylake", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE)},
+ {"skylake-avx512", M_CPU_SUBTYPE (INTEL_COREI7_SKYLAKE_AVX512)},
+ {"cannonlake", M_CPU_SUBTYPE (INTEL_COREI7_CANNONLAKE)},
+ {"icelake-client", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_CLIENT)},
+ {"icelake-server", M_CPU_SUBTYPE (INTEL_COREI7_ICELAKE_SERVER)},
+ {"cascadelake", M_CPU_SUBTYPE (INTEL_COREI7_CASCADELAKE)},
+ {"tigerlake", M_CPU_SUBTYPE (INTEL_COREI7_TIGERLAKE)},
+ {"cooperlake", M_CPU_SUBTYPE (INTEL_COREI7_COOPERLAKE)},
+ {"bonnell", M_CPU_TYPE (INTEL_BONNELL)},
+ {"silvermont", M_CPU_TYPE (INTEL_SILVERMONT)},
+ {"goldmont", M_CPU_TYPE (INTEL_GOLDMONT)},
+ {"goldmont-plus", M_CPU_TYPE (INTEL_GOLDMONT_PLUS)},
+ {"tremont", M_CPU_TYPE (INTEL_TREMONT)},
+ {"knl", M_CPU_TYPE (INTEL_KNL)},
+ {"knm", M_CPU_TYPE (INTEL_KNM)},
+ {"amdfam10h", M_CPU_TYPE (AMDFAM10H)},
+ {"barcelona", M_CPU_SUBTYPE (AMDFAM10H_BARCELONA)},
+ {"shanghai", M_CPU_SUBTYPE (AMDFAM10H_SHANGHAI)},
+ {"istanbul", M_CPU_SUBTYPE (AMDFAM10H_ISTANBUL)},
+ {"btver1", M_CPU_TYPE (AMD_BTVER1)},
+ {"amdfam15h", M_CPU_TYPE (AMDFAM15H)},
+ {"bdver1", M_CPU_SUBTYPE (AMDFAM15H_BDVER1)},
+ {"bdver2", M_CPU_SUBTYPE (AMDFAM15H_BDVER2)},
+ {"bdver3", M_CPU_SUBTYPE (AMDFAM15H_BDVER3)},
+ {"bdver4", M_CPU_SUBTYPE (AMDFAM15H_BDVER4)},
+ {"btver2", M_CPU_TYPE (AMD_BTVER2)},
+ {"amdfam17h", M_CPU_TYPE (AMDFAM17H)},
+ {"znver1", M_CPU_SUBTYPE (AMDFAM17H_ZNVER1)},
+ {"znver2", M_CPU_SUBTYPE (AMDFAM17H_ZNVER2)},
};
/* These are the target attribute strings for which a dispatcher is
@@ -2026,44 +1946,92 @@ struct _isa_names_table
static const _isa_names_table isa_names_table[] =
{
- {"cmov", F_CMOV, P_ZERO},
- {"mmx", F_MMX, P_MMX},
- {"popcnt", F_POPCNT, P_POPCNT},
- {"sse", F_SSE, P_SSE},
- {"sse2", F_SSE2, P_SSE2},
- {"sse3", F_SSE3, P_SSE3},
- {"ssse3", F_SSSE3, P_SSSE3},
- {"sse4a", F_SSE4_A, P_SSE4_A},
- {"sse4.1", F_SSE4_1, P_SSE4_1},
- {"sse4.2", F_SSE4_2, P_SSE4_2},
- {"avx", F_AVX, P_AVX},
- {"fma4", F_FMA4, P_FMA4},
- {"xop", F_XOP, P_XOP},
- {"fma", F_FMA, P_FMA},
- {"avx2", F_AVX2, P_AVX2},
- {"avx512f", F_AVX512F, P_AVX512F},
- {"bmi", F_BMI, P_BMI},
- {"bmi2", F_BMI2, P_BMI2},
- {"aes", F_AES, P_AES},
- {"pclmul", F_PCLMUL, P_PCLMUL},
- {"avx512vl",F_AVX512VL, P_ZERO},
- {"avx512bw",F_AVX512BW, P_ZERO},
- {"avx512dq",F_AVX512DQ, P_ZERO},
- {"avx512cd",F_AVX512CD, P_ZERO},
- {"avx512er",F_AVX512ER, P_ZERO},
- {"avx512pf",F_AVX512PF, P_ZERO},
- {"avx512vbmi",F_AVX512VBMI, P_ZERO},
- {"avx512ifma",F_AVX512IFMA, P_ZERO},
- {"avx5124vnniw",F_AVX5124VNNIW, P_ZERO},
- {"avx5124fmaps",F_AVX5124FMAPS, P_ZERO},
- {"avx512vpopcntdq",F_AVX512VPOPCNTDQ, P_ZERO},
- {"avx512vbmi2", F_AVX512VBMI2, P_ZERO},
- {"gfni", F_GFNI, P_ZERO},
- {"vpclmulqdq", F_VPCLMULQDQ, P_ZERO},
- {"avx512vnni", F_AVX512VNNI, P_ZERO},
- {"avx512bitalg", F_AVX512BITALG, P_ZERO},
- {"avx512bf16", F_AVX512BF16, P_ZERO},
- {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_ZERO}
+ {"cmov", FEATURE_CMOV, P_ZERO},
+ {"mmx", FEATURE_MMX, P_MMX},
+ {"popcnt", FEATURE_POPCNT, P_POPCNT},
+ {"sse", FEATURE_SSE, P_SSE},
+ {"sse2", FEATURE_SSE2, P_SSE2},
+ {"sse3", FEATURE_SSE3, P_SSE3},
+ {"ssse3", FEATURE_SSSE3, P_SSSE3},
+ {"sse4a", FEATURE_SSE4_A, P_SSE4_A},
+ {"sse4.1", FEATURE_SSE4_1, P_SSE4_1},
+ {"sse4.2", FEATURE_SSE4_2, P_SSE4_2},
+ {"avx", FEATURE_AVX, P_AVX},
+ {"fma4", FEATURE_FMA4, P_FMA4},
+ {"xop", FEATURE_XOP, P_XOP},
+ {"fma", FEATURE_FMA, P_FMA},
+ {"avx2", FEATURE_AVX2, P_AVX2},
+ {"avx512f", FEATURE_AVX512F, P_AVX512F},
+ {"bmi", FEATURE_BMI, P_BMI},
+ {"bmi2", FEATURE_BMI2, P_BMI2},
+ {"aes", FEATURE_AES, P_AES},
+ {"pclmul", FEATURE_PCLMUL, P_PCLMUL},
+ {"avx512vl",FEATURE_AVX512VL, P_ZERO},
+ {"avx512bw",FEATURE_AVX512BW, P_ZERO},
+ {"avx512dq",FEATURE_AVX512DQ, P_ZERO},
+ {"avx512cd",FEATURE_AVX512CD, P_ZERO},
+ {"avx512er",FEATURE_AVX512ER, P_ZERO},
+ {"avx512pf",FEATURE_AVX512PF, P_ZERO},
+ {"avx512vbmi",FEATURE_AVX512VBMI, P_ZERO},
+ {"avx512ifma",FEATURE_AVX512IFMA, P_ZERO},
+ {"avx5124vnniw",FEATURE_AVX5124VNNIW, P_ZERO},
+ {"avx5124fmaps",FEATURE_AVX5124FMAPS, P_ZERO},
+ {"avx512vpopcntdq",FEATURE_AVX512VPOPCNTDQ, P_ZERO},
+ {"avx512vbmi2", FEATURE_AVX512VBMI2, P_ZERO},
+ {"gfni", FEATURE_GFNI, P_ZERO},
+ {"vpclmulqdq", FEATURE_VPCLMULQDQ, P_ZERO},
+ {"avx512vnni", FEATURE_AVX512VNNI, P_ZERO},
+ {"avx512bitalg", FEATURE_AVX512BITALG, P_ZERO},
+ {"avx512bf16", FEATURE_AVX512BF16, P_ZERO},
+ {"avx512vp2intersect",FEATURE_AVX512VP2INTERSECT, P_ZERO},
+ {"3dnow", FEATURE_3DNOW, P_ZERO},
+ {"3dnowp", FEATURE_3DNOWP, P_ZERO},
+ {"adx", FEATURE_ADX, P_ZERO},
+ {"abm", FEATURE_ABM, P_ZERO},
+ {"cldemote", FEATURE_CLDEMOTE, P_ZERO},
+ {"clflushopt", FEATURE_CLFLUSHOPT, P_ZERO},
+ {"clwb", FEATURE_CLWB, P_ZERO},
+ {"clzero", FEATURE_CLZERO, P_ZERO},
+ {"cmpxchg16b", FEATURE_CMPXCHG16B, P_ZERO},
+ {"cmpxchg8b", FEATURE_CMPXCHG8B, P_ZERO},
+ {"enqcmd", FEATURE_ENQCMD, P_ZERO},
+ {"f16c", FEATURE_F16C, P_ZERO},
+ {"fsgsbase", FEATURE_FSGSBASE, P_ZERO},
+ {"fxsave", FEATURE_FXSAVE, P_ZERO},
+ {"hle", FEATURE_HLE, P_ZERO},
+ {"ibt", FEATURE_IBT, P_ZERO},
+ {"lahf_lm", FEATURE_LAHF_LM, P_ZERO},
+ {"lm", FEATURE_LM, P_ZERO},
+ {"lwp", FEATURE_LWP, P_ZERO},
+ {"lzcnt", FEATURE_LZCNT, P_ZERO},
+ {"movbe", FEATURE_MOVBE, P_ZERO},
+ {"movdir64b", FEATURE_MOVDIR64B, P_ZERO},
+ {"movdiri", FEATURE_MOVDIRI, P_ZERO},
+ {"mwaitx", FEATURE_MWAITX, P_ZERO},
+ {"ospke", FEATURE_OSPKE, P_ZERO},
+ {"osxsave", FEATURE_OSXSAVE, P_ZERO},
+ {"pconfig", FEATURE_PCONFIG, P_ZERO},
+ {"pku", FEATURE_PKU, P_ZERO},
+ {"prefetchwt1", FEATURE_PREFETCHWT1, P_ZERO},
+ {"prfchw", FEATURE_PRFCHW, P_ZERO},
+ {"ptwrite", FEATURE_PTWRITE, P_ZERO},
+ {"rdpid", FEATURE_RDPID, P_ZERO},
+ {"rdrnd", FEATURE_RDRND, P_ZERO},
+ {"rdseed", FEATURE_RDSEED, P_ZERO},
+ {"rtm", FEATURE_RTM, P_ZERO},
+ {"serialize", FEATURE_SERIALIZE, P_ZERO},
+ {"sgx", FEATURE_SGX, P_ZERO},
+ {"sha", FEATURE_SHA, P_ZERO},
+ {"shstk", FEATURE_SHSTK, P_ZERO},
+ {"tbm", FEATURE_TBM, P_ZERO},
+ {"tsxldtrk", FEATURE_TSXLDTRK, P_ZERO},
+ {"vaes", FEATURE_VAES, P_ZERO},
+ {"waitpkg", FEATURE_WAITPKG, P_ZERO},
+ {"wbnoinvd", FEATURE_WBNOINVD, P_ZERO},
+ {"xsave", FEATURE_XSAVE, P_ZERO},
+ {"xsavec", FEATURE_XSAVEC, P_ZERO},
+ {"xsaveopt", FEATURE_XSAVEOPT, P_ZERO},
+ {"xsaves", FEATURE_XSAVES, P_ZERO}
};
/* This parses the attribute arguments to target in DECL and determines
@@ -2509,16 +2477,29 @@ fold_builtin_cpu (tree fndecl, tree *args)
if (isa_names_table[i].feature >= 32)
{
- tree __cpu_features2_var = make_var_decl (unsigned_type_node,
+ tree index_type
+ = build_index_type (size_int (SIZE_OF_CPU_FEATURES));
+ tree type = build_array_type (unsigned_type_node, index_type);
+ tree __cpu_features2_var = make_var_decl (type,
"__cpu_features2");
varpool_node::add (__cpu_features2_var);
- field_val = (1U << (isa_names_table[i].feature - 32));
- /* Return __cpu_features2 & field_val */
- final = build2 (BIT_AND_EXPR, unsigned_type_node,
- __cpu_features2_var,
- build_int_cstu (unsigned_type_node, field_val));
- return build1 (CONVERT_EXPR, integer_type_node, final);
+ for (unsigned int j = 0; j < SIZE_OF_CPU_FEATURES; j++)
+ if (isa_names_table[i].feature < (32 + 32 + j * 32))
+ {
+ field_val = (1U << (isa_names_table[i].feature
+ - (32 + j * 32)));
+ tree index = size_int (j);
+ array_elt = build4 (ARRAY_REF, unsigned_type_node,
+ __cpu_features2_var,
+ index, NULL_TREE, NULL_TREE);
+ /* Return __cpu_features2[index] & field_val */
+ final = build2 (BIT_AND_EXPR, unsigned_type_node,
+ array_elt,
+ build_int_cstu (unsigned_type_node,
+ field_val));
+ return build1 (CONVERT_EXPR, integer_type_node, final);
+ }
}
field = TYPE_FIELDS (__processor_model_type);
@@ -7,348 +7,220 @@
/* { dg-do run } */
#include <assert.h>
+#include <stdlib.h>
#include "cpuid.h"
-
-/* Check if the Intel CPU model and sub-model are identified. */
-static void
-check_intel_cpu_model (unsigned int family, unsigned int model,
- unsigned int brand_id)
-{
- /* Parse family and model only if brand ID is 0. */
- if (brand_id == 0)
- {
- switch (family)
- {
- case 0x5:
- /* Pentium. */
- break;
- case 0x6:
- switch (model)
- {
- case 0x1c:
- case 0x26:
- /* Atom. */
- assert (__builtin_cpu_is ("atom"));
- break;
- case 0x37:
- case 0x4a:
- case 0x4d:
- case 0x5a:
- case 0x5d:
- /* Silvermont. */
- assert (__builtin_cpu_is ("silvermont"));
- break;
- case 0x5c:
- case 0x5f:
- /* Goldmont. */
- assert (__builtin_cpu_is ("goldmont"));
- break;
- case 0x7a:
- /* Goldmont Plus. */
- assert (__builtin_cpu_is ("goldmont-plus"));
- break;
- case 0x57:
- /* Knights Landing. */
- assert (__builtin_cpu_is ("knl"));
- break;
- case 0x85:
- /* Knights Mill */
- assert (__builtin_cpu_is ("knm"));
- break;
- case 0x1a:
- case 0x1e:
- case 0x1f:
- case 0x2e:
- /* Nehalem. */
- assert (__builtin_cpu_is ("corei7"));
- assert (__builtin_cpu_is ("nehalem"));
- break;
- case 0x25:
- case 0x2c:
- case 0x2f:
- /* Westmere. */
- assert (__builtin_cpu_is ("corei7"));
- assert (__builtin_cpu_is ("westmere"));
- break;
- case 0x2a:
- case 0x2d:
- /* Sandy Bridge. */
- assert (__builtin_cpu_is ("corei7"));
- assert (__builtin_cpu_is ("sandybridge"));
- break;
- case 0x3a:
- case 0x3e:
- /* Ivy Bridge. */
- assert (__builtin_cpu_is ("corei7"));
- assert (__builtin_cpu_is ("ivybridge"));
- break;
- case 0x3c:
- case 0x3f:
- case 0x45:
- case 0x46:
- /* Haswell. */
- assert (__builtin_cpu_is ("corei7"));
- assert (__builtin_cpu_is ("haswell"));
- break;
- case 0x3d:
- case 0x47:
- case 0x4f:
- case 0x56:
- /* Broadwell. */
- assert (__builtin_cpu_is ("corei7"));
- assert (__builtin_cpu_is ("broadwell"));
- break;
- case 0x4e:
- case 0x5e:
- /* Skylake. */
- case 0x8e:
- case 0x9e:
- /* Kaby Lake. */
- assert (__builtin_cpu_is ("corei7"));
- assert (__builtin_cpu_is ("skylake"));
- break;
- case 0x55:
- {
- unsigned int eax, ebx, ecx, edx;
- __cpuid_count (7, 0, eax, ebx, ecx, edx);
- assert (__builtin_cpu_is ("corei7"));
- if (ecx & bit_AVX512VNNI)
- /* Cascade Lake. */
- assert (__builtin_cpu_is ("cascadelake"));
- else
- /* Skylake with AVX-512 support. */
- assert (__builtin_cpu_is ("skylake-avx512"));
- break;
- }
- case 0x66:
- /* Cannon Lake. */
- assert (__builtin_cpu_is ("cannonlake"));
- break;
- case 0x17:
- case 0x1d:
- /* Penryn. */
- case 0x0f:
- /* Merom. */
- assert (__builtin_cpu_is ("core2"));
- break;
- default:
- break;
- }
- break;
- default:
- /* We have no idea. */
- break;
- }
- }
-}
-
-/* Check if the AMD CPU model and sub-model are identified. */
-static void
-check_amd_cpu_model (unsigned int family, unsigned int model)
-{
- switch (family)
- {
- /* AMD Family 10h. */
- case 0x10:
- switch (model)
- {
- case 0x2:
- /* Barcelona. */
- assert (__builtin_cpu_is ("amdfam10h"));
- assert (__builtin_cpu_is ("barcelona"));
- break;
- case 0x4:
- /* Shanghai. */
- assert (__builtin_cpu_is ("amdfam10h"));
- assert (__builtin_cpu_is ("shanghai"));
- break;
- case 0x8:
- /* Istanbul. */
- assert (__builtin_cpu_is ("amdfam10h"));
- assert (__builtin_cpu_is ("istanbul"));
- break;
- default:
- break;
- }
- break;
- /* AMD Family 15h. */
- case 0x15:
- assert (__builtin_cpu_is ("amdfam15h"));
- /* Bulldozer version 1. */
- if ( model <= 0xf)
- assert (__builtin_cpu_is ("bdver1"));
- /* Bulldozer version 2. */
- if (model >= 0x10 && model <= 0x1f)
- assert (__builtin_cpu_is ("bdver2"));
- break;
- default:
- break;
- }
-}
+#define CHECK___builtin_cpu_is(cpu) assert (__builtin_cpu_is (cpu))
+#define gcc_assert(a) assert (a)
+#define gcc_unreachable() abort ()
+#define inline
+#include "../../../common/config/i386/cpuinfo.h"
/* Check if the ISA features are identified. */
static void
-check_features (unsigned int ecx, unsigned int edx,
- int max_cpuid_level)
+check_features (struct __processor_model *cpu_model,
+ unsigned int *cpu_features2)
{
- unsigned int eax, ebx;
- unsigned int ext_level;
+#define has_feature(f) \
+ has_cpu_feature (cpu_model, cpu_features2, f)
- if (edx & bit_CMOV)
+ if (has_feature (FEATURE_CMOV))
assert (__builtin_cpu_supports ("cmov"));
- if (edx & bit_MMX)
+ if (has_feature (FEATURE_MMX))
assert (__builtin_cpu_supports ("mmx"));
- if (edx & bit_SSE)
+ if (has_feature (FEATURE_POPCNT))
+ assert (__builtin_cpu_supports ("popcnt"));
+ if (has_feature (FEATURE_SSE))
assert (__builtin_cpu_supports ("sse"));
- if (edx & bit_SSE2)
+ if (has_feature (FEATURE_SSE2))
assert (__builtin_cpu_supports ("sse2"));
- if (ecx & bit_POPCNT)
- assert (__builtin_cpu_supports ("popcnt"));
- if (ecx & bit_AES)
- assert (__builtin_cpu_supports ("aes"));
- if (ecx & bit_PCLMUL)
- assert (__builtin_cpu_supports ("pclmul"));
- if (ecx & bit_SSE3)
+ if (has_feature (FEATURE_SSE3))
assert (__builtin_cpu_supports ("sse3"));
- if (ecx & bit_SSSE3)
+ if (has_feature (FEATURE_SSSE3))
assert (__builtin_cpu_supports ("ssse3"));
- if (ecx & bit_SSE4_1)
+ if (has_feature (FEATURE_SSE4_1))
assert (__builtin_cpu_supports ("sse4.1"));
- if (ecx & bit_SSE4_2)
+ if (has_feature (FEATURE_SSE4_2))
assert (__builtin_cpu_supports ("sse4.2"));
- if (ecx & bit_AVX)
+ if (has_feature (FEATURE_AVX))
assert (__builtin_cpu_supports ("avx"));
- if (ecx & bit_FMA)
+ if (has_feature (FEATURE_AVX2))
+ assert (__builtin_cpu_supports ("avx2"));
+ if (has_feature (FEATURE_SSE4_A))
+ assert (__builtin_cpu_supports ("sse4a"));
+ if (has_feature (FEATURE_FMA4))
+ assert (__builtin_cpu_supports ("fma4"));
+ if (has_feature (FEATURE_XOP))
+ assert (__builtin_cpu_supports ("xop"));
+ if (has_feature (FEATURE_FMA))
assert (__builtin_cpu_supports ("fma"));
-
- /* Get advanced features at level 7 (eax = 7, ecx = 0). */
- if (max_cpuid_level >= 7)
- {
- __cpuid_count (7, 0, eax, ebx, ecx, edx);
- if (ebx & bit_BMI)
- assert (__builtin_cpu_supports ("bmi"));
- if (ebx & bit_AVX2)
- assert (__builtin_cpu_supports ("avx2"));
- if (ebx & bit_BMI2)
- assert (__builtin_cpu_supports ("bmi2"));
- if (ebx & bit_AVX512F)
- assert (__builtin_cpu_supports ("avx512f"));
- if (ebx & bit_AVX512VL)
- assert (__builtin_cpu_supports ("avx512vl"));
- if (ebx & bit_AVX512BW)
- assert (__builtin_cpu_supports ("avx512bw"));
- if (ebx & bit_AVX512DQ)
- assert (__builtin_cpu_supports ("avx512dq"));
- if (ebx & bit_AVX512CD)
- assert (__builtin_cpu_supports ("avx512cd"));
- if (ebx & bit_AVX512PF)
- assert (__builtin_cpu_supports ("avx512pf"));
- if (ebx & bit_AVX512ER)
- assert (__builtin_cpu_supports ("avx512er"));
- if (ebx & bit_AVX512IFMA)
- assert (__builtin_cpu_supports ("avx512ifma"));
- if (ecx & bit_AVX512VBMI)
- assert (__builtin_cpu_supports ("avx512vbmi"));
- if (ecx & bit_AVX512VBMI2)
- assert (__builtin_cpu_supports ("avx512vbmi2"));
- if (ecx & bit_GFNI)
- assert (__builtin_cpu_supports ("gfni"));
- if (ecx & bit_VPCLMULQDQ)
- assert (__builtin_cpu_supports ("vpclmulqdq"));
- if (ecx & bit_AVX512VNNI)
- assert (__builtin_cpu_supports ("avx512vnni"));
- if (ecx & bit_AVX512BITALG)
- assert (__builtin_cpu_supports ("avx512bitalg"));
- if (ecx & bit_AVX512VPOPCNTDQ)
- assert (__builtin_cpu_supports ("avx512vpopcntdq"));
- if (edx & bit_AVX5124VNNIW)
- assert (__builtin_cpu_supports ("avx5124vnniw"));
- if (edx & bit_AVX5124FMAPS)
- assert (__builtin_cpu_supports ("avx5124fmaps"));
-
- __cpuid_count (7, 1, eax, ebx, ecx, edx);
- if (eax & bit_AVX512BF16)
- assert (__builtin_cpu_supports ("avx512bf16"));
- }
-
- /* Check cpuid level of extended features. */
- __cpuid (0x80000000, ext_level, ebx, ecx, edx);
-
- if (ext_level >= 0x80000001)
- {
- __cpuid (0x80000001, eax, ebx, ecx, edx);
-
- if (ecx & bit_SSE4a)
- assert (__builtin_cpu_supports ("sse4a"));
- if (ecx & bit_FMA4)
- assert (__builtin_cpu_supports ("fma4"));
- if (ecx & bit_XOP)
- assert (__builtin_cpu_supports ("xop"));
- }
-}
-
-static int __attribute__ ((noinline))
-__get_cpuid_output (unsigned int __level,
- unsigned int *__eax, unsigned int *__ebx,
- unsigned int *__ecx, unsigned int *__edx)
-{
- return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
+ if (has_feature (FEATURE_AVX512F))
+ assert (__builtin_cpu_supports ("avx512f"));
+ if (has_feature (FEATURE_BMI))
+ assert (__builtin_cpu_supports ("bmi"));
+ if (has_feature (FEATURE_BMI2))
+ assert (__builtin_cpu_supports ("bmi2"));
+ if (has_feature (FEATURE_AES))
+ assert (__builtin_cpu_supports ("aes"));
+ if (has_feature (FEATURE_PCLMUL))
+ assert (__builtin_cpu_supports ("pclmul"));
+ if (has_feature (FEATURE_AVX512VL))
+ assert (__builtin_cpu_supports ("avx512vl"));
+ if (has_feature (FEATURE_AVX512BW))
+ assert (__builtin_cpu_supports ("avx512bw"));
+ if (has_feature (FEATURE_AVX512DQ))
+ assert (__builtin_cpu_supports ("avx512dq"));
+ if (has_feature (FEATURE_AVX512CD))
+ assert (__builtin_cpu_supports ("avx512cd"));
+ if (has_feature (FEATURE_AVX512ER))
+ assert (__builtin_cpu_supports ("avx512er"));
+ if (has_feature (FEATURE_AVX512PF))
+ assert (__builtin_cpu_supports ("avx512pf"));
+ if (has_feature (FEATURE_AVX512VBMI))
+ assert (__builtin_cpu_supports ("avx512vbmi"));
+ if (has_feature (FEATURE_AVX512IFMA))
+ assert (__builtin_cpu_supports ("avx512ifma"));
+ if (has_feature (FEATURE_AVX5124VNNIW))
+ assert (__builtin_cpu_supports ("avx5124vnniw"));
+ if (has_feature (FEATURE_AVX5124FMAPS))
+ assert (__builtin_cpu_supports ("avx5124fmaps"));
+ if (has_feature (FEATURE_AVX512VPOPCNTDQ))
+ assert (__builtin_cpu_supports ("avx512vpopcntdq"));
+ if (has_feature (FEATURE_AVX512VBMI2))
+ assert (__builtin_cpu_supports ("avx512vbmi2"));
+ if (has_feature (FEATURE_GFNI))
+ assert (__builtin_cpu_supports ("gfni"));
+ if (has_feature (FEATURE_VPCLMULQDQ))
+ assert (__builtin_cpu_supports ("vpclmulqdq"));
+ if (has_feature (FEATURE_AVX512VNNI))
+ assert (__builtin_cpu_supports ("avx512vnni"));
+ if (has_feature (FEATURE_AVX512BITALG))
+ assert (__builtin_cpu_supports ("avx512bitalg"));
+ if (has_feature (FEATURE_AVX512BF16))
+ assert (__builtin_cpu_supports ("avx512bf16"));
+ if (has_feature (FEATURE_AVX512VP2INTERSECT))
+ assert (__builtin_cpu_supports ("avx512vp2intersect"));
+ if (has_feature (FEATURE_3DNOW))
+ assert (__builtin_cpu_supports ("3dnow"));
+ if (has_feature (FEATURE_3DNOWP))
+ assert (__builtin_cpu_supports ("3dnowp"));
+ if (has_feature (FEATURE_ADX))
+ assert (__builtin_cpu_supports ("adx"));
+ if (has_feature (FEATURE_ABM))
+ assert (__builtin_cpu_supports ("abm"));
+ if (has_feature (FEATURE_CLDEMOTE))
+ assert (__builtin_cpu_supports ("cldemote"));
+ if (has_feature (FEATURE_CLFLUSHOPT))
+ assert (__builtin_cpu_supports ("clflushopt"));
+ if (has_feature (FEATURE_CLWB))
+ assert (__builtin_cpu_supports ("clwb"));
+ if (has_feature (FEATURE_CLZERO))
+ assert (__builtin_cpu_supports ("clzero"));
+ if (has_feature (FEATURE_CMPXCHG16B))
+ assert (__builtin_cpu_supports ("cmpxchg16b"));
+ if (has_feature (FEATURE_CMPXCHG8B))
+ assert (__builtin_cpu_supports ("cmpxchg8b"));
+ if (has_feature (FEATURE_ENQCMD))
+ assert (__builtin_cpu_supports ("enqcmd"));
+ if (has_feature (FEATURE_F16C))
+ assert (__builtin_cpu_supports ("f16c"));
+ if (has_feature (FEATURE_FSGSBASE))
+ assert (__builtin_cpu_supports ("fsgsbase"));
+ if (has_feature (FEATURE_FXSAVE))
+ assert (__builtin_cpu_supports ("fxsave"));
+ if (has_feature (FEATURE_HLE))
+ assert (__builtin_cpu_supports ("hle"));
+ if (has_feature (FEATURE_IBT))
+ assert (__builtin_cpu_supports ("ibt"));
+ if (has_feature (FEATURE_LAHF_LM))
+ assert (__builtin_cpu_supports ("lahf_lm"));
+ if (has_feature (FEATURE_LM))
+ assert (__builtin_cpu_supports ("lm"));
+ if (has_feature (FEATURE_LWP))
+ assert (__builtin_cpu_supports ("lwp"));
+ if (has_feature (FEATURE_LZCNT))
+ assert (__builtin_cpu_supports ("lzcnt"));
+ if (has_feature (FEATURE_MOVBE))
+ assert (__builtin_cpu_supports ("movbe"));
+ if (has_feature (FEATURE_MOVDIR64B))
+ assert (__builtin_cpu_supports ("movdir64b"));
+ if (has_feature (FEATURE_MOVDIRI))
+ assert (__builtin_cpu_supports ("movdiri"));
+ if (has_feature (FEATURE_MWAITX))
+ assert (__builtin_cpu_supports ("mwaitx"));
+ if (has_feature (FEATURE_OSPKE))
+ assert (__builtin_cpu_supports ("ospke"));
+ if (has_feature (FEATURE_OSXSAVE))
+ assert (__builtin_cpu_supports ("osxsave"));
+ if (has_feature (FEATURE_PCONFIG))
+ assert (__builtin_cpu_supports ("pconfig"));
+ if (has_feature (FEATURE_PKU))
+ assert (__builtin_cpu_supports ("pku"));
+ if (has_feature (FEATURE_PREFETCHWT1))
+ assert (__builtin_cpu_supports ("prefetchwt1"));
+ if (has_feature (FEATURE_PRFCHW))
+ assert (__builtin_cpu_supports ("prfchw"));
+ if (has_feature (FEATURE_PTWRITE))
+ assert (__builtin_cpu_supports ("ptwrite"));
+ if (has_feature (FEATURE_RDPID))
+ assert (__builtin_cpu_supports ("rdpid"));
+ if (has_feature (FEATURE_RDRND))
+ assert (__builtin_cpu_supports ("rdrnd"));
+ if (has_feature (FEATURE_RDSEED))
+ assert (__builtin_cpu_supports ("rdseed"));
+ if (has_feature (FEATURE_RTM))
+ assert (__builtin_cpu_supports ("rtm"));
+ if (has_feature (FEATURE_SERIALIZE))
+ assert (__builtin_cpu_supports ("serialize"));
+ if (has_feature (FEATURE_SGX))
+ assert (__builtin_cpu_supports ("sgx"));
+ if (has_feature (FEATURE_SHA))
+ assert (__builtin_cpu_supports ("sha"));
+ if (has_feature (FEATURE_SHSTK))
+ assert (__builtin_cpu_supports ("shstk"));
+ if (has_feature (FEATURE_TBM))
+ assert (__builtin_cpu_supports ("tbm"));
+ if (has_feature (FEATURE_TSXLDTRK))
+ assert (__builtin_cpu_supports ("tsxldtrk"));
+ if (has_feature (FEATURE_VAES))
+ assert (__builtin_cpu_supports ("vaes"));
+ if (has_feature (FEATURE_WAITPKG))
+ assert (__builtin_cpu_supports ("waitpkg"));
+ if (has_feature (FEATURE_WBNOINVD))
+ assert (__builtin_cpu_supports ("wbnoinvd"));
+ if (has_feature (FEATURE_XSAVE))
+ assert (__builtin_cpu_supports ("xsave"));
+ if (has_feature (FEATURE_XSAVEC))
+ assert (__builtin_cpu_supports ("xsavec"));
+ if (has_feature (FEATURE_XSAVEOPT))
+ assert (__builtin_cpu_supports ("xsaveopt"));
+ if (has_feature (FEATURE_XSAVES))
+ assert (__builtin_cpu_supports ("xsaves"));
}
static int
check_detailed ()
{
- unsigned int eax, ebx, ecx, edx;
-
- int max_level;
- unsigned int vendor;
- unsigned int model, family, brand_id;
- unsigned int extended_model, extended_family;
+ struct __processor_model cpu_model = { 0 };
+ struct __processor_model2 cpu_model2 = { 0 };
+ unsigned int cpu_features2[SIZE_OF_CPU_FEATURES] = { 0 };
- /* Assume cpuid insn present. Run in level 0 to get vendor id. */
- if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
+ if (cpu_indicator_init (&cpu_model, &cpu_model2, cpu_features2) != 0)
return 0;
- vendor = ebx;
- max_level = eax;
+ check_features (&cpu_model, cpu_features2);
- if (max_level < 1)
- return 0;
-
- if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
- return 0;
-
- model = (eax >> 4) & 0x0f;
- family = (eax >> 8) & 0x0f;
- brand_id = ebx & 0xff;
- extended_model = (eax >> 12) & 0xf0;
- extended_family = (eax >> 20) & 0xff;
-
- if (vendor == signature_INTEL_ebx)
+ switch (cpu_model.__cpu_vendor)
{
+ case VENDOR_INTEL:
assert (__builtin_cpu_is ("intel"));
- /* Adjust family and model for Intel CPUs. */
- if (family == 0x0f)
- {
- family += extended_family;
- model += extended_model;
- }
- else if (family == 0x06)
- model += extended_model;
- check_intel_cpu_model (family, model, brand_id);
- check_features (ecx, edx, max_level);
- }
- else if (vendor == signature_AMD_ebx)
- {
+ get_intel_cpu (&cpu_model, &cpu_model2, cpu_features2, 0);
+ break;
+ case VENDOR_AMD:
assert (__builtin_cpu_is ("amd"));
- /* Adjust model and family for AMD CPUS. */
- if (family == 0x0f)
- {
- family += extended_family;
- model += (extended_model << 4);
- }
- check_amd_cpu_model (family, model);
- check_features (ecx, edx, max_level);
+ get_amd_cpu (&cpu_model, &cpu_model2, cpu_features2);
+ break;
+ default:
+ break;
}
return 0;
@@ -26,7 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "cpuid.h"
#include "tsystem.h"
#include "auto-target.h"
-#include "cpuinfo.h"
+#include "common/config/i386/cpuinfo.h"
#ifdef HAVE_INIT_PRIORITY
#define CONSTRUCTOR_PRIORITY (101)
@@ -39,386 +39,14 @@ int __cpu_indicator_init (void)
struct __processor_model __cpu_model = { };
-#ifndef SHARED
/* We want to move away from __cpu_model in libgcc_s.so.1 and the
size of __cpu_model is part of ABI. So, new features that don't
fit into __cpu_model.__cpu_features[0] go into extra variables
- in libgcc.a only, preferrably hidden. */
-unsigned int __cpu_features2;
-#endif
-
-
-/* Get the specific type of AMD CPU. */
-
-static void
-get_amd_cpu (unsigned int family, unsigned int model)
-{
- switch (family)
- {
- /* AMD Family 10h. */
- case 0x10:
- __cpu_model.__cpu_type = AMDFAM10H;
- switch (model)
- {
- case 0x2:
- /* Barcelona. */
- __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
- break;
- case 0x4:
- /* Shanghai. */
- __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
- break;
- case 0x8:
- /* Istanbul. */
- __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
- break;
- default:
- break;
- }
- break;
- /* AMD Family 14h "btver1". */
- case 0x14:
- __cpu_model.__cpu_type = AMD_BTVER1;
- break;
- /* AMD Family 15h "Bulldozer". */
- case 0x15:
- __cpu_model.__cpu_type = AMDFAM15H;
-
- if (model == 0x2)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
- /* Bulldozer version 1. */
- else if (model <= 0xf)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
- /* Bulldozer version 2 "Piledriver" */
- else if (model <= 0x2f)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
- /* Bulldozer version 3 "Steamroller" */
- else if (model <= 0x4f)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
- /* Bulldozer version 4 "Excavator" */
- else if (model <= 0x7f)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
- break;
- /* AMD Family 16h "btver2" */
- case 0x16:
- __cpu_model.__cpu_type = AMD_BTVER2;
- break;
- case 0x17:
- __cpu_model.__cpu_type = AMDFAM17H;
- /* AMD family 17h version 1. */
- if (model <= 0x1f)
- __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
- if (model >= 0x30)
- __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
- break;
- default:
- break;
- }
-}
-
-/* Get the specific type of Intel CPU. */
-
-static void
-get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
-{
- /* Parse family and model only if brand ID is 0. */
- if (brand_id == 0)
- {
- switch (family)
- {
- case 0x5:
- /* Pentium. */
- break;
- case 0x6:
- switch (model)
- {
- case 0x1c:
- case 0x26:
- /* Bonnell. */
- __cpu_model.__cpu_type = INTEL_BONNELL;
- break;
- case 0x37:
- case 0x4a:
- case 0x4d:
- case 0x5a:
- case 0x5d:
- /* Silvermont. */
- __cpu_model.__cpu_type = INTEL_SILVERMONT;
- break;
- case 0x5c:
- case 0x5f:
- /* Goldmont. */
- __cpu_model.__cpu_type = INTEL_GOLDMONT;
- break;
- case 0x7a:
- /* Goldmont Plus. */
- __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
- break;
- case 0x57:
- /* Knights Landing. */
- __cpu_model.__cpu_type = INTEL_KNL;
- break;
- case 0x85:
- /* Knights Mill. */
- __cpu_model.__cpu_type = INTEL_KNM;
- break;
- case 0x1a:
- case 0x1e:
- case 0x1f:
- case 0x2e:
- /* Nehalem. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
- break;
- case 0x25:
- case 0x2c:
- case 0x2f:
- /* Westmere. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
- break;
- case 0x2a:
- case 0x2d:
- /* Sandy Bridge. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
- break;
- case 0x3a:
- case 0x3e:
- /* Ivy Bridge. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
- break;
- case 0x3c:
- case 0x3f:
- case 0x45:
- case 0x46:
- /* Haswell. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
- break;
- case 0x3d:
- case 0x47:
- case 0x4f:
- case 0x56:
- /* Broadwell. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
- break;
- case 0x4e:
- case 0x5e:
- /* Skylake. */
- case 0x8e:
- case 0x9e:
- /* Kaby Lake. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
- break;
- case 0x55:
- {
- unsigned int eax, ebx, ecx, edx;
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpuid_count (7, 0, eax, ebx, ecx, edx);
- if (ecx & bit_AVX512VNNI)
- /* Cascade Lake. */
- __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
- else
- /* Skylake with AVX-512 support. */
- __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
- }
- break;
- case 0x66:
- /* Cannon Lake. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
- break;
- case 0x17:
- case 0x1d:
- /* Penryn. */
- case 0x0f:
- /* Merom. */
- __cpu_model.__cpu_type = INTEL_CORE2;
- break;
- default:
- break;
- }
- break;
- default:
- /* We have no idea. */
- break;
- }
- }
-}
-
-/* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
- the max possible level of CPUID insn. */
-static void
-get_available_features (unsigned int ecx, unsigned int edx,
- int max_cpuid_level)
-{
- unsigned int eax, ebx;
- unsigned int ext_level;
-
- unsigned int features = 0;
- unsigned int features2 = 0;
-
- /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
-#define XCR_XFEATURE_ENABLED_MASK 0x0
-#define XSTATE_FP 0x1
-#define XSTATE_SSE 0x2
-#define XSTATE_YMM 0x4
-#define XSTATE_OPMASK 0x20
-#define XSTATE_ZMM 0x40
-#define XSTATE_HI_ZMM 0x80
-
-#define XCR_AVX_ENABLED_MASK \
- (XSTATE_SSE | XSTATE_YMM)
-#define XCR_AVX512F_ENABLED_MASK \
- (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
-
- /* Check if AVX and AVX512 are usable. */
- int avx_usable = 0;
- int avx512_usable = 0;
- if ((ecx & bit_OSXSAVE))
- {
- /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
- ZMM16-ZMM31 states are supported by OSXSAVE. */
- unsigned int xcrlow;
- unsigned int xcrhigh;
- asm (".byte 0x0f, 0x01, 0xd0"
- : "=a" (xcrlow), "=d" (xcrhigh)
- : "c" (XCR_XFEATURE_ENABLED_MASK));
- if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
- {
- avx_usable = 1;
- avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
- == XCR_AVX512F_ENABLED_MASK);
- }
- }
-
-#define set_feature(f) \
- do \
- { \
- if (f < 32) \
- features |= (1U << (f & 31)); \
- else \
- features2 |= (1U << ((f - 32) & 31)); \
- } \
- while (0)
-
- if (edx & bit_CMOV)
- set_feature (FEATURE_CMOV);
- if (edx & bit_MMX)
- set_feature (FEATURE_MMX);
- if (edx & bit_SSE)
- set_feature (FEATURE_SSE);
- if (edx & bit_SSE2)
- set_feature (FEATURE_SSE2);
- if (ecx & bit_POPCNT)
- set_feature (FEATURE_POPCNT);
- if (ecx & bit_AES)
- set_feature (FEATURE_AES);
- if (ecx & bit_PCLMUL)
- set_feature (FEATURE_PCLMUL);
- if (ecx & bit_SSE3)
- set_feature (FEATURE_SSE3);
- if (ecx & bit_SSSE3)
- set_feature (FEATURE_SSSE3);
- if (ecx & bit_SSE4_1)
- set_feature (FEATURE_SSE4_1);
- if (ecx & bit_SSE4_2)
- set_feature (FEATURE_SSE4_2);
- if (avx_usable)
- {
- if (ecx & bit_AVX)
- set_feature (FEATURE_AVX);
- if (ecx & bit_FMA)
- set_feature (FEATURE_FMA);
- }
-
- /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
- if (max_cpuid_level >= 7)
- {
- __cpuid_count (7, 0, eax, ebx, ecx, edx);
- if (ebx & bit_BMI)
- set_feature (FEATURE_BMI);
- if (avx_usable)
- {
- if (ebx & bit_AVX2)
- set_feature (FEATURE_AVX2);
- if (ecx & bit_VPCLMULQDQ)
- set_feature (FEATURE_VPCLMULQDQ);
- }
- if (ebx & bit_BMI2)
- set_feature (FEATURE_BMI2);
- if (ecx & bit_GFNI)
- set_feature (FEATURE_GFNI);
- if (avx512_usable)
- {
- if (ebx & bit_AVX512F)
- set_feature (FEATURE_AVX512F);
- if (ebx & bit_AVX512VL)
- set_feature (FEATURE_AVX512VL);
- if (ebx & bit_AVX512BW)
- set_feature (FEATURE_AVX512BW);
- if (ebx & bit_AVX512DQ)
- set_feature (FEATURE_AVX512DQ);
- if (ebx & bit_AVX512CD)
- set_feature (FEATURE_AVX512CD);
- if (ebx & bit_AVX512PF)
- set_feature (FEATURE_AVX512PF);
- if (ebx & bit_AVX512ER)
- set_feature (FEATURE_AVX512ER);
- if (ebx & bit_AVX512IFMA)
- set_feature (FEATURE_AVX512IFMA);
- if (ecx & bit_AVX512VBMI)
- set_feature (FEATURE_AVX512VBMI);
- if (ecx & bit_AVX512VBMI2)
- set_feature (FEATURE_AVX512VBMI2);
- if (ecx & bit_AVX512VNNI)
- set_feature (FEATURE_AVX512VNNI);
- if (ecx & bit_AVX512BITALG)
- set_feature (FEATURE_AVX512BITALG);
- if (ecx & bit_AVX512VPOPCNTDQ)
- set_feature (FEATURE_AVX512VPOPCNTDQ);
- if (edx & bit_AVX5124VNNIW)
- set_feature (FEATURE_AVX5124VNNIW);
- if (edx & bit_AVX5124FMAPS)
- set_feature (FEATURE_AVX5124FMAPS);
- if (edx & bit_AVX512VP2INTERSECT)
- set_feature (FEATURE_AVX512VP2INTERSECT);
+ in libgcc.a only, preferably hidden.
- __cpuid_count (7, 1, eax, ebx, ecx, edx);
- if (eax & bit_AVX512BF16)
- set_feature (FEATURE_AVX512BF16);
- }
- }
-
- /* Check cpuid level of extended features. */
- __cpuid (0x80000000, ext_level, ebx, ecx, edx);
-
- if (ext_level >= 0x80000001)
- {
- __cpuid (0x80000001, eax, ebx, ecx, edx);
-
- if (ecx & bit_SSE4a)
- set_feature (FEATURE_SSE4_A);
- if (avx_usable)
- {
- if (ecx & bit_FMA4)
- set_feature (FEATURE_FMA4);
- if (ecx & bit_XOP)
- set_feature (FEATURE_XOP);
- }
- }
-
- __cpu_model.__cpu_features[0] = features;
-#ifndef SHARED
- __cpu_features2 = features2;
-#else
- (void) features2;
-#endif
-}
+ NB: Since older 386-builtins.c accesses __cpu_features2 as scalar or
+ smaller array, it can only access the first few elements. */
+unsigned int __cpu_features2[SIZE_OF_CPU_FEATURES];
/* A constructor function that is sets __cpu_model and __cpu_features with
the right values. This needs to run only once. This constructor is
@@ -429,85 +57,9 @@ get_available_features (unsigned int ecx, unsigned int edx,
int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
__cpu_indicator_init (void)
{
- unsigned int eax, ebx, ecx, edx;
-
- int max_level;
- unsigned int vendor;
- unsigned int model, family, brand_id;
- unsigned int extended_model, extended_family;
-
- /* This function needs to run just once. */
- if (__cpu_model.__cpu_vendor)
- return 0;
-
- /* Assume cpuid insn present. Run in level 0 to get vendor id. */
- if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
- {
- __cpu_model.__cpu_vendor = VENDOR_OTHER;
- return -1;
- }
-
- vendor = ebx;
- max_level = eax;
-
- if (max_level < 1)
- {
- __cpu_model.__cpu_vendor = VENDOR_OTHER;
- return -1;
- }
-
- if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
- {
- __cpu_model.__cpu_vendor = VENDOR_OTHER;
- return -1;
- }
-
- model = (eax >> 4) & 0x0f;
- family = (eax >> 8) & 0x0f;
- brand_id = ebx & 0xff;
- extended_model = (eax >> 12) & 0xf0;
- extended_family = (eax >> 20) & 0xff;
-
- if (vendor == signature_INTEL_ebx)
- {
- /* Adjust model and family for Intel CPUS. */
- if (family == 0x0f)
- {
- family += extended_family;
- model += extended_model;
- }
- else if (family == 0x06)
- model += extended_model;
-
- /* Get CPU type. */
- get_intel_cpu (family, model, brand_id);
- /* Find available features. */
- get_available_features (ecx, edx, max_level);
- __cpu_model.__cpu_vendor = VENDOR_INTEL;
- }
- else if (vendor == signature_AMD_ebx)
- {
- /* Adjust model and family for AMD CPUS. */
- if (family == 0x0f)
- {
- family += extended_family;
- model += extended_model;
- }
-
- /* Get CPU type. */
- get_amd_cpu (family, model);
- /* Find available features. */
- get_available_features (ecx, edx, max_level);
- __cpu_model.__cpu_vendor = VENDOR_AMD;
- }
- else
- __cpu_model.__cpu_vendor = VENDOR_OTHER;
-
- gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
- gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
- gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
-
- return 0;
+ struct __processor_model2 cpu_model2;
+ return cpu_indicator_init (&__cpu_model, &cpu_model2,
+ __cpu_features2);
}
#if defined SHARED && defined USE_ELF_SYMVER
--
2.26.2