1  /* Get CPU type and Features for x86 processors.
       2     Copyright (C) 2012-2023 Free Software Foundation, Inc.
       3     Contributed by Sriraman Tallam (tmsriram@google.com)
       4  
       5  This file is part of GCC.
       6  
       7  GCC is free software; you can redistribute it and/or modify it under
       8  the terms of the GNU General Public License as published by the Free
       9  Software Foundation; either version 3, or (at your option) any later
      10  version.
      11  
      12  GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13  WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15  for more details.
      16  
      17  Under Section 7 of GPL version 3, you are granted additional
      18  permissions described in the GCC Runtime Library Exception, version
      19  3.1, as published by the Free Software Foundation.
      20  
      21  You should have received a copy of the GNU General Public License and
      22  a copy of the GCC Runtime Library Exception along with this program;
      23  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      24  <http://www.gnu.org/licenses/>.  */
      25  
      26  struct __processor_model
      27  {
      28    unsigned int __cpu_vendor;
      29    unsigned int __cpu_type;
      30    unsigned int __cpu_subtype;
      31    /* The first 32 features are stored as bitmasks in __cpu_features.
      32       The rest of features are stored as bitmasks in a separate array
      33       of unsigned int.  */
      34    unsigned int __cpu_features[1];
      35  };
      36  
      37  struct __processor_model2
      38  {
      39    unsigned int __cpu_family;
      40    unsigned int __cpu_model;
      41    unsigned int __cpu_max_level;
      42    unsigned int __cpu_ext_level;
      43  };
      44  
      45  #ifndef CHECK___builtin_cpu_is
      46  # define CHECK___builtin_cpu_is(cpu)
      47  #endif
      48  
      49  #ifndef CHECK___builtin_cpu_supports
      50  # define CHECK___builtin_cpu_supports(isa)
      51  #endif
      52  
      53  /* Return non-zero if the processor has feature F.  */
      54  
      55  static inline int
      56  has_cpu_feature (struct __processor_model *cpu_model,
      57  		 unsigned int *cpu_features2,
      58  		 enum processor_features feature)
      59  {
      60    unsigned index, offset;
      61    unsigned f = feature;
      62  
      63    if (f < 32)
      64      {
      65        /* The first 32 features.  */
      66        return cpu_model->__cpu_features[0] & (1U << f);
      67      }
      68    else
      69      {
      70        /* The rest of features.  cpu_features2[i] contains features from
      71  	 (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
      72        f -= 32;
      73        index = f / 32;
      74        offset = f % 32;
      75        return cpu_features2[index] & (1U << offset);
      76      }
      77  }
      78  
      79  /* Save FEATURE to either CPU_MODEL or CPU_FEATURES2.  */
      80  
      81  static inline void
      82  set_cpu_feature (struct __processor_model *cpu_model,
      83  		 unsigned int *cpu_features2,
      84  		 enum processor_features feature)
      85  {
      86    unsigned index, offset;
      87    unsigned f = feature;
      88  
      89    if (f < 32)
      90      {
      91        /* The first 32 features.  */
      92        cpu_model->__cpu_features[0] |= (1U << f);
      93      }
      94    else
      95      {
      96        /* The rest of features.  cpu_features2[i] contains features from
      97  	 (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
      98        f -= 32;
      99        index = f / 32;
     100        offset = f % 32;
     101        cpu_features2[index] |= (1U << offset);
     102      }
     103  }
     104  
     105  /* Drop FEATURE from either CPU_MODEL or CPU_FEATURES2.  */
     106  
     107  static inline void
     108  reset_cpu_feature (struct __processor_model *cpu_model,
     109  		   unsigned int *cpu_features2,
     110  		   enum processor_features feature)
     111  {
     112    unsigned index, offset;
     113    unsigned f = feature;
     114  
     115    if (f < 32)
     116      {
     117        /* The first 32 features.  */
     118        cpu_model->__cpu_features[0] &= ~(1U << f);
     119      }
     120    else
     121      {
     122        /* The rest of features.  cpu_features2[i] contains features from
     123  	 (32 + i * 32) to (31 + 32 + i * 32), inclusively.  */
     124        f -= 32;
     125        index = f / 32;
     126        offset = f % 32;
     127        cpu_features2[index] &= ~(1U << offset);
     128      }
     129  }
     130  
     131  /* Get the specific type of AMD CPU and return AMD CPU name.  Return
     132     NULL for unknown AMD CPU.  */
     133  
     134  static inline const char *
     135  get_amd_cpu (struct __processor_model *cpu_model,
     136  	     struct __processor_model2 *cpu_model2,
     137  	     unsigned int *cpu_features2)
     138  {
     139    const char *cpu = NULL;
     140    unsigned int family = cpu_model2->__cpu_family;
     141    unsigned int model = cpu_model2->__cpu_model;
     142  
     143    switch (family)
     144      {
     145      case 0x10:
     146        /* AMD Family 10h.  */
     147        cpu = "amdfam10";
     148        cpu_model->__cpu_type = AMDFAM10H;
     149        switch (model)
     150  	{
     151  	case 0x2:
     152  	  /* Barcelona.  */
     153  	  CHECK___builtin_cpu_is ("amdfam10h");
     154  	  CHECK___builtin_cpu_is ("barcelona");
     155  	  cpu_model->__cpu_subtype = AMDFAM10H_BARCELONA;
     156  	  break;
     157  	case 0x4:
     158  	  /* Shanghai.  */
     159  	  CHECK___builtin_cpu_is ("amdfam10h");
     160  	  CHECK___builtin_cpu_is ("shanghai");
     161  	  cpu_model->__cpu_subtype = AMDFAM10H_SHANGHAI;
     162  	  break;
     163  	case 0x8:
     164  	  /* Istanbul.  */
     165  	  CHECK___builtin_cpu_is ("amdfam10h");
     166  	  CHECK___builtin_cpu_is ("istanbul");
     167  	  cpu_model->__cpu_subtype = AMDFAM10H_ISTANBUL;
     168  	  break;
     169  	default:
     170  	  break;
     171  	}
     172        break;
     173      case 0x14:
     174        /* AMD Family 14h "btver1". */
     175        cpu = "btver1";
     176        CHECK___builtin_cpu_is ("btver1");
     177        cpu_model->__cpu_type = AMD_BTVER1;
     178        break;
     179      case 0x15:
     180        /* AMD Family 15h "Bulldozer".  */
     181        cpu_model->__cpu_type = AMDFAM15H;
     182        if (model == 0x2)
     183  	{
     184  	  /* Bulldozer version 2 "Piledriver" */
     185  	  cpu = "bdver2";
     186  	  CHECK___builtin_cpu_is ("bdver2");
     187  	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
     188  	}
     189        else if (model <= 0xf)
     190  	{
     191  	  /* Bulldozer version 1.  */
     192  	  cpu = "bdver1";
     193  	  CHECK___builtin_cpu_is ("bdver1");
     194  	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
     195  	}
     196        else if (model <= 0x2f)
     197  	{
     198  	  /* Bulldozer version 2 "Piledriver" */
     199  	  cpu = "bdver2";
     200  	  CHECK___builtin_cpu_is ("bdver2");
     201  	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
     202  	}
     203        else if (model <= 0x4f)
     204  	{
     205  	  /* Bulldozer version 3 "Steamroller"  */
     206  	  cpu = "bdver3";
     207  	  CHECK___builtin_cpu_is ("bdver3");
     208  	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
     209  	}
     210        else if (model <= 0x7f)
     211  	{
     212  	  /* Bulldozer version 4 "Excavator"   */
     213  	  cpu = "bdver4";
     214  	  CHECK___builtin_cpu_is ("bdver4");
     215  	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
     216  	}
     217        else if (has_cpu_feature (cpu_model, cpu_features2,
     218  				FEATURE_AVX2))
     219  	{
     220  	  cpu = "bdver4";
     221  	  CHECK___builtin_cpu_is ("bdver4");
     222  	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER4;
     223  	}
     224        else if (has_cpu_feature (cpu_model, cpu_features2,
     225  				FEATURE_XSAVEOPT))
     226  	{
     227  	  cpu = "bdver3";
     228  	  CHECK___builtin_cpu_is ("bdver3");
     229  	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER3;
     230  	}
     231        else if (has_cpu_feature (cpu_model, cpu_features2,
     232  				FEATURE_BMI))
     233  	{
     234  	  cpu = "bdver2";
     235  	  CHECK___builtin_cpu_is ("bdver2");
     236  	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER2;
     237  	}
     238        else if (has_cpu_feature (cpu_model, cpu_features2,
     239  				FEATURE_XOP))
     240  	{
     241  	  cpu = "bdver1";
     242  	  CHECK___builtin_cpu_is ("bdver1");
     243  	  cpu_model->__cpu_subtype = AMDFAM15H_BDVER1;
     244  	}
     245        break;
     246      case 0x16:
     247        /* AMD Family 16h "btver2" */
     248        cpu = "btver2";
     249        CHECK___builtin_cpu_is ("btver2");
     250        cpu_model->__cpu_type = AMD_BTVER2;
     251        break;
     252      case 0x17:
     253        cpu_model->__cpu_type = AMDFAM17H;
     254        if (model <= 0x1f)
     255  	{
     256  	  /* AMD family 17h version 1.  */
     257  	  cpu = "znver1";
     258  	  CHECK___builtin_cpu_is ("znver1");
     259  	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
     260  	}
     261        else if (model >= 0x30)
     262  	{
     263  	  cpu = "znver2";
     264  	  CHECK___builtin_cpu_is ("znver2");
     265  	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
     266  	}
     267        else if (has_cpu_feature (cpu_model, cpu_features2,
     268  				FEATURE_CLWB))
     269  	{
     270  	  cpu = "znver2";
     271  	  CHECK___builtin_cpu_is ("znver2");
     272  	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER2;
     273  	}
     274        else if (has_cpu_feature (cpu_model, cpu_features2,
     275  				FEATURE_CLZERO))
     276  	{
     277  	  cpu = "znver1";
     278  	  CHECK___builtin_cpu_is ("znver1");
     279  	  cpu_model->__cpu_subtype = AMDFAM17H_ZNVER1;
     280  	}
     281        break;
     282      case 0x19:
     283        cpu_model->__cpu_type = AMDFAM19H;
     284        /* AMD family 19h.  */
     285        if (model <= 0x0f)
     286  	{
     287  	  cpu = "znver3";
     288  	  CHECK___builtin_cpu_is ("znver3");
     289  	  cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3;
     290  	}
     291        else if ((model >= 0x10 && model <= 0x1f)
     292  		|| (model >= 0x60 && model <= 0xaf))
     293  	{
     294  	  cpu = "znver4";
     295  	  CHECK___builtin_cpu_is ("znver4");
     296  	  cpu_model->__cpu_subtype = AMDFAM19H_ZNVER4;
     297  	}
     298        else if (has_cpu_feature (cpu_model, cpu_features2,
     299  				FEATURE_AVX512F))
     300  	{
     301  	  cpu = "znver4";
     302  	  CHECK___builtin_cpu_is ("znver4");
     303  	  cpu_model->__cpu_subtype = AMDFAM19H_ZNVER4;
     304  	}
     305        else if (has_cpu_feature (cpu_model, cpu_features2,
     306  				FEATURE_VAES))
     307  	{
     308  	  cpu = "znver3";
     309  	  CHECK___builtin_cpu_is ("znver3");
     310  	  cpu_model->__cpu_subtype = AMDFAM19H_ZNVER3;
     311  	}
     312        break;
     313      default:
     314        break;
     315      }
     316  
     317    return cpu;
     318  }
     319  
     320  /* Get the specific type of Intel CPU and return Intel CPU name.  Return
     321     NULL for unknown Intel CPU.  */
     322  
     323  static inline const char *
     324  get_intel_cpu (struct __processor_model *cpu_model,
     325  	       struct __processor_model2 *cpu_model2,
     326  	       unsigned int *cpu_features2)
     327  {
     328    const char *cpu = NULL;
     329  
     330    /* Parse family and model only for model 6. */
     331    if (cpu_model2->__cpu_family != 0x6)
     332      return cpu;
     333  
     334    switch (cpu_model2->__cpu_model)
     335      {
     336      case 0x1c:
     337      case 0x26:
     338        /* Bonnell.  */
     339        cpu = "bonnell";
     340        CHECK___builtin_cpu_is ("atom");
     341        cpu_model->__cpu_type = INTEL_BONNELL;
     342        break;
     343      case 0x37:
     344      case 0x4a:
     345      case 0x4d:
     346      case 0x5d:
     347        /* Silvermont.  */
     348      case 0x4c:
     349      case 0x5a:
     350      case 0x75:
     351        /* Airmont.  */
     352        cpu = "silvermont";
     353        CHECK___builtin_cpu_is ("silvermont");
     354        cpu_model->__cpu_type = INTEL_SILVERMONT;
     355        break;
     356      case 0x5c:
     357      case 0x5f:
     358        /* Goldmont.  */
     359        cpu = "goldmont";
     360        CHECK___builtin_cpu_is ("goldmont");
     361        cpu_model->__cpu_type = INTEL_GOLDMONT;
     362        break;
     363      case 0x7a:
     364        /* Goldmont Plus.  */
     365        cpu = "goldmont-plus";
     366        CHECK___builtin_cpu_is ("goldmont-plus");
     367        cpu_model->__cpu_type = INTEL_GOLDMONT_PLUS;
     368        break;
     369      case 0x86:
     370      case 0x96:
     371      case 0x9c:
     372        /* Tremont.  */
     373        cpu = "tremont";
     374        CHECK___builtin_cpu_is ("tremont");
     375        cpu_model->__cpu_type = INTEL_TREMONT;
     376        break;
     377      case 0x57:
     378        /* Knights Landing.  */
     379        cpu = "knl";
     380        CHECK___builtin_cpu_is ("knl");
     381        cpu_model->__cpu_type = INTEL_KNL;
     382        break;
     383      case 0x85:
     384        /* Knights Mill. */
     385        cpu = "knm";
     386        CHECK___builtin_cpu_is ("knm");
     387        cpu_model->__cpu_type = INTEL_KNM;
     388        break;
     389      case 0x1a:
     390      case 0x1e:
     391      case 0x1f:
     392      case 0x2e:
     393        /* Nehalem.  */
     394        cpu = "nehalem";
     395        CHECK___builtin_cpu_is ("corei7");
     396        CHECK___builtin_cpu_is ("nehalem");
     397        cpu_model->__cpu_type = INTEL_COREI7;
     398        cpu_model->__cpu_subtype = INTEL_COREI7_NEHALEM;
     399        break;
     400      case 0x25:
     401      case 0x2c:
     402      case 0x2f:
     403        /* Westmere.  */
     404        cpu = "westmere";
     405        CHECK___builtin_cpu_is ("corei7");
     406        CHECK___builtin_cpu_is ("westmere");
     407        cpu_model->__cpu_type = INTEL_COREI7;
     408        cpu_model->__cpu_subtype = INTEL_COREI7_WESTMERE;
     409        break;
     410      case 0x2a:
     411      case 0x2d:
     412        /* Sandy Bridge.  */
     413        cpu = "sandybridge";
     414        CHECK___builtin_cpu_is ("corei7");
     415        CHECK___builtin_cpu_is ("sandybridge");
     416        cpu_model->__cpu_type = INTEL_COREI7;
     417        cpu_model->__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
     418        break;
     419      case 0x3a:
     420      case 0x3e:
     421        /* Ivy Bridge.  */
     422        cpu = "ivybridge";
     423        CHECK___builtin_cpu_is ("corei7");
     424        CHECK___builtin_cpu_is ("ivybridge");
     425        cpu_model->__cpu_type = INTEL_COREI7;
     426        cpu_model->__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
     427        break;
     428      case 0x3c:
     429      case 0x3f:
     430      case 0x45:
     431      case 0x46:
     432        /* Haswell.  */
     433        cpu = "haswell";
     434        CHECK___builtin_cpu_is ("corei7");
     435        CHECK___builtin_cpu_is ("haswell");
     436        cpu_model->__cpu_type = INTEL_COREI7;
     437        cpu_model->__cpu_subtype = INTEL_COREI7_HASWELL;
     438        break;
     439      case 0x3d:
     440      case 0x47:
     441      case 0x4f:
     442      case 0x56:
     443        /* Broadwell.  */
     444        cpu = "broadwell";
     445        CHECK___builtin_cpu_is ("corei7");
     446        CHECK___builtin_cpu_is ("broadwell");
     447        cpu_model->__cpu_type = INTEL_COREI7;
     448        cpu_model->__cpu_subtype = INTEL_COREI7_BROADWELL;
     449        break;
     450      case 0x4e:
     451      case 0x5e:
     452        /* Skylake.  */
     453      case 0x8e:
     454      case 0x9e:
     455        /* Kaby Lake.  */
     456      case 0xa5:
     457      case 0xa6:
     458        /* Comet Lake.  */
     459        cpu = "skylake";
     460        CHECK___builtin_cpu_is ("corei7");
     461        CHECK___builtin_cpu_is ("skylake");
     462        cpu_model->__cpu_type = INTEL_COREI7;
     463        cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
     464        break;
     465      case 0xa7:
     466      case 0xa8:
     467        /* Rocket Lake.  */
     468        cpu = "rocketlake";
     469        CHECK___builtin_cpu_is ("corei7");
     470        CHECK___builtin_cpu_is ("rocketlake");
     471        cpu_model->__cpu_type = INTEL_COREI7;
     472        cpu_model->__cpu_subtype = INTEL_COREI7_ROCKETLAKE;
     473        break;
     474      case 0x55:
     475        CHECK___builtin_cpu_is ("corei7");
     476        cpu_model->__cpu_type = INTEL_COREI7;
     477        if (has_cpu_feature (cpu_model, cpu_features2,
     478  			   FEATURE_AVX512BF16))
     479  	{
     480  	  /* Cooper Lake.  */
     481  	  cpu = "cooperlake";
     482  	  CHECK___builtin_cpu_is ("cooperlake");
     483  	  cpu_model->__cpu_subtype = INTEL_COREI7_COOPERLAKE;
     484  	}
     485        else if (has_cpu_feature (cpu_model, cpu_features2,
     486  				FEATURE_AVX512VNNI))
     487  	{
     488  	  /* Cascade Lake.  */
     489  	  cpu = "cascadelake";
     490  	  CHECK___builtin_cpu_is ("cascadelake");
     491  	  cpu_model->__cpu_subtype = INTEL_COREI7_CASCADELAKE;
     492  	}
     493        else
     494  	{
     495  	  /* Skylake with AVX-512 support.  */
     496  	  cpu = "skylake-avx512";
     497  	  CHECK___builtin_cpu_is ("skylake-avx512");
     498  	  cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
     499  	}
     500        break;
     501      case 0x66:
     502        /* Cannon Lake.  */
     503        cpu = "cannonlake";
     504        CHECK___builtin_cpu_is ("corei7");
     505        CHECK___builtin_cpu_is ("cannonlake");
     506        cpu_model->__cpu_type = INTEL_COREI7;
     507        cpu_model->__cpu_subtype = INTEL_COREI7_CANNONLAKE;
     508        break;
     509      case 0x6a:
     510      case 0x6c:
     511        /* Ice Lake server.  */
     512        cpu = "icelake-server";
     513        CHECK___builtin_cpu_is ("corei7");
     514        CHECK___builtin_cpu_is ("icelake-server");
     515        cpu_model->__cpu_type = INTEL_COREI7;
     516        cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_SERVER;
     517        break;
     518      case 0x7e:
     519      case 0x7d:
     520      case 0x9d:
     521         /* Ice Lake client.  */
     522        cpu = "icelake-client";
     523        CHECK___builtin_cpu_is ("corei7");
     524        CHECK___builtin_cpu_is ("icelake-client");
     525        cpu_model->__cpu_type = INTEL_COREI7;
     526        cpu_model->__cpu_subtype = INTEL_COREI7_ICELAKE_CLIENT;
     527        break;
     528      case 0x8c:
     529      case 0x8d:
     530        /* Tiger Lake.  */
     531        cpu = "tigerlake";
     532        CHECK___builtin_cpu_is ("corei7");
     533        CHECK___builtin_cpu_is ("tigerlake");
     534        cpu_model->__cpu_type = INTEL_COREI7;
     535        cpu_model->__cpu_subtype = INTEL_COREI7_TIGERLAKE;
     536        break;
     537      case 0x97:
     538      case 0x9a:
     539      case 0xbf:
     540        /* Alder Lake.  */
     541      case 0xb7:
     542        /* Raptor Lake.  */
     543      case 0xaa:
     544      case 0xac:
     545        /* Meteor Lake.  */
     546        cpu = "alderlake";
     547        CHECK___builtin_cpu_is ("corei7");
     548        CHECK___builtin_cpu_is ("alderlake");
     549        cpu_model->__cpu_type = INTEL_COREI7;
     550        cpu_model->__cpu_subtype = INTEL_COREI7_ALDERLAKE;
     551        break;
     552      case 0x8f:
     553        /* Sapphire Rapids.  */
     554      case 0xcf:
     555        /* Emerald Rapids.  */
     556        cpu = "sapphirerapids";
     557        CHECK___builtin_cpu_is ("corei7");
     558        CHECK___builtin_cpu_is ("sapphirerapids");
     559        cpu_model->__cpu_type = INTEL_COREI7;
     560        cpu_model->__cpu_subtype = INTEL_COREI7_SAPPHIRERAPIDS;
     561        break;
     562      case 0xaf:
     563        /* Sierra Forest.  */
     564        cpu = "sierraforest";
     565        CHECK___builtin_cpu_is ("sierraforest");
     566        cpu_model->__cpu_type = INTEL_SIERRAFOREST;
     567        break;
     568      case 0xad:
     569        /* Granite Rapids.  */
     570        cpu = "graniterapids";
     571        CHECK___builtin_cpu_is ("corei7");
     572        CHECK___builtin_cpu_is ("graniterapids");
     573        cpu_model->__cpu_type = INTEL_COREI7;
     574        cpu_model->__cpu_subtype = INTEL_COREI7_GRANITERAPIDS;
     575        break;
     576      case 0xae:
     577        /* Granite Rapids D.  */
     578        cpu = "graniterapids-d";
     579        CHECK___builtin_cpu_is ("corei7");
     580        CHECK___builtin_cpu_is ("graniterapids-d");
     581        cpu_model->__cpu_type = INTEL_COREI7;
     582        cpu_model->__cpu_subtype = INTEL_COREI7_GRANITERAPIDS_D;
     583        break;
     584      case 0xb6:
     585        /* Grand Ridge.  */
     586        cpu = "grandridge";
     587        CHECK___builtin_cpu_is ("grandridge");
     588        cpu_model->__cpu_type = INTEL_GRANDRIDGE;
     589        break;
     590      case 0x17:
     591      case 0x1d:
     592        /* Penryn.  */
     593      case 0x0f:
     594        /* Merom.  */
     595        cpu = "core2";
     596        CHECK___builtin_cpu_is ("core2");
     597        cpu_model->__cpu_type = INTEL_CORE2;
     598        break;
     599      default:
     600        break;
     601      }
     602  
     603    return cpu;
     604  }
     605  
     606  /* Get the specific type of ZHAOXIN CPU and return ZHAOXIN CPU name.
     607     Return NULL for unknown ZHAOXIN CPU.  */
     608  
     609  static inline const char *
     610  get_zhaoxin_cpu (struct __processor_model *cpu_model,
     611  		 struct __processor_model2 *cpu_model2,
     612  		 unsigned int *cpu_features2)
     613  {
     614    const char *cpu = NULL;
     615    unsigned int family = cpu_model2->__cpu_family;
     616    unsigned int model = cpu_model2->__cpu_model;
     617  
     618    switch (family)
     619      {
     620      /* ZHAOXIN family 7h.  */
     621      case 0x07:
     622        cpu_model->__cpu_type = ZHAOXIN_FAM7H;
     623        if (model == 0x3b)
     624  	{
     625  	  cpu = "lujiazui";
     626  	  CHECK___builtin_cpu_is ("lujiazui");
     627  	  reset_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX);
     628  	  reset_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C);
     629  	  cpu_model->__cpu_subtype = ZHAOXIN_FAM7H_LUJIAZUI;
     630  	}
     631        break;
     632      default:
     633        break;
     634      }
     635  
     636    return cpu;
     637  }
     638  
     639  /* ECX and EDX are output of CPUID at level one.  */
     640  static inline void
     641  get_available_features (struct __processor_model *cpu_model,
     642  			struct __processor_model2 *cpu_model2,
     643  			unsigned int *cpu_features2,
     644  			unsigned int ecx, unsigned int edx)
     645  {
     646    unsigned int max_cpuid_level = cpu_model2->__cpu_max_level;
     647    unsigned int eax, ebx;
     648    unsigned int ext_level;
     649  
     650    /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv.  */
     651  #define XCR_XFEATURE_ENABLED_MASK	0x0
     652  #define XSTATE_FP			0x1
     653  #define XSTATE_SSE			0x2
     654  #define XSTATE_YMM			0x4
     655  #define XSTATE_OPMASK			0x20
     656  #define XSTATE_ZMM			0x40
     657  #define XSTATE_HI_ZMM			0x80
     658  #define XSTATE_TILECFG			0x20000
     659  #define XSTATE_TILEDATA		0x40000
     660  
     661  #define XCR_AVX_ENABLED_MASK \
     662    (XSTATE_SSE | XSTATE_YMM)
     663  #define XCR_AVX512F_ENABLED_MASK \
     664    (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
     665  #define XCR_AMX_ENABLED_MASK \
     666    (XSTATE_TILECFG | XSTATE_TILEDATA)
     667  
     668    /* Check if AVX and AVX512 are usable.  */
     669    int avx_usable = 0;
     670    int avx512_usable = 0;
     671    int amx_usable = 0;
     672    /* Check if KL is usable.  */
     673    int has_kl = 0;
     674    if ((ecx & bit_OSXSAVE))
     675      {
     676        /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
     677  	 ZMM16-ZMM31 states are supported by OSXSAVE.  */
     678        unsigned int xcrlow;
     679        unsigned int xcrhigh;
     680        __asm__ (".byte 0x0f, 0x01, 0xd0"
     681  	       : "=a" (xcrlow), "=d" (xcrhigh)
     682  	       : "c" (XCR_XFEATURE_ENABLED_MASK));
     683        if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
     684  	{
     685  	  avx_usable = 1;
     686  	  avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
     687  			   == XCR_AVX512F_ENABLED_MASK);
     688  	}
     689        amx_usable = ((xcrlow & XCR_AMX_ENABLED_MASK)
     690  		    == XCR_AMX_ENABLED_MASK);
     691      }
     692  
     693  #define set_feature(f) \
     694    set_cpu_feature (cpu_model, cpu_features2, f)
     695  
     696    if (edx & bit_CMOV)
     697      set_feature (FEATURE_CMOV);
     698    if (edx & bit_MMX)
     699      set_feature (FEATURE_MMX);
     700    if (edx & bit_SSE)
     701      set_feature (FEATURE_SSE);
     702    if (edx & bit_SSE2)
     703      set_feature (FEATURE_SSE2);
     704    if (edx & bit_CMPXCHG8B)
     705      set_feature (FEATURE_CMPXCHG8B);
     706    if (edx & bit_FXSAVE)
     707      set_feature (FEATURE_FXSAVE);
     708  
     709    if (ecx & bit_POPCNT)
     710      set_feature (FEATURE_POPCNT);
     711    if (ecx & bit_AES)
     712      set_feature (FEATURE_AES);
     713    if (ecx & bit_PCLMUL)
     714      set_feature (FEATURE_PCLMUL);
     715    if (ecx & bit_SSE3)
     716      set_feature (FEATURE_SSE3);
     717    if (ecx & bit_SSSE3)
     718      set_feature (FEATURE_SSSE3);
     719    if (ecx & bit_SSE4_1)
     720      set_feature (FEATURE_SSE4_1);
     721    if (ecx & bit_SSE4_2)
     722      set_feature (FEATURE_SSE4_2);
     723    if (ecx & bit_OSXSAVE)
     724      set_feature (FEATURE_OSXSAVE);
     725    if (ecx & bit_CMPXCHG16B)
     726      set_feature (FEATURE_CMPXCHG16B);
     727    if (ecx & bit_MOVBE)
     728      set_feature (FEATURE_MOVBE);
     729    if (ecx & bit_AES)
     730      set_feature (FEATURE_AES);
     731    if (ecx & bit_RDRND)
     732      set_feature (FEATURE_RDRND);
     733    if (ecx & bit_XSAVE)
     734      set_feature (FEATURE_XSAVE);
     735    if (avx_usable)
     736      {
     737        if (ecx & bit_AVX)
     738  	set_feature (FEATURE_AVX);
     739        if (ecx & bit_FMA)
     740  	set_feature (FEATURE_FMA);
     741        if (ecx & bit_F16C)
     742  	set_feature (FEATURE_F16C);
     743      }
     744  
     745    /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
     746    if (max_cpuid_level >= 7)
     747      {
     748        __cpuid_count (7, 0, eax, ebx, ecx, edx);
     749        if (ebx & bit_BMI)
     750  	set_feature (FEATURE_BMI);
     751        if (ebx & bit_SGX)
     752  	set_feature (FEATURE_SGX);
     753        if (ebx & bit_HLE)
     754  	set_feature (FEATURE_HLE);
     755        if (ebx & bit_RTM)
     756  	set_feature (FEATURE_RTM);
     757        if (avx_usable)
     758  	{
     759  	  if (ebx & bit_AVX2)
     760  	    set_feature (FEATURE_AVX2);
     761  	  if (ecx & bit_VPCLMULQDQ)
     762  	    set_feature (FEATURE_VPCLMULQDQ);
     763  	  if (ecx & bit_VAES)
     764  	    set_feature (FEATURE_VAES);
     765  	}
     766        if (ebx & bit_BMI2)
     767  	set_feature (FEATURE_BMI2);
     768        if (ebx & bit_FSGSBASE)
     769  	set_feature (FEATURE_FSGSBASE);
     770        if (ebx & bit_RDSEED)
     771  	set_feature (FEATURE_RDSEED);
     772        if (ebx & bit_ADX)
     773  	set_feature (FEATURE_ADX);
     774        if (ebx & bit_SHA)
     775  	set_feature (FEATURE_SHA);
     776        if (ebx & bit_CLFLUSHOPT)
     777  	set_feature (FEATURE_CLFLUSHOPT);
     778        if (ebx & bit_CLWB)
     779  	set_feature (FEATURE_CLWB);
     780        if (ecx & bit_PREFETCHWT1)
     781  	set_feature (FEATURE_PREFETCHWT1);
     782        /* NB: bit_OSPKE indicates that OS supports PKU.  */
     783        if (ecx & bit_OSPKE)
     784  	set_feature (FEATURE_PKU);
     785        if (ecx & bit_RDPID)
     786  	set_feature (FEATURE_RDPID);
     787        if (ecx & bit_GFNI)
     788  	set_feature (FEATURE_GFNI);
     789        if (ecx & bit_MOVDIRI)
     790  	set_feature (FEATURE_MOVDIRI);
     791        if (ecx & bit_MOVDIR64B)
     792  	set_feature (FEATURE_MOVDIR64B);
     793        if (ecx & bit_ENQCMD)
     794  	set_feature (FEATURE_ENQCMD);
     795        if (ecx & bit_CLDEMOTE)
     796  	set_feature (FEATURE_CLDEMOTE);
     797        if (ecx & bit_WAITPKG)
     798  	set_feature (FEATURE_WAITPKG);
     799        if (ecx & bit_SHSTK)
     800  	set_feature (FEATURE_SHSTK);
     801        if (ecx & bit_KL)
     802  	has_kl = 1;
     803        if (edx & bit_SERIALIZE)
     804  	set_feature (FEATURE_SERIALIZE);
     805        if (edx & bit_TSXLDTRK)
     806  	set_feature (FEATURE_TSXLDTRK);
     807        if (edx & bit_PCONFIG)
     808  	set_feature (FEATURE_PCONFIG);
     809        if (edx & bit_IBT)
     810  	set_feature (FEATURE_IBT);
     811        if (edx & bit_UINTR)
     812  	set_feature (FEATURE_UINTR);
     813        if (amx_usable)
     814  	{
     815  	  if (edx & bit_AMX_TILE)
     816  	    set_feature (FEATURE_AMX_TILE);
     817  	  if (edx & bit_AMX_INT8)
     818  	    set_feature (FEATURE_AMX_INT8);
     819  	  if (edx & bit_AMX_BF16)
     820  	    set_feature (FEATURE_AMX_BF16);
     821  	}
     822        if (avx512_usable)
     823  	{
     824  	  if (ebx & bit_AVX512F)
     825  	    set_feature (FEATURE_AVX512F);
     826  	  if (ebx & bit_AVX512VL)
     827  	    set_feature (FEATURE_AVX512VL);
     828  	  if (ebx & bit_AVX512BW)
     829  	    set_feature (FEATURE_AVX512BW);
     830  	  if (ebx & bit_AVX512DQ)
     831  	    set_feature (FEATURE_AVX512DQ);
     832  	  if (ebx & bit_AVX512CD)
     833  	    set_feature (FEATURE_AVX512CD);
     834  	  if (ebx & bit_AVX512PF)
     835  	    set_feature (FEATURE_AVX512PF);
     836  	  if (ebx & bit_AVX512ER)
     837  	    set_feature (FEATURE_AVX512ER);
     838  	  if (ebx & bit_AVX512IFMA)
     839  	    set_feature (FEATURE_AVX512IFMA);
     840  	  if (ecx & bit_AVX512VBMI)
     841  	    set_feature (FEATURE_AVX512VBMI);
     842  	  if (ecx & bit_AVX512VBMI2)
     843  	    set_feature (FEATURE_AVX512VBMI2);
     844  	  if (ecx & bit_AVX512VNNI)
     845  	    set_feature (FEATURE_AVX512VNNI);
     846  	  if (ecx & bit_AVX512BITALG)
     847  	    set_feature (FEATURE_AVX512BITALG);
     848  	  if (ecx & bit_AVX512VPOPCNTDQ)
     849  	    set_feature (FEATURE_AVX512VPOPCNTDQ);
     850  	  if (edx & bit_AVX5124VNNIW)
     851  	    set_feature (FEATURE_AVX5124VNNIW);
     852  	  if (edx & bit_AVX5124FMAPS)
     853  	    set_feature (FEATURE_AVX5124FMAPS);
     854  	  if (edx & bit_AVX512VP2INTERSECT)
     855  	    set_feature (FEATURE_AVX512VP2INTERSECT);
     856  	  if (edx & bit_AVX512FP16)
     857  	    set_feature (FEATURE_AVX512FP16);
     858  	}
     859  
     860        __cpuid_count (7, 1, eax, ebx, ecx, edx);
     861        if (eax & bit_HRESET)
     862  	set_feature (FEATURE_HRESET);
     863        if (eax & bit_CMPCCXADD)
     864  	set_feature(FEATURE_CMPCCXADD);
     865        if (edx & bit_PREFETCHI)
     866  	set_feature (FEATURE_PREFETCHI);
     867        if (eax & bit_RAOINT)
     868  	set_feature (FEATURE_RAOINT);
     869        if (avx_usable)
     870  	{
     871  	  if (eax & bit_AVXVNNI)
     872  	    set_feature (FEATURE_AVXVNNI);
     873  	  if (eax & bit_AVXIFMA)
     874  	    set_feature (FEATURE_AVXIFMA);
     875  	  if (edx & bit_AVXVNNIINT8)
     876  	    set_feature (FEATURE_AVXVNNIINT8);
     877  	  if (edx & bit_AVXNECONVERT)
     878  	    set_feature (FEATURE_AVXNECONVERT);
     879  	}
     880        if (avx512_usable)
     881  	{
     882  	  if (eax & bit_AVX512BF16)
     883  	    set_feature (FEATURE_AVX512BF16);
     884  	}
     885        if (amx_usable)
     886  	{
     887  	  if (eax & bit_AMX_FP16)
     888  	    set_feature (FEATURE_AMX_FP16);
     889  	  if (edx & bit_AMX_COMPLEX)
     890  	    set_feature (FEATURE_AMX_COMPLEX);
     891  	}
     892      }
     893  
     894    /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
     895    if (max_cpuid_level >= 0xd)
     896      {
     897        __cpuid_count (0xd, 1, eax, ebx, ecx, edx);
     898        if (eax & bit_XSAVEOPT)
     899  	set_feature (FEATURE_XSAVEOPT);
     900        if (eax & bit_XSAVEC)
     901  	set_feature (FEATURE_XSAVEC);
     902        if (eax & bit_XSAVES)
     903  	set_feature (FEATURE_XSAVES);
     904      }
     905  
     906    /* Get Advanced Features at level 0x14 (eax = 0x14, ecx = 0). */
     907    if (max_cpuid_level >= 0x14)
     908      {
     909        __cpuid_count (0x14, 0, eax, ebx, ecx, edx);
     910        if (ebx & bit_PTWRITE)
     911  	set_feature (FEATURE_PTWRITE);
     912      }
     913  
     914    /* Get Advanced Features at level 0x19 (eax = 0x19).  */
     915    if (max_cpuid_level >= 0x19)
     916      {
     917        __cpuid (0x19, eax, ebx, ecx, edx);
     918        /* Check if OS support keylocker.  */
     919        if (ebx & bit_AESKLE)
     920  	{
     921  	  set_feature (FEATURE_AESKLE);
     922  	  if (ebx & bit_WIDEKL)
     923  	    set_feature (FEATURE_WIDEKL);
     924  	  if (has_kl)
     925  	    set_feature (FEATURE_KL);
     926  	}
     927      }
     928  
     929    /* Check cpuid level of extended features.  */
     930    __cpuid (0x80000000, ext_level, ebx, ecx, edx);
     931  
     932    cpu_model2->__cpu_ext_level = ext_level;
     933  
     934    if (ext_level >= 0x80000001)
     935      {
     936        __cpuid (0x80000001, eax, ebx, ecx, edx);
     937  
     938        if (ecx & bit_SSE4a)
     939  	set_feature (FEATURE_SSE4_A);
     940        if (ecx & bit_LAHF_LM)
     941  	set_feature (FEATURE_LAHF_LM);
     942        if (ecx & bit_ABM)
     943  	set_feature (FEATURE_ABM);
     944        if (ecx & bit_LWP)
     945  	set_feature (FEATURE_LWP);
     946        if (ecx & bit_TBM)
     947  	set_feature (FEATURE_TBM);
     948        if (ecx & bit_LZCNT)
     949  	set_feature (FEATURE_LZCNT);
     950        if (ecx & bit_PRFCHW)
     951  	set_feature (FEATURE_PRFCHW);
     952        if (ecx & bit_MWAITX)
     953  	set_feature (FEATURE_MWAITX);
     954  
     955        if (edx & bit_LM)
     956  	set_feature (FEATURE_LM);
     957        if (edx & bit_3DNOWP)
     958  	set_feature (FEATURE_3DNOWP);
     959        if (edx & bit_3DNOW)
     960  	set_feature (FEATURE_3DNOW);
     961  
     962        if (avx_usable)
     963  	{
     964  	  if (ecx & bit_FMA4)
     965  	    set_feature (FEATURE_FMA4);
     966  	  if (ecx & bit_XOP)
     967  	    set_feature (FEATURE_XOP);
     968  	}
     969      }
     970  
     971    if (ext_level >= 0x80000008)
     972      {
     973        __cpuid (0x80000008, eax, ebx, ecx, edx);
     974        if (ebx & bit_CLZERO)
     975  	set_feature (FEATURE_CLZERO);
     976        if (ebx & bit_WBNOINVD)
     977  	set_feature (FEATURE_WBNOINVD);
     978      }
     979  
     980  #undef set_feature
     981  }
     982  
     983  static inline int
     984  cpu_indicator_init (struct __processor_model *cpu_model,
     985  		    struct __processor_model2 *cpu_model2,
     986  		    unsigned int *cpu_features2)
     987  {
     988    unsigned int eax, ebx, ecx, edx;
     989  
     990    int max_level;
     991    unsigned int vendor;
     992    unsigned int model, family;
     993    unsigned int extended_model, extended_family;
     994  
     995    /* This function needs to run just once.  */
     996    if (cpu_model->__cpu_vendor)
     997      return 0;
     998  
     999    /* Assume cpuid insn present. Run in level 0 to get vendor id. */
    1000    if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
    1001      {
    1002        cpu_model->__cpu_vendor = VENDOR_OTHER;
    1003        return -1;
    1004      }
    1005  
    1006    vendor = ebx;
    1007    max_level = eax;
    1008  
    1009    if (max_level < 1)
    1010      {
    1011        cpu_model->__cpu_vendor = VENDOR_OTHER;
    1012        return -1;
    1013      }
    1014  
    1015    if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
    1016      {
    1017        cpu_model->__cpu_vendor = VENDOR_OTHER;
    1018        return -1;
    1019      }
    1020  
    1021    cpu_model2->__cpu_max_level = max_level;
    1022  
    1023    model = (eax >> 4) & 0x0f;
    1024    family = (eax >> 8) & 0x0f;
    1025    extended_model = (eax >> 12) & 0xf0;
    1026    extended_family = (eax >> 20) & 0xff;
    1027  
    1028    /* Find available features. */
    1029    get_available_features (cpu_model, cpu_model2, cpu_features2,
    1030  			  ecx, edx);
    1031  
    1032    if (vendor == signature_INTEL_ebx)
    1033      {
    1034        /* Adjust model and family for Intel CPUS. */
    1035        if (family == 0x0f)
    1036  	{
    1037  	  family += extended_family;
    1038  	  model += extended_model;
    1039  	}
    1040        else if (family == 0x06)
    1041  	model += extended_model;
    1042  
    1043        cpu_model2->__cpu_family = family;
    1044        cpu_model2->__cpu_model = model;
    1045  
    1046        /* Get CPU type.  */
    1047        get_intel_cpu (cpu_model, cpu_model2, cpu_features2);
    1048        cpu_model->__cpu_vendor = VENDOR_INTEL;
    1049      }
    1050    else if (vendor == signature_AMD_ebx)
    1051      {
    1052        /* Adjust model and family for AMD CPUS. */
    1053        if (family == 0x0f)
    1054  	{
    1055  	  family += extended_family;
    1056  	  model += extended_model;
    1057  	}
    1058  
    1059        cpu_model2->__cpu_family = family;
    1060        cpu_model2->__cpu_model = model;
    1061  
    1062        /* Get CPU type.  */
    1063        get_amd_cpu (cpu_model, cpu_model2, cpu_features2);
    1064        cpu_model->__cpu_vendor = VENDOR_AMD;
    1065      }
    1066    else if (vendor == signature_CENTAUR_ebx && family < 0x07)
    1067      cpu_model->__cpu_vendor = VENDOR_CENTAUR;
    1068    else if (vendor == signature_SHANGHAI_ebx
    1069  	   || vendor == signature_CENTAUR_ebx)
    1070      {
    1071        /* Adjust model and family for ZHAOXIN CPUS.  */
    1072        if (family == 0x07)
    1073  	model += extended_model;
    1074  
    1075        cpu_model2->__cpu_family = family;
    1076        cpu_model2->__cpu_model = model;
    1077  
    1078        /* Get CPU type.  */
    1079        get_zhaoxin_cpu (cpu_model, cpu_model2, cpu_features2);
    1080        cpu_model->__cpu_vendor = VENDOR_ZHAOXIN;
    1081      }
    1082    else if (vendor == signature_CYRIX_ebx)
    1083      cpu_model->__cpu_vendor = VENDOR_CYRIX;
    1084    else if (vendor == signature_NSC_ebx)
    1085      cpu_model->__cpu_vendor = VENDOR_NSC;
    1086    else
    1087      cpu_model->__cpu_vendor = VENDOR_OTHER;
    1088  
    1089    if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_LM)
    1090        && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE2))
    1091      {
    1092        CHECK___builtin_cpu_supports ("x86-64");
    1093        set_cpu_feature (cpu_model, cpu_features2,
    1094  		       FEATURE_X86_64_BASELINE);
    1095        if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_CMPXCHG16B)
    1096  	  && has_cpu_feature (cpu_model, cpu_features2, FEATURE_POPCNT)
    1097  	  && has_cpu_feature (cpu_model, cpu_features2, FEATURE_LAHF_LM)
    1098  	  && has_cpu_feature (cpu_model, cpu_features2, FEATURE_SSE4_2))
    1099  	{
    1100  	  CHECK___builtin_cpu_supports ("x86-64-v2");
    1101  	  set_cpu_feature (cpu_model, cpu_features2,
    1102  			   FEATURE_X86_64_V2);
    1103  	  if (has_cpu_feature (cpu_model, cpu_features2, FEATURE_AVX2)
    1104  	      && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI)
    1105  	      && has_cpu_feature (cpu_model, cpu_features2, FEATURE_BMI2)
    1106  	      && has_cpu_feature (cpu_model, cpu_features2, FEATURE_F16C)
    1107  	      && has_cpu_feature (cpu_model, cpu_features2, FEATURE_FMA)
    1108  	      && has_cpu_feature (cpu_model, cpu_features2,
    1109  				  FEATURE_LZCNT)
    1110  	      && has_cpu_feature (cpu_model, cpu_features2,
    1111  				  FEATURE_MOVBE))
    1112  	    {
    1113  	      CHECK___builtin_cpu_supports ("x86-64-v3");
    1114  	      set_cpu_feature (cpu_model, cpu_features2,
    1115  			       FEATURE_X86_64_V3);
    1116  	      if (has_cpu_feature (cpu_model, cpu_features2,
    1117  				   FEATURE_AVX512BW)
    1118  		  && has_cpu_feature (cpu_model, cpu_features2,
    1119  				      FEATURE_AVX512CD)
    1120  		  && has_cpu_feature (cpu_model, cpu_features2,
    1121  				      FEATURE_AVX512DQ)
    1122  		  && has_cpu_feature (cpu_model, cpu_features2,
    1123  				      FEATURE_AVX512VL))
    1124  		{
    1125  		  CHECK___builtin_cpu_supports ("x86-64-v4");
    1126  		  set_cpu_feature (cpu_model, cpu_features2,
    1127  				   FEATURE_X86_64_V4);
    1128  		}
    1129  	    }
    1130  	}
    1131      }
    1132  
    1133    gcc_assert (cpu_model->__cpu_vendor < VENDOR_MAX);
    1134    gcc_assert (cpu_model->__cpu_type < CPU_TYPE_MAX);
    1135    gcc_assert (cpu_model->__cpu_subtype < CPU_SUBTYPE_MAX);
    1136  
    1137    return 0;
    1138  }