138fd1498Szrj /* Get CPU type and Features for x86 processors.
238fd1498Szrj Copyright (C) 2012-2018 Free Software Foundation, Inc.
338fd1498Szrj Contributed by Sriraman Tallam (tmsriram@google.com)
438fd1498Szrj
538fd1498Szrj This file is part of GCC.
638fd1498Szrj
738fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
838fd1498Szrj the terms of the GNU General Public License as published by the Free
938fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1038fd1498Szrj version.
1138fd1498Szrj
1238fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1338fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1438fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1538fd1498Szrj for more details.
1638fd1498Szrj
1738fd1498Szrj Under Section 7 of GPL version 3, you are granted additional
1838fd1498Szrj permissions described in the GCC Runtime Library Exception, version
1938fd1498Szrj 3.1, as published by the Free Software Foundation.
2038fd1498Szrj
2138fd1498Szrj You should have received a copy of the GNU General Public License and
2238fd1498Szrj a copy of the GCC Runtime Library Exception along with this program;
2338fd1498Szrj see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2438fd1498Szrj <http://www.gnu.org/licenses/>. */
2538fd1498Szrj
2638fd1498Szrj #include "cpuid.h"
2738fd1498Szrj #include "tsystem.h"
2838fd1498Szrj #include "auto-target.h"
2938fd1498Szrj #include "cpuinfo.h"
3038fd1498Szrj
3138fd1498Szrj #ifdef HAVE_INIT_PRIORITY
3238fd1498Szrj #define CONSTRUCTOR_PRIORITY (101)
3338fd1498Szrj #else
3438fd1498Szrj #define CONSTRUCTOR_PRIORITY
3538fd1498Szrj #endif
3638fd1498Szrj
3738fd1498Szrj int __cpu_indicator_init (void)
3838fd1498Szrj __attribute__ ((constructor CONSTRUCTOR_PRIORITY));
3938fd1498Szrj
4038fd1498Szrj
4138fd1498Szrj struct __processor_model __cpu_model = { };
4238fd1498Szrj #ifndef SHARED
4338fd1498Szrj /* We want to move away from __cpu_model in libgcc_s.so.1 and the
4438fd1498Szrj size of __cpu_model is part of ABI. So, new features that don't
4538fd1498Szrj fit into __cpu_model.__cpu_features[0] go into extra variables
4638fd1498Szrj in libgcc.a only, preferrably hidden. */
4738fd1498Szrj unsigned int __cpu_features2;
4838fd1498Szrj #endif
4938fd1498Szrj
5038fd1498Szrj
5138fd1498Szrj /* Get the specific type of AMD CPU. */
5238fd1498Szrj
5338fd1498Szrj static void
get_amd_cpu(unsigned int family,unsigned int model)5438fd1498Szrj get_amd_cpu (unsigned int family, unsigned int model)
5538fd1498Szrj {
5638fd1498Szrj switch (family)
5738fd1498Szrj {
5838fd1498Szrj /* AMD Family 10h. */
5938fd1498Szrj case 0x10:
6038fd1498Szrj __cpu_model.__cpu_type = AMDFAM10H;
6138fd1498Szrj switch (model)
6238fd1498Szrj {
6338fd1498Szrj case 0x2:
6438fd1498Szrj /* Barcelona. */
6538fd1498Szrj __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
6638fd1498Szrj break;
6738fd1498Szrj case 0x4:
6838fd1498Szrj /* Shanghai. */
6938fd1498Szrj __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
7038fd1498Szrj break;
7138fd1498Szrj case 0x8:
7238fd1498Szrj /* Istanbul. */
7338fd1498Szrj __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
7438fd1498Szrj break;
7538fd1498Szrj default:
7638fd1498Szrj break;
7738fd1498Szrj }
7838fd1498Szrj break;
7938fd1498Szrj /* AMD Family 14h "btver1". */
8038fd1498Szrj case 0x14:
8138fd1498Szrj __cpu_model.__cpu_type = AMD_BTVER1;
8238fd1498Szrj break;
8338fd1498Szrj /* AMD Family 15h "Bulldozer". */
8438fd1498Szrj case 0x15:
8538fd1498Szrj __cpu_model.__cpu_type = AMDFAM15H;
86*58e805e6Szrj
87*58e805e6Szrj if (model == 0x2)
88*58e805e6Szrj __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
8938fd1498Szrj /* Bulldozer version 1. */
90*58e805e6Szrj else if (model <= 0xf)
9138fd1498Szrj __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
9238fd1498Szrj /* Bulldozer version 2 "Piledriver" */
93*58e805e6Szrj else if (model <= 0x2f)
9438fd1498Szrj __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
9538fd1498Szrj /* Bulldozer version 3 "Steamroller" */
96*58e805e6Szrj else if (model <= 0x4f)
9738fd1498Szrj __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
9838fd1498Szrj /* Bulldozer version 4 "Excavator" */
99*58e805e6Szrj else if (model <= 0x7f)
10038fd1498Szrj __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
10138fd1498Szrj break;
10238fd1498Szrj /* AMD Family 16h "btver2" */
10338fd1498Szrj case 0x16:
10438fd1498Szrj __cpu_model.__cpu_type = AMD_BTVER2;
10538fd1498Szrj break;
10638fd1498Szrj case 0x17:
10738fd1498Szrj __cpu_model.__cpu_type = AMDFAM17H;
10838fd1498Szrj /* AMD family 17h version 1. */
10938fd1498Szrj if (model <= 0x1f)
11038fd1498Szrj __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
11138fd1498Szrj break;
11238fd1498Szrj default:
11338fd1498Szrj break;
11438fd1498Szrj }
11538fd1498Szrj }
11638fd1498Szrj
11738fd1498Szrj /* Get the specific type of Intel CPU. */
11838fd1498Szrj
11938fd1498Szrj static void
get_intel_cpu(unsigned int family,unsigned int model,unsigned int brand_id)12038fd1498Szrj get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
12138fd1498Szrj {
12238fd1498Szrj /* Parse family and model only if brand ID is 0. */
12338fd1498Szrj if (brand_id == 0)
12438fd1498Szrj {
12538fd1498Szrj switch (family)
12638fd1498Szrj {
12738fd1498Szrj case 0x5:
12838fd1498Szrj /* Pentium. */
12938fd1498Szrj break;
13038fd1498Szrj case 0x6:
13138fd1498Szrj switch (model)
13238fd1498Szrj {
13338fd1498Szrj case 0x1c:
13438fd1498Szrj case 0x26:
13538fd1498Szrj /* Bonnell. */
13638fd1498Szrj __cpu_model.__cpu_type = INTEL_BONNELL;
13738fd1498Szrj break;
13838fd1498Szrj case 0x37:
13938fd1498Szrj case 0x4a:
14038fd1498Szrj case 0x4d:
14138fd1498Szrj case 0x5a:
14238fd1498Szrj case 0x5d:
14338fd1498Szrj /* Silvermont. */
14438fd1498Szrj __cpu_model.__cpu_type = INTEL_SILVERMONT;
14538fd1498Szrj break;
14638fd1498Szrj case 0x57:
14738fd1498Szrj /* Knights Landing. */
14838fd1498Szrj __cpu_model.__cpu_type = INTEL_KNL;
14938fd1498Szrj break;
15038fd1498Szrj case 0x85:
15138fd1498Szrj /* Knights Mill. */
15238fd1498Szrj __cpu_model.__cpu_type = INTEL_KNM;
15338fd1498Szrj break;
15438fd1498Szrj case 0x1a:
15538fd1498Szrj case 0x1e:
15638fd1498Szrj case 0x1f:
15738fd1498Szrj case 0x2e:
15838fd1498Szrj /* Nehalem. */
15938fd1498Szrj __cpu_model.__cpu_type = INTEL_COREI7;
16038fd1498Szrj __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
16138fd1498Szrj break;
16238fd1498Szrj case 0x25:
16338fd1498Szrj case 0x2c:
16438fd1498Szrj case 0x2f:
16538fd1498Szrj /* Westmere. */
16638fd1498Szrj __cpu_model.__cpu_type = INTEL_COREI7;
16738fd1498Szrj __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
16838fd1498Szrj break;
16938fd1498Szrj case 0x2a:
17038fd1498Szrj case 0x2d:
17138fd1498Szrj /* Sandy Bridge. */
17238fd1498Szrj __cpu_model.__cpu_type = INTEL_COREI7;
17338fd1498Szrj __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
17438fd1498Szrj break;
17538fd1498Szrj case 0x3a:
17638fd1498Szrj case 0x3e:
17738fd1498Szrj /* Ivy Bridge. */
17838fd1498Szrj __cpu_model.__cpu_type = INTEL_COREI7;
17938fd1498Szrj __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
18038fd1498Szrj break;
18138fd1498Szrj case 0x3c:
18238fd1498Szrj case 0x3f:
18338fd1498Szrj case 0x45:
18438fd1498Szrj case 0x46:
18538fd1498Szrj /* Haswell. */
18638fd1498Szrj __cpu_model.__cpu_type = INTEL_COREI7;
18738fd1498Szrj __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
18838fd1498Szrj break;
18938fd1498Szrj case 0x3d:
19038fd1498Szrj case 0x47:
19138fd1498Szrj case 0x4f:
19238fd1498Szrj case 0x56:
19338fd1498Szrj /* Broadwell. */
19438fd1498Szrj __cpu_model.__cpu_type = INTEL_COREI7;
19538fd1498Szrj __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
19638fd1498Szrj break;
19738fd1498Szrj case 0x4e:
19838fd1498Szrj case 0x5e:
19938fd1498Szrj /* Skylake. */
20038fd1498Szrj case 0x8e:
20138fd1498Szrj case 0x9e:
20238fd1498Szrj /* Kaby Lake. */
20338fd1498Szrj __cpu_model.__cpu_type = INTEL_COREI7;
20438fd1498Szrj __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
20538fd1498Szrj break;
20638fd1498Szrj case 0x55:
20738fd1498Szrj /* Skylake with AVX-512 support. */
20838fd1498Szrj __cpu_model.__cpu_type = INTEL_COREI7;
20938fd1498Szrj __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
21038fd1498Szrj break;
21138fd1498Szrj case 0x66:
21238fd1498Szrj /* Cannon Lake. */
21338fd1498Szrj __cpu_model.__cpu_type = INTEL_COREI7;
21438fd1498Szrj __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
21538fd1498Szrj break;
21638fd1498Szrj case 0x17:
21738fd1498Szrj case 0x1d:
21838fd1498Szrj /* Penryn. */
21938fd1498Szrj case 0x0f:
22038fd1498Szrj /* Merom. */
22138fd1498Szrj __cpu_model.__cpu_type = INTEL_CORE2;
22238fd1498Szrj break;
22338fd1498Szrj default:
22438fd1498Szrj break;
22538fd1498Szrj }
22638fd1498Szrj break;
22738fd1498Szrj default:
22838fd1498Szrj /* We have no idea. */
22938fd1498Szrj break;
23038fd1498Szrj }
23138fd1498Szrj }
23238fd1498Szrj }
23338fd1498Szrj
23438fd1498Szrj /* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
23538fd1498Szrj the max possible level of CPUID insn. */
23638fd1498Szrj static void
get_available_features(unsigned int ecx,unsigned int edx,int max_cpuid_level)23738fd1498Szrj get_available_features (unsigned int ecx, unsigned int edx,
23838fd1498Szrj int max_cpuid_level)
23938fd1498Szrj {
24038fd1498Szrj unsigned int eax, ebx;
24138fd1498Szrj unsigned int ext_level;
24238fd1498Szrj
24338fd1498Szrj unsigned int features = 0;
24438fd1498Szrj unsigned int features2 = 0;
24538fd1498Szrj
24638fd1498Szrj /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
24738fd1498Szrj #define XCR_XFEATURE_ENABLED_MASK 0x0
24838fd1498Szrj #define XSTATE_FP 0x1
24938fd1498Szrj #define XSTATE_SSE 0x2
25038fd1498Szrj #define XSTATE_YMM 0x4
25138fd1498Szrj #define XSTATE_OPMASK 0x20
25238fd1498Szrj #define XSTATE_ZMM 0x40
25338fd1498Szrj #define XSTATE_HI_ZMM 0x80
25438fd1498Szrj
25538fd1498Szrj #define XCR_AVX_ENABLED_MASK \
25638fd1498Szrj (XSTATE_SSE | XSTATE_YMM)
25738fd1498Szrj #define XCR_AVX512F_ENABLED_MASK \
25838fd1498Szrj (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
25938fd1498Szrj
26038fd1498Szrj /* Check if AVX and AVX512 are usable. */
26138fd1498Szrj int avx_usable = 0;
26238fd1498Szrj int avx512_usable = 0;
26338fd1498Szrj if ((ecx & bit_OSXSAVE))
26438fd1498Szrj {
26538fd1498Szrj /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
26638fd1498Szrj ZMM16-ZMM31 states are supported by OSXSAVE. */
26738fd1498Szrj unsigned int xcrlow;
26838fd1498Szrj unsigned int xcrhigh;
26938fd1498Szrj asm (".byte 0x0f, 0x01, 0xd0"
27038fd1498Szrj : "=a" (xcrlow), "=d" (xcrhigh)
27138fd1498Szrj : "c" (XCR_XFEATURE_ENABLED_MASK));
27238fd1498Szrj if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
27338fd1498Szrj {
27438fd1498Szrj avx_usable = 1;
27538fd1498Szrj avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
27638fd1498Szrj == XCR_AVX512F_ENABLED_MASK);
27738fd1498Szrj }
27838fd1498Szrj }
27938fd1498Szrj
28038fd1498Szrj #define set_feature(f) \
28138fd1498Szrj do \
28238fd1498Szrj { \
28338fd1498Szrj if (f < 32) \
28438fd1498Szrj features |= (1U << (f & 31)); \
28538fd1498Szrj else \
28638fd1498Szrj features2 |= (1U << ((f - 32) & 31)); \
28738fd1498Szrj } \
28838fd1498Szrj while (0)
28938fd1498Szrj
29038fd1498Szrj if (edx & bit_CMOV)
29138fd1498Szrj set_feature (FEATURE_CMOV);
29238fd1498Szrj if (edx & bit_MMX)
29338fd1498Szrj set_feature (FEATURE_MMX);
29438fd1498Szrj if (edx & bit_SSE)
29538fd1498Szrj set_feature (FEATURE_SSE);
29638fd1498Szrj if (edx & bit_SSE2)
29738fd1498Szrj set_feature (FEATURE_SSE2);
29838fd1498Szrj if (ecx & bit_POPCNT)
29938fd1498Szrj set_feature (FEATURE_POPCNT);
30038fd1498Szrj if (ecx & bit_AES)
30138fd1498Szrj set_feature (FEATURE_AES);
30238fd1498Szrj if (ecx & bit_PCLMUL)
30338fd1498Szrj set_feature (FEATURE_PCLMUL);
30438fd1498Szrj if (ecx & bit_SSE3)
30538fd1498Szrj set_feature (FEATURE_SSE3);
30638fd1498Szrj if (ecx & bit_SSSE3)
30738fd1498Szrj set_feature (FEATURE_SSSE3);
30838fd1498Szrj if (ecx & bit_SSE4_1)
30938fd1498Szrj set_feature (FEATURE_SSE4_1);
31038fd1498Szrj if (ecx & bit_SSE4_2)
31138fd1498Szrj set_feature (FEATURE_SSE4_2);
31238fd1498Szrj if (avx_usable)
31338fd1498Szrj {
31438fd1498Szrj if (ecx & bit_AVX)
31538fd1498Szrj set_feature (FEATURE_AVX);
31638fd1498Szrj if (ecx & bit_FMA)
31738fd1498Szrj set_feature (FEATURE_FMA);
31838fd1498Szrj }
31938fd1498Szrj
32038fd1498Szrj /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
32138fd1498Szrj if (max_cpuid_level >= 7)
32238fd1498Szrj {
32338fd1498Szrj __cpuid_count (7, 0, eax, ebx, ecx, edx);
32438fd1498Szrj if (ebx & bit_BMI)
32538fd1498Szrj set_feature (FEATURE_BMI);
32638fd1498Szrj if (avx_usable)
32738fd1498Szrj {
32838fd1498Szrj if (ebx & bit_AVX2)
32938fd1498Szrj set_feature (FEATURE_AVX2);
33038fd1498Szrj }
33138fd1498Szrj if (ebx & bit_BMI2)
33238fd1498Szrj set_feature (FEATURE_BMI2);
33338fd1498Szrj if (avx512_usable)
33438fd1498Szrj {
33538fd1498Szrj if (ebx & bit_AVX512F)
33638fd1498Szrj set_feature (FEATURE_AVX512F);
33738fd1498Szrj if (ebx & bit_AVX512VL)
33838fd1498Szrj set_feature (FEATURE_AVX512VL);
33938fd1498Szrj if (ebx & bit_AVX512BW)
34038fd1498Szrj set_feature (FEATURE_AVX512BW);
34138fd1498Szrj if (ebx & bit_AVX512DQ)
34238fd1498Szrj set_feature (FEATURE_AVX512DQ);
34338fd1498Szrj if (ebx & bit_AVX512CD)
34438fd1498Szrj set_feature (FEATURE_AVX512CD);
34538fd1498Szrj if (ebx & bit_AVX512PF)
34638fd1498Szrj set_feature (FEATURE_AVX512PF);
34738fd1498Szrj if (ebx & bit_AVX512ER)
34838fd1498Szrj set_feature (FEATURE_AVX512ER);
34938fd1498Szrj if (ebx & bit_AVX512IFMA)
35038fd1498Szrj set_feature (FEATURE_AVX512IFMA);
35138fd1498Szrj if (ecx & bit_AVX512VBMI)
35238fd1498Szrj set_feature (FEATURE_AVX512VBMI);
35338fd1498Szrj if (ecx & bit_AVX512VBMI2)
35438fd1498Szrj set_feature (FEATURE_AVX512VBMI2);
35538fd1498Szrj if (ecx & bit_GFNI)
35638fd1498Szrj set_feature (FEATURE_GFNI);
35738fd1498Szrj if (ecx & bit_VPCLMULQDQ)
35838fd1498Szrj set_feature (FEATURE_VPCLMULQDQ);
35938fd1498Szrj if (ecx & bit_AVX512VNNI)
36038fd1498Szrj set_feature (FEATURE_AVX512VNNI);
36138fd1498Szrj if (ecx & bit_AVX512BITALG)
36238fd1498Szrj set_feature (FEATURE_AVX512BITALG);
36338fd1498Szrj if (ecx & bit_AVX512VPOPCNTDQ)
36438fd1498Szrj set_feature (FEATURE_AVX512VPOPCNTDQ);
36538fd1498Szrj if (edx & bit_AVX5124VNNIW)
36638fd1498Szrj set_feature (FEATURE_AVX5124VNNIW);
36738fd1498Szrj if (edx & bit_AVX5124FMAPS)
36838fd1498Szrj set_feature (FEATURE_AVX5124FMAPS);
36938fd1498Szrj }
37038fd1498Szrj }
37138fd1498Szrj
37238fd1498Szrj /* Check cpuid level of extended features. */
37338fd1498Szrj __cpuid (0x80000000, ext_level, ebx, ecx, edx);
37438fd1498Szrj
37538fd1498Szrj if (ext_level >= 0x80000001)
37638fd1498Szrj {
37738fd1498Szrj __cpuid (0x80000001, eax, ebx, ecx, edx);
37838fd1498Szrj
37938fd1498Szrj if (ecx & bit_SSE4a)
38038fd1498Szrj set_feature (FEATURE_SSE4_A);
38138fd1498Szrj if (avx_usable)
38238fd1498Szrj {
38338fd1498Szrj if (ecx & bit_FMA4)
38438fd1498Szrj set_feature (FEATURE_FMA4);
38538fd1498Szrj if (ecx & bit_XOP)
38638fd1498Szrj set_feature (FEATURE_XOP);
38738fd1498Szrj }
38838fd1498Szrj }
38938fd1498Szrj
39038fd1498Szrj __cpu_model.__cpu_features[0] = features;
39138fd1498Szrj #ifndef SHARED
39238fd1498Szrj __cpu_features2 = features2;
39338fd1498Szrj #else
39438fd1498Szrj (void) features2;
39538fd1498Szrj #endif
39638fd1498Szrj }
39738fd1498Szrj
39838fd1498Szrj /* A constructor function that is sets __cpu_model and __cpu_features with
39938fd1498Szrj the right values. This needs to run only once. This constructor is
40038fd1498Szrj given the highest priority and it should run before constructors without
40138fd1498Szrj the priority set. However, it still runs after ifunc initializers and
40238fd1498Szrj needs to be called explicitly there. */
40338fd1498Szrj
40438fd1498Szrj int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
__cpu_indicator_init(void)40538fd1498Szrj __cpu_indicator_init (void)
40638fd1498Szrj {
40738fd1498Szrj unsigned int eax, ebx, ecx, edx;
40838fd1498Szrj
40938fd1498Szrj int max_level;
41038fd1498Szrj unsigned int vendor;
41138fd1498Szrj unsigned int model, family, brand_id;
41238fd1498Szrj unsigned int extended_model, extended_family;
41338fd1498Szrj
41438fd1498Szrj /* This function needs to run just once. */
41538fd1498Szrj if (__cpu_model.__cpu_vendor)
41638fd1498Szrj return 0;
41738fd1498Szrj
41838fd1498Szrj /* Assume cpuid insn present. Run in level 0 to get vendor id. */
41938fd1498Szrj if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
42038fd1498Szrj {
42138fd1498Szrj __cpu_model.__cpu_vendor = VENDOR_OTHER;
42238fd1498Szrj return -1;
42338fd1498Szrj }
42438fd1498Szrj
42538fd1498Szrj vendor = ebx;
42638fd1498Szrj max_level = eax;
42738fd1498Szrj
42838fd1498Szrj if (max_level < 1)
42938fd1498Szrj {
43038fd1498Szrj __cpu_model.__cpu_vendor = VENDOR_OTHER;
43138fd1498Szrj return -1;
43238fd1498Szrj }
43338fd1498Szrj
43438fd1498Szrj if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
43538fd1498Szrj {
43638fd1498Szrj __cpu_model.__cpu_vendor = VENDOR_OTHER;
43738fd1498Szrj return -1;
43838fd1498Szrj }
43938fd1498Szrj
44038fd1498Szrj model = (eax >> 4) & 0x0f;
44138fd1498Szrj family = (eax >> 8) & 0x0f;
44238fd1498Szrj brand_id = ebx & 0xff;
44338fd1498Szrj extended_model = (eax >> 12) & 0xf0;
44438fd1498Szrj extended_family = (eax >> 20) & 0xff;
44538fd1498Szrj
44638fd1498Szrj if (vendor == signature_INTEL_ebx)
44738fd1498Szrj {
44838fd1498Szrj /* Adjust model and family for Intel CPUS. */
44938fd1498Szrj if (family == 0x0f)
45038fd1498Szrj {
45138fd1498Szrj family += extended_family;
45238fd1498Szrj model += extended_model;
45338fd1498Szrj }
45438fd1498Szrj else if (family == 0x06)
45538fd1498Szrj model += extended_model;
45638fd1498Szrj
45738fd1498Szrj /* Get CPU type. */
45838fd1498Szrj get_intel_cpu (family, model, brand_id);
45938fd1498Szrj /* Find available features. */
46038fd1498Szrj get_available_features (ecx, edx, max_level);
46138fd1498Szrj __cpu_model.__cpu_vendor = VENDOR_INTEL;
46238fd1498Szrj }
46338fd1498Szrj else if (vendor == signature_AMD_ebx)
46438fd1498Szrj {
46538fd1498Szrj /* Adjust model and family for AMD CPUS. */
46638fd1498Szrj if (family == 0x0f)
46738fd1498Szrj {
46838fd1498Szrj family += extended_family;
46938fd1498Szrj model += extended_model;
47038fd1498Szrj }
47138fd1498Szrj
47238fd1498Szrj /* Get CPU type. */
47338fd1498Szrj get_amd_cpu (family, model);
47438fd1498Szrj /* Find available features. */
47538fd1498Szrj get_available_features (ecx, edx, max_level);
47638fd1498Szrj __cpu_model.__cpu_vendor = VENDOR_AMD;
47738fd1498Szrj }
47838fd1498Szrj else
47938fd1498Szrj __cpu_model.__cpu_vendor = VENDOR_OTHER;
48038fd1498Szrj
48138fd1498Szrj gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
48238fd1498Szrj gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
48338fd1498Szrj gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
48438fd1498Szrj
48538fd1498Szrj return 0;
48638fd1498Szrj }
48738fd1498Szrj
48838fd1498Szrj #if defined SHARED && defined USE_ELF_SYMVER
48938fd1498Szrj __asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0");
49038fd1498Szrj __asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0");
49138fd1498Szrj #endif
492