x86: Move cpuinfo.h from libgcc to common/config/i386
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 18 May 2020 12:58:41 +0000 (05:58 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 24 Jun 2020 12:47:34 +0000 (05:47 -0700)
Both x86 backend and libgcc define enum processor_features.  libgcc sets
enum processor_feature and x86 backend checks enum processor_feature.
They are very easy out of sync and it has happened multiple times in the
past.

1. Move cpuinfo.h from libgcc to common/config/i386 so that we can share
the same enum processor_features in x86 backend and libgcc.
2. Change __cpu_features2 to an array to support more processor features.
3. Add more processor features to enum processor_features.

gcc/

PR target/95259
* common/config/i386/cpuinfo.h: New file.
(__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_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.
* common/config/i386/i386-cpuinfo.h (processor_vendor): Add
Add VENDOR_CENTAUR, VENDOR_CYRIX and VENDOR_NSC.
(processor_features): Moved from gcc/config/i386/i386-builtins.c.
Renamed F_XXX to FEATURE_XXX.  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_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.
(SIZE_OF_CPU_FEATURES): New.
* config/i386/i386-builtins.c (processor_features): Removed.
(isa_names_table): Replace F_XXX with FEATURE_XXX.
(fold_builtin_cpu): Change __cpu_features2 to an array.

libgcc/

PR target/95259
* config/i386/cpuinfo.c: Don't include "cpuinfo.h".  Include
"common/config/i386/i386-cpuinfo.h" and
"common/config/i386/cpuinfo.h".
(__cpu_features2): Changed to array.
(get_amd_cpu): Removed.
(get_intel_cpu): Likewise.
(get_available_features): Likewise.
(__cpu_indicator_init): Call cpu_indicator_init.
* config/i386/cpuinfo.h: Removed.

gcc/common/config/i386/cpuinfo.h [new file with mode: 0644]
gcc/common/config/i386/i386-cpuinfo.h
gcc/config/i386/i386-builtins.c
libgcc/config/i386/cpuinfo.c
libgcc/config/i386/cpuinfo.h [deleted file]

diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
new file mode 100644 (file)
index 0000000..2d72b3b
--- /dev/null
@@ -0,0 +1,844 @@
+/* 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/>.  */
+
+struct __processor_model
+{
+  unsigned int __cpu_vendor;
+  unsigned int __cpu_type;
+  unsigned int __cpu_subtype;
+  /* The first 32 features are stored as bitmasks in __cpu_features.
+     The rest of features are stored as bitmasks in a separate array
+     of unsigned int.  */
+  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)
+    {
+      /* The first 32 features.  */
+      return cpu_model->__cpu_features[0] & (1U << (f & 31));
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  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)
+    {
+      /* The first 32 features.  */
+      cpu_model->__cpu_features[0] |= (1U << (f & 31));
+      return;
+    }
+  /* The rest of features.  cpu_features2[i] contains features from
+     (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
+  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);
+      /* NB: bit_OSPKE indicates that OS supports PKU.  */
+      if (ecx & bit_OSPKE)
+       set_feature (FEATURE_PKU);
+      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;
+}
index e11c68f..96cf0ea 100644 (file)
@@ -30,6 +30,9 @@ enum processor_vendor
   VENDOR_INTEL = 1,
   VENDOR_AMD,
   VENDOR_OTHER,
+  VENDOR_CENTAUR,
+  VENDOR_CYRIX,
+  VENDOR_NSC,
   BUILTIN_VENDOR_MAX = VENDOR_OTHER,
   VENDOR_MAX
 };
@@ -122,6 +125,101 @@ enum feature_priority
   P_PROC_DYNAMIC
 };
 
