1 /*
2 * Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 *
4 * This file is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 3, or (at your option) any
7 * later version.
8 *
9 * This file is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * Under Section 7 of GPL version 3, you are granted additional
15 * permissions described in the GCC Runtime Library Exception, version
16 * 3.1, as published by the Free Software Foundation.
17 *
18 * You should have received a copy of the GNU General Public License and
19 * a copy of the GCC Runtime Library Exception along with this program;
20 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
21 * <http://www.gnu.org/licenses/>.
22 */
23
24 /* %ecx */
25 #define bit_SSE3 (1 << 0)
26 #define bit_PCLMUL (1 << 1)
27 #define bit_LZCNT (1 << 5)
28 #define bit_SSSE3 (1 << 9)
29 #define bit_FMA (1 << 12)
30 #define bit_CMPXCHG16B (1 << 13)
31 #define bit_SSE4_1 (1 << 19)
32 #define bit_SSE4_2 (1 << 20)
33 #define bit_MOVBE (1 << 22)
34 #define bit_POPCNT (1 << 23)
35 #define bit_AES (1 << 25)
36 #define bit_XSAVE (1 << 26)
37 #define bit_OSXSAVE (1 << 27)
38 #define bit_AVX (1 << 28)
39 #define bit_F16C (1 << 29)
40 #define bit_RDRND (1 << 30)
41
42 /* %edx */
43 #define bit_CMPXCHG8B (1 << 8)
44 #define bit_CMOV (1 << 15)
45 #define bit_MMX (1 << 23)
46 #define bit_FXSAVE (1 << 24)
47 #define bit_SSE (1 << 25)
48 #define bit_SSE2 (1 << 26)
49
50 /* Extended Features */
51 /* %ecx */
52 #define bit_LAHF_LM (1 << 0)
53 #define bit_ABM (1 << 5)
54 #define bit_SSE4a (1 << 6)
55 #define bit_XOP (1 << 11)
56 #define bit_LWP (1 << 15)
57 #define bit_FMA4 (1 << 16)
58 #define bit_TBM (1 << 21)
59
60 /* %edx */
61 #define bit_MMXEXT (1 << 22)
62 #define bit_LM (1 << 29)
63 #define bit_3DNOWP (1 << 30)
64 #define bit_3DNOW (1 << 31)
65
66 /* Extended Features (%eax == 7) */
67 #define bit_FSGSBASE (1 << 0)
68 #define bit_BMI (1 << 3)
69 #define bit_AVX2 (1 << 5)
70 #define bit_BMI2 (1 << 8)
71
72 #if defined(__i386__) && defined(__PIC__)
73 /* %ebx may be the PIC register. */
74 #if __GNUC__ >= 3
75 #define __cpuid(level, a, b, c, d) \
76 __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t" \
77 "cpuid\n\t" \
78 "xchg{l}\t{%%}ebx, %k1\n\t" \
79 : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
80 : "0" (level))
81
82 #define __cpuid_count(level, count, a, b, c, d) \
83 __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t" \
84 "cpuid\n\t" \
85 "xchg{l}\t{%%}ebx, %k1\n\t" \
86 : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
87 : "0" (level), "2" (count))
88 #else
89 /* Host GCCs older than 3.0 weren't supporting Intel asm syntax
90 nor alternatives in i386 code. */
91 #define __cpuid(level, a, b, c, d) \
92 __asm__ ("xchgl\t%%ebx, %k1\n\t" \
93 "cpuid\n\t" \
94 "xchgl\t%%ebx, %k1\n\t" \
95 : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
96 : "0" (level))
97
98 #define __cpuid_count(level, count, a, b, c, d) \
99 __asm__ ("xchgl\t%%ebx, %k1\n\t" \
100 "cpuid\n\t" \
101 "xchgl\t%%ebx, %k1\n\t" \
102 : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
103 : "0" (level), "2" (count))
104 #endif
105 #elif defined(__x86_64__) && (defined(__code_model_medium__) || defined(__code_model_large__)) && defined(__PIC__)
106 /* %rbx may be the PIC register. */
107 #define __cpuid(level, a, b, c, d) \
108 __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t" \
109 "cpuid\n\t" \
110 "xchg{q}\t{%%}rbx, %q1\n\t" \
111 : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
112 : "0" (level))
113
114 #define __cpuid_count(level, count, a, b, c, d) \
115 __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t" \
116 "cpuid\n\t" \
117 "xchg{q}\t{%%}rbx, %q1\n\t" \
118 : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
119 : "0" (level), "2" (count))
120 #else
121 #define __cpuid(level, a, b, c, d) \
122 __asm__ ("cpuid\n\t" \
123 : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
124 : "0" (level))
125
126 #define __cpuid_count(level, count, a, b, c, d) \
127 __asm__ ("cpuid\n\t" \
128 : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
129 : "0" (level), "2" (count))
130 #endif
131
132 /* Return highest supported input value for cpuid instruction. ext can
133 be either 0x0 or 0x8000000 to return highest supported value for
134 basic or extended cpuid information. Function returns 0 if cpuid
135 is not supported or whatever cpuid returns in eax register. If sig
136 pointer is non-null, then first four bytes of the signature
137 (as found in ebx register) are returned in location pointed by sig. */
138
139 static __inline unsigned int
__get_cpuid_max(unsigned int __ext,unsigned int * __sig)140 __get_cpuid_max (unsigned int __ext, unsigned int *__sig)
141 {
142 unsigned int __eax, __ebx, __ecx, __edx;
143
144 #ifndef __x86_64__
145 /* See if we can use cpuid. On AMD64 we always can. */
146 #if __GNUC__ >= 3
147 __asm__ ("pushf{l|d}\n\t"
148 "pushf{l|d}\n\t"
149 "pop{l}\t%0\n\t"
150 "mov{l}\t{%0, %1|%1, %0}\n\t"
151 "xor{l}\t{%2, %0|%0, %2}\n\t"
152 "push{l}\t%0\n\t"
153 "popf{l|d}\n\t"
154 "pushf{l|d}\n\t"
155 "pop{l}\t%0\n\t"
156 "popf{l|d}\n\t"
157 : "=&r" (__eax), "=&r" (__ebx)
158 : "i" (0x00200000));
159 #else
160 /* Host GCCs older than 3.0 weren't supporting Intel asm syntax
161 nor alternatives in i386 code. */
162 __asm__ ("pushfl\n\t"
163 "pushfl\n\t"
164 "popl\t%0\n\t"
165 "movl\t%0, %1\n\t"
166 "xorl\t%2, %0\n\t"
167 "pushl\t%0\n\t"
168 "popfl\n\t"
169 "pushfl\n\t"
170 "popl\t%0\n\t"
171 "popfl\n\t"
172 : "=&r" (__eax), "=&r" (__ebx)
173 : "i" (0x00200000));
174 #endif
175
176 if (!((__eax ^ __ebx) & 0x00200000))
177 return 0;
178 #endif
179
180 /* Host supports cpuid. Return highest supported cpuid input value. */
181 __cpuid (__ext, __eax, __ebx, __ecx, __edx);
182
183 if (__sig)
184 *__sig = __ebx;
185
186 return __eax;
187 }
188
189 /* Return cpuid data for requested cpuid level, as found in returned
190 eax, ebx, ecx and edx registers. The function checks if cpuid is
191 supported and returns 1 for valid cpuid information or 0 for
192 unsupported cpuid level. All pointers are required to be non-null. */
193
194 static __inline int
__get_cpuid(unsigned int __level,unsigned int * __eax,unsigned int * __ebx,unsigned int * __ecx,unsigned int * __edx)195 __get_cpuid (unsigned int __level,
196 unsigned int *__eax, unsigned int *__ebx,
197 unsigned int *__ecx, unsigned int *__edx)
198 {
199 unsigned int __ext = __level & 0x80000000;
200
201 if (__get_cpuid_max (__ext, 0) < __level)
202 return 0;
203
204 __cpuid (__level, *__eax, *__ebx, *__ecx, *__edx);
205 return 1;
206 }
207