1234287Sdim/*===---- cpuid.h - X86 cpu model detection --------------------------------===
2234287Sdim *
3353358Sdim * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim * See https://llvm.org/LICENSE.txt for license information.
5353358Sdim * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6234287Sdim *
7234287Sdim *===-----------------------------------------------------------------------===
8234287Sdim */
9234287Sdim
10234287Sdim#if !(__x86_64__ || __i386__)
11234287Sdim#error this header is for x86 only
12234287Sdim#endif
13234287Sdim
14280031Sdim/* Responses identification request with %eax 0 */
15280031Sdim/* AMD:     "AuthenticAMD" */
16280031Sdim#define signature_AMD_ebx 0x68747541
17280031Sdim#define signature_AMD_edx 0x69746e65
18280031Sdim#define signature_AMD_ecx 0x444d4163
19280031Sdim/* CENTAUR: "CentaurHauls" */
20280031Sdim#define signature_CENTAUR_ebx 0x746e6543
21280031Sdim#define signature_CENTAUR_edx 0x48727561
22280031Sdim#define signature_CENTAUR_ecx 0x736c7561
23280031Sdim/* CYRIX:   "CyrixInstead" */
24280031Sdim#define signature_CYRIX_ebx 0x69727943
25280031Sdim#define signature_CYRIX_edx 0x736e4978
26280031Sdim#define signature_CYRIX_ecx 0x64616574
27280031Sdim/* INTEL:   "GenuineIntel" */
28280031Sdim#define signature_INTEL_ebx 0x756e6547
29280031Sdim#define signature_INTEL_edx 0x49656e69
30280031Sdim#define signature_INTEL_ecx 0x6c65746e
31280031Sdim/* TM1:     "TransmetaCPU" */
32280031Sdim#define signature_TM1_ebx 0x6e617254
33280031Sdim#define signature_TM1_edx 0x74656d73
34280031Sdim#define signature_TM1_ecx 0x55504361
35280031Sdim/* TM2:     "GenuineTMx86" */
36280031Sdim#define signature_TM2_ebx 0x756e6547
37280031Sdim#define signature_TM2_edx 0x54656e69
38280031Sdim#define signature_TM2_ecx 0x3638784d
39280031Sdim/* NSC:     "Geode by NSC" */
40280031Sdim#define signature_NSC_ebx 0x646f6547
41360784Sdim#define signature_NSC_edx 0x79622065
42360784Sdim#define signature_NSC_ecx 0x43534e20
43280031Sdim/* NEXGEN:  "NexGenDriven" */
44280031Sdim#define signature_NEXGEN_ebx 0x4778654e
45280031Sdim#define signature_NEXGEN_edx 0x72446e65
46280031Sdim#define signature_NEXGEN_ecx 0x6e657669
47280031Sdim/* RISE:    "RiseRiseRise" */
48280031Sdim#define signature_RISE_ebx 0x65736952
49280031Sdim#define signature_RISE_edx 0x65736952
50280031Sdim#define signature_RISE_ecx 0x65736952
51280031Sdim/* SIS:     "SiS SiS SiS " */
52280031Sdim#define signature_SIS_ebx 0x20536953
53280031Sdim#define signature_SIS_edx 0x20536953
54280031Sdim#define signature_SIS_ecx 0x20536953
55280031Sdim/* UMC:     "UMC UMC UMC " */
56280031Sdim#define signature_UMC_ebx 0x20434d55
57280031Sdim#define signature_UMC_edx 0x20434d55
58280031Sdim#define signature_UMC_ecx 0x20434d55
59280031Sdim/* VIA:     "VIA VIA VIA " */
60280031Sdim#define signature_VIA_ebx 0x20414956
61280031Sdim#define signature_VIA_edx 0x20414956
62280031Sdim#define signature_VIA_ecx 0x20414956
63280031Sdim/* VORTEX:  "Vortex86 SoC" */
64280031Sdim#define signature_VORTEX_ebx 0x74726f56
65280031Sdim#define signature_VORTEX_edx 0x36387865
66280031Sdim#define signature_VORTEX_ecx 0x436f5320
67280031Sdim
68321369Sdim/* Features in %ecx for leaf 1 */
69253802Sdim#define bit_SSE3        0x00000001
70253802Sdim#define bit_PCLMULQDQ   0x00000002
71309124Sdim#define bit_PCLMUL      bit_PCLMULQDQ   /* for gcc compat */
72253802Sdim#define bit_DTES64      0x00000004
73253802Sdim#define bit_MONITOR     0x00000008
74253802Sdim#define bit_DSCPL       0x00000010
75253802Sdim#define bit_VMX         0x00000020
76253802Sdim#define bit_SMX         0x00000040
77253802Sdim#define bit_EIST        0x00000080
78253802Sdim#define bit_TM2         0x00000100
79253802Sdim#define bit_SSSE3       0x00000200
80253802Sdim#define bit_CNXTID      0x00000400
81253802Sdim#define bit_FMA         0x00001000
82253802Sdim#define bit_CMPXCHG16B  0x00002000
83253802Sdim#define bit_xTPR        0x00004000
84253802Sdim#define bit_PDCM        0x00008000
85253802Sdim#define bit_PCID        0x00020000
86253802Sdim#define bit_DCA         0x00040000
87253802Sdim#define bit_SSE41       0x00080000
88309124Sdim#define bit_SSE4_1      bit_SSE41       /* for gcc compat */
89253802Sdim#define bit_SSE42       0x00100000
90309124Sdim#define bit_SSE4_2      bit_SSE42       /* for gcc compat */
91253802Sdim#define bit_x2APIC      0x00200000
92253802Sdim#define bit_MOVBE       0x00400000
93253802Sdim#define bit_POPCNT      0x00800000
94253802Sdim#define bit_TSCDeadline 0x01000000
95253802Sdim#define bit_AESNI       0x02000000
96309124Sdim#define bit_AES         bit_AESNI       /* for gcc compat */
97253802Sdim#define bit_XSAVE       0x04000000
98253802Sdim#define bit_OSXSAVE     0x08000000
99253802Sdim#define bit_AVX         0x10000000
100309124Sdim#define bit_F16C        0x20000000
101280031Sdim#define bit_RDRND       0x40000000
102253802Sdim
103321369Sdim/* Features in %edx for leaf 1 */
104253802Sdim#define bit_FPU         0x00000001
105253802Sdim#define bit_VME         0x00000002
106253802Sdim#define bit_DE          0x00000004
107253802Sdim#define bit_PSE         0x00000008
108253802Sdim#define bit_TSC         0x00000010
109253802Sdim#define bit_MSR         0x00000020
110253802Sdim#define bit_PAE         0x00000040
111253802Sdim#define bit_MCE         0x00000080
112253802Sdim#define bit_CX8         0x00000100
113309124Sdim#define bit_CMPXCHG8B   bit_CX8         /* for gcc compat */
114253802Sdim#define bit_APIC        0x00000200
115253802Sdim#define bit_SEP         0x00000800
116253802Sdim#define bit_MTRR        0x00001000
117253802Sdim#define bit_PGE         0x00002000
118253802Sdim#define bit_MCA         0x00004000
119253802Sdim#define bit_CMOV        0x00008000
120253802Sdim#define bit_PAT         0x00010000
121253802Sdim#define bit_PSE36       0x00020000
122253802Sdim#define bit_PSN         0x00040000
123253802Sdim#define bit_CLFSH       0x00080000
124253802Sdim#define bit_DS          0x00200000
125253802Sdim#define bit_ACPI        0x00400000
126253802Sdim#define bit_MMX         0x00800000
127253802Sdim#define bit_FXSR        0x01000000
128309124Sdim#define bit_FXSAVE      bit_FXSR        /* for gcc compat */
129253802Sdim#define bit_SSE         0x02000000
130253802Sdim#define bit_SSE2        0x04000000
131253802Sdim#define bit_SS          0x08000000
132253802Sdim#define bit_HTT         0x10000000
133253802Sdim#define bit_TM          0x20000000
134253802Sdim#define bit_PBE         0x80000000
135253802Sdim
136321369Sdim/* Features in %ebx for leaf 7 sub-leaf 0 */
137253802Sdim#define bit_FSGSBASE    0x00000001
138321369Sdim#define bit_SGX         0x00000004
139321369Sdim#define bit_BMI         0x00000008
140321369Sdim#define bit_HLE         0x00000010
141321369Sdim#define bit_AVX2        0x00000020
142253802Sdim#define bit_SMEP        0x00000080
143321369Sdim#define bit_BMI2        0x00000100
144253802Sdim#define bit_ENH_MOVSB   0x00000200
145341825Sdim#define bit_INVPCID     0x00000400
146321369Sdim#define bit_RTM         0x00000800
147321369Sdim#define bit_MPX         0x00004000
148321369Sdim#define bit_AVX512F     0x00010000
149321369Sdim#define bit_AVX512DQ    0x00020000
150321369Sdim#define bit_RDSEED      0x00040000
151321369Sdim#define bit_ADX         0x00080000
152321369Sdim#define bit_AVX512IFMA  0x00200000
153321369Sdim#define bit_CLFLUSHOPT  0x00800000
154321369Sdim#define bit_CLWB        0x01000000
155321369Sdim#define bit_AVX512PF    0x04000000
156341825Sdim#define bit_AVX512ER    0x08000000
157321369Sdim#define bit_AVX512CD    0x10000000
158321369Sdim#define bit_SHA         0x20000000
159321369Sdim#define bit_AVX512BW    0x40000000
160321369Sdim#define bit_AVX512VL    0x80000000
161253802Sdim
162321369Sdim/* Features in %ecx for leaf 7 sub-leaf 0 */
163327952Sdim#define bit_PREFTCHWT1       0x00000001
164327952Sdim#define bit_AVX512VBMI       0x00000002
165327952Sdim#define bit_PKU              0x00000004
166327952Sdim#define bit_OSPKE            0x00000010
167341825Sdim#define bit_WAITPKG          0x00000020
168327952Sdim#define bit_AVX512VBMI2      0x00000040
169327952Sdim#define bit_SHSTK            0x00000080
170327952Sdim#define bit_GFNI             0x00000100
171327952Sdim#define bit_VAES             0x00000200
172327952Sdim#define bit_VPCLMULQDQ       0x00000400
173327952Sdim#define bit_AVX512VNNI       0x00000800
174327952Sdim#define bit_AVX512BITALG     0x00001000
175321369Sdim#define bit_AVX512VPOPCNTDQ  0x00004000
176327952Sdim#define bit_RDPID            0x00400000
177341825Sdim#define bit_CLDEMOTE         0x02000000
178341825Sdim#define bit_MOVDIRI          0x08000000
179341825Sdim#define bit_MOVDIR64B        0x10000000
180353358Sdim#define bit_ENQCMD           0x20000000
181321369Sdim
182321369Sdim/* Features in %edx for leaf 7 sub-leaf 0 */
183321369Sdim#define bit_AVX5124VNNIW  0x00000004
184321369Sdim#define bit_AVX5124FMAPS  0x00000008
185341825Sdim#define bit_PCONFIG       0x00040000
186327952Sdim#define bit_IBT           0x00100000
187321369Sdim
188353358Sdim/* Features in %eax for leaf 7 sub-leaf 1 */
189353358Sdim#define bit_AVX512BF16    0x00000020
190353358Sdim
191321369Sdim/* Features in %eax for leaf 13 sub-leaf 1 */
192321369Sdim#define bit_XSAVEOPT    0x00000001
193321369Sdim#define bit_XSAVEC      0x00000002
194321369Sdim#define bit_XSAVES      0x00000008
195321369Sdim
196341825Sdim/* Features in %eax for leaf 0x14 sub-leaf 0 */
197341825Sdim#define bit_PTWRITE     0x00000010
198341825Sdim
199321369Sdim/* Features in %ecx for leaf 0x80000001 */
200321369Sdim#define bit_LAHF_LM     0x00000001
201321369Sdim#define bit_ABM         0x00000020
202327952Sdim#define bit_LZCNT       bit_ABM        /* for gcc compat */
203321369Sdim#define bit_SSE4a       0x00000040
204321369Sdim#define bit_PRFCHW      0x00000100
205321369Sdim#define bit_XOP         0x00000800
206321369Sdim#define bit_LWP         0x00008000
207321369Sdim#define bit_FMA4        0x00010000
208321369Sdim#define bit_TBM         0x00200000
209321369Sdim#define bit_MWAITX      0x20000000
210321369Sdim
211321369Sdim/* Features in %edx for leaf 0x80000001 */
212321369Sdim#define bit_MMXEXT      0x00400000
213321369Sdim#define bit_LM          0x20000000
214321369Sdim#define bit_3DNOWP      0x40000000
215321369Sdim#define bit_3DNOW       0x80000000
216321369Sdim
217341825Sdim/* Features in %ebx for leaf 0x80000008 */
218321369Sdim#define bit_CLZERO      0x00000001
219341825Sdim#define bit_WBNOINVD    0x00000200
220321369Sdim
221321369Sdim
222253802Sdim#if __i386__
223321369Sdim#define __cpuid(__leaf, __eax, __ebx, __ecx, __edx) \
224280031Sdim    __asm("cpuid" : "=a"(__eax), "=b" (__ebx), "=c"(__ecx), "=d"(__edx) \
225321369Sdim                  : "0"(__leaf))
226280031Sdim
227321369Sdim#define __cpuid_count(__leaf, __count, __eax, __ebx, __ecx, __edx) \
228280031Sdim    __asm("cpuid" : "=a"(__eax), "=b" (__ebx), "=c"(__ecx), "=d"(__edx) \
229321369Sdim                  : "0"(__leaf), "2"(__count))
230280031Sdim#else
231280031Sdim/* x86-64 uses %rbx as the base register, so preserve it. */
232321369Sdim#define __cpuid(__leaf, __eax, __ebx, __ecx, __edx) \
233280031Sdim    __asm("  xchgq  %%rbx,%q1\n" \
234253802Sdim          "  cpuid\n" \
235280031Sdim          "  xchgq  %%rbx,%q1" \
236253802Sdim        : "=a"(__eax), "=r" (__ebx), "=c"(__ecx), "=d"(__edx) \
237321369Sdim        : "0"(__leaf))
238253802Sdim
239321369Sdim#define __cpuid_count(__leaf, __count, __eax, __ebx, __ecx, __edx) \
240280031Sdim    __asm("  xchgq  %%rbx,%q1\n" \
241253802Sdim          "  cpuid\n" \
242280031Sdim          "  xchgq  %%rbx,%q1" \
243253802Sdim        : "=a"(__eax), "=r" (__ebx), "=c"(__ecx), "=d"(__edx) \
244321369Sdim        : "0"(__leaf), "2"(__count))
245253802Sdim#endif
246253802Sdim
247321369Sdimstatic __inline int __get_cpuid_max (unsigned int __leaf, unsigned int *__sig)
248253802Sdim{
249253802Sdim    unsigned int __eax, __ebx, __ecx, __edx;
250253802Sdim#if __i386__
251253802Sdim    int __cpuid_supported;
252253802Sdim
253253802Sdim    __asm("  pushfl\n"
254253802Sdim          "  popl   %%eax\n"
255253802Sdim          "  movl   %%eax,%%ecx\n"
256253802Sdim          "  xorl   $0x00200000,%%eax\n"
257253802Sdim          "  pushl  %%eax\n"
258253802Sdim          "  popfl\n"
259253802Sdim          "  pushfl\n"
260253802Sdim          "  popl   %%eax\n"
261253802Sdim          "  movl   $0,%0\n"
262253802Sdim          "  cmpl   %%eax,%%ecx\n"
263253802Sdim          "  je     1f\n"
264253802Sdim          "  movl   $1,%0\n"
265253802Sdim          "1:"
266253802Sdim        : "=r" (__cpuid_supported) : : "eax", "ecx");
267253802Sdim    if (!__cpuid_supported)
268253802Sdim        return 0;
269253802Sdim#endif
270253802Sdim
271321369Sdim    __cpuid(__leaf, __eax, __ebx, __ecx, __edx);
272253802Sdim    if (__sig)
273253802Sdim        *__sig = __ebx;
274253802Sdim    return __eax;
275253802Sdim}
276321369Sdim
277321369Sdimstatic __inline int __get_cpuid (unsigned int __leaf, unsigned int *__eax,
278321369Sdim                                 unsigned int *__ebx, unsigned int *__ecx,
279321369Sdim                                 unsigned int *__edx)
280321369Sdim{
281321369Sdim    unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0);
282321369Sdim
283321369Sdim    if (__max_leaf == 0 || __max_leaf < __leaf)
284321369Sdim        return 0;
285321369Sdim
286321369Sdim    __cpuid(__leaf, *__eax, *__ebx, *__ecx, *__edx);
287321369Sdim    return 1;
288321369Sdim}
289321369Sdim
290321369Sdimstatic __inline int __get_cpuid_count (unsigned int __leaf,
291321369Sdim                                       unsigned int __subleaf,
292321369Sdim                                       unsigned int *__eax, unsigned int *__ebx,
293321369Sdim                                       unsigned int *__ecx, unsigned int *__edx)
294321369Sdim{
295321369Sdim    unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0);
296321369Sdim
297321369Sdim    if (__max_leaf == 0 || __max_leaf < __leaf)
298321369Sdim        return 0;
299321369Sdim
300321369Sdim    __cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
301321369Sdim    return 1;
302321369Sdim}
303