+/* ISA Features supported. New features have to be inserted at the end.  */
+
+enum processor_features
+{
+  FEATURE_CMOV = 0,
+  FEATURE_MMX,
+  FEATURE_POPCNT,
+  FEATURE_SSE,
+  FEATURE_SSE2,
+  FEATURE_SSE3,
+  FEATURE_SSSE3,
+  FEATURE_SSE4_1,
+  FEATURE_SSE4_2,
+  FEATURE_AVX,
+  FEATURE_AVX2,
+  FEATURE_SSE4_A,
+  FEATURE_FMA4,
+  FEATURE_XOP,
+  FEATURE_FMA,
+  FEATURE_AVX512F,
+  FEATURE_BMI,
+  FEATURE_BMI2,
+  FEATURE_AES,
+  FEATURE_PCLMUL,
+  FEATURE_AVX512VL,
+  FEATURE_AVX512BW,
+  FEATURE_AVX512DQ,
+  FEATURE_AVX512CD,
+  FEATURE_AVX512ER,
+  FEATURE_AVX512PF,
+  FEATURE_AVX512VBMI,
+  FEATURE_AVX512IFMA,
+  FEATURE_AVX5124VNNIW,
+  FEATURE_AVX5124FMAPS,
+  FEATURE_AVX512VPOPCNTDQ,
+  FEATURE_AVX512VBMI2,
+  FEATURE_GFNI,
+  FEATURE_VPCLMULQDQ,
+  FEATURE_AVX512VNNI,
+  FEATURE_AVX512BITALG,
+  FEATURE_AVX512BF16,
+  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_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
+};
+
+/* Size of __cpu_features2 array in libgcc/config/i386/cpuinfo.c.  */
+#define SIZE_OF_CPU_FEATURES ((CPU_FEATURE_MAX - 1) / 32)
+
 /* These are the values for vendor types, cpu types and subtypes.  Cpu
    types and subtypes should be subtracted by the corresponding start
    value.  */
index 6f6a832..57e709d 100644 (file)
@@ -1835,50 +1835,6 @@ ix86_builtin_reciprocal (tree fndecl)
     }
 }
 
-/* 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 target attribute strings for which a dispatcher is
    available, from fold_builtin_cpu.  */
 struct _isa_names_table
@@ -1890,44 +1846,44 @@ struct _isa_names_table
 
 static const _isa_names_table isa_names_table[] =
 {
-  {"cmov",    F_CMOV,  P_NONE},
-  {"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_NONE},
-  {"avx512bw",F_AVX512BW, P_NONE},
-  {"avx512dq",F_AVX512DQ, P_NONE},
-  {"avx512cd",F_AVX512CD, P_NONE},
-  {"avx512er",F_AVX512ER, P_NONE},
-  {"avx512pf",F_AVX512PF, P_NONE},
-  {"avx512vbmi",F_AVX512VBMI, P_NONE},
-  {"avx512ifma",F_AVX512IFMA, P_NONE},
-  {"avx5124vnniw",F_AVX5124VNNIW, P_NONE},
-  {"avx5124fmaps",F_AVX5124FMAPS, P_NONE},
-  {"avx512vpopcntdq",F_AVX512VPOPCNTDQ,        P_NONE},
-  {"avx512vbmi2", F_AVX512VBMI2, P_NONE},
-  {"gfni",     F_GFNI, P_NONE},
-  {"vpclmulqdq", F_VPCLMULQDQ, P_NONE},
-  {"avx512vnni", F_AVX512VNNI, P_NONE},
-  {"avx512bitalg", F_AVX512BITALG, P_NONE},
-  {"avx512bf16", F_AVX512BF16, P_NONE},
-  {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_NONE}
+  {"cmov",    FEATURE_CMOV,    P_NONE},
+  {"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_NONE},
+  {"avx512bw",FEATURE_AVX512BW, P_NONE},
+  {"avx512dq",FEATURE_AVX512DQ, P_NONE},
+  {"avx512cd",FEATURE_AVX512CD, P_NONE},
+  {"avx512er",FEATURE_AVX512ER, P_NONE},
+  {"avx512pf",FEATURE_AVX512PF, P_NONE},
+  {"avx512vbmi",FEATURE_AVX512VBMI, P_NONE},
+  {"avx512ifma",FEATURE_AVX512IFMA, P_NONE},
+  {"avx5124vnniw",FEATURE_AVX5124VNNIW, P_NONE},
+  {"avx5124fmaps",FEATURE_AVX5124FMAPS, P_NONE},
+  {"avx512vpopcntdq",FEATURE_AVX512VPOPCNTDQ,  P_NONE},
+  {"avx512vbmi2", FEATURE_AVX512VBMI2, P_NONE},
+  {"gfni",     FEATURE_GFNI,   P_NONE},
+  {"vpclmulqdq", FEATURE_VPCLMULQDQ, P_NONE},
+  {"avx512vnni", FEATURE_AVX512VNNI, P_NONE},
+  {"avx512bitalg", FEATURE_AVX512BITALG, P_NONE},
+  {"avx512bf16", FEATURE_AVX512BF16, P_NONE},
+  {"avx512vp2intersect",FEATURE_AVX512VP2INTERSECT, P_NONE}
 };
 
 /* This parses the attribute arguments to target in DECL and determines
@@ -2294,16 +2250,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);
index cf5f088..7218952 100644 (file)
@@ -26,7 +26,8 @@ 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/i386-cpuinfo.h"
+#include "common/config/i386/cpuinfo.h"
 
 #ifdef HAVE_INIT_PRIORITY
 #define CONSTRUCTOR_PRIORITY (101)
@@ -39,386 +40,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 +58,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
diff --git a/libgcc/config/i386/cpuinfo.h b/libgcc/config/i386/cpuinfo.h
deleted file mode 100644 (file)
index 0f97510..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/* 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/>.  */
-
-/* Processor Vendor and Models. */
-
-enum processor_vendor
-{
-  VENDOR_INTEL = 1,
-  VENDOR_AMD,
-  VENDOR_OTHER,
-  VENDOR_MAX
-};
-
-/* Any new types or subtypes have to be inserted at the end. */
-
-enum processor_types
-{
-  INTEL_BONNELL = 1,
-  INTEL_CORE2,
-  INTEL_COREI7,
-  AMDFAM10H,
-  AMDFAM15H,
-  INTEL_SILVERMONT,
-  INTEL_KNL,
-  AMD_BTVER1,
-  AMD_BTVER2,  
-  AMDFAM17H,
-  INTEL_KNM,
-  INTEL_GOLDMONT,
-  INTEL_GOLDMONT_PLUS,
-  INTEL_TREMONT,
-  CPU_TYPE_MAX
-};
-
-enum processor_subtypes
-{
-  INTEL_COREI7_NEHALEM = 1,
-  INTEL_COREI7_WESTMERE,
-  INTEL_COREI7_SANDYBRIDGE,
-  AMDFAM10H_BARCELONA,
-  AMDFAM10H_SHANGHAI,
-  AMDFAM10H_ISTANBUL,
-  AMDFAM15H_BDVER1,
-  AMDFAM15H_BDVER2,
-  AMDFAM15H_BDVER3,
-  AMDFAM15H_BDVER4,
-  AMDFAM17H_ZNVER1,
-  INTEL_COREI7_IVYBRIDGE,
-  INTEL_COREI7_HASWELL,
-  INTEL_COREI7_BROADWELL,
-  INTEL_COREI7_SKYLAKE,
-  INTEL_COREI7_SKYLAKE_AVX512,
-  INTEL_COREI7_CANNONLAKE,
-  INTEL_COREI7_ICELAKE_CLIENT,
-  INTEL_COREI7_ICELAKE_SERVER,
-  AMDFAM17H_ZNVER2,
-  INTEL_COREI7_CASCADELAKE,
-  INTEL_COREI7_TIGERLAKE,
-  INTEL_COREI7_COOPERLAKE,
-  CPU_SUBTYPE_MAX
-};
-
-/* ISA Features supported. New features have to be inserted at the end.  */
-
-enum processor_features
-{
-  FEATURE_CMOV = 0,
-  FEATURE_MMX,
-  FEATURE_POPCNT,
-  FEATURE_SSE,
-  FEATURE_SSE2,
-  FEATURE_SSE3,
-  FEATURE_SSSE3,
-  FEATURE_SSE4_1,
-  FEATURE_SSE4_2,
-  FEATURE_AVX,
-  FEATURE_AVX2,
-  FEATURE_SSE4_A,
-  FEATURE_FMA4,
-  FEATURE_XOP,
-  FEATURE_FMA,
-  FEATURE_AVX512F,
-  FEATURE_BMI,
-  FEATURE_BMI2,
-  FEATURE_AES,
-  FEATURE_PCLMUL,
-  FEATURE_AVX512VL,
-  FEATURE_AVX512BW,
-  FEATURE_AVX512DQ,
-  FEATURE_AVX512CD,
-  FEATURE_AVX512ER,
-  FEATURE_AVX512PF,
-  FEATURE_AVX512VBMI,
-  FEATURE_AVX512IFMA,
-  FEATURE_AVX5124VNNIW,
-  FEATURE_AVX5124FMAPS,
-  FEATURE_AVX512VPOPCNTDQ,
-  FEATURE_AVX512VBMI2,
-  FEATURE_GFNI,
-  FEATURE_VPCLMULQDQ,
-  FEATURE_AVX512VNNI,
-  FEATURE_AVX512BITALG,
-  FEATURE_AVX512BF16,
-  FEATURE_AVX512VP2INTERSECT
-};
-
-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;