]>
Commit | Line | Data |
---|---|---|
792317cc | 1 | /* This test checks if the __builtin_cpu_is and __builtin_cpu_supports calls |
91fe5efb ST |
2 | are recognized. It also independently uses CPUID to get cpu type and |
3 | features supported and checks if the builtins correctly identify the | |
4 | platform. The code to do the identification is adapted from | |
5 | libgcc/config/i386/cpuinfo.c. */ | |
792317cc ST |
6 | |
7 | /* { dg-do run } */ | |
8 | ||
9 | #include <assert.h> | |
91fe5efb | 10 | #include "cpuid.h" |
792317cc | 11 | |
91fe5efb ST |
12 | enum vendor_signatures |
13 | { | |
14 | SIG_INTEL = 0x756e6547 /* Genu */, | |
15 | SIG_AMD = 0x68747541 /* Auth */ | |
16 | }; | |
17 | ||
18 | /* Check if the Intel CPU model and sub-model are identified. */ | |
19 | static void | |
20 | check_intel_cpu_model (unsigned int family, unsigned int model, | |
21 | unsigned int brand_id) | |
22 | { | |
23 | /* Parse family and model only if brand ID is 0. */ | |
24 | if (brand_id == 0) | |
25 | { | |
26 | switch (family) | |
27 | { | |
28 | case 0x5: | |
29 | /* Pentium. */ | |
30 | break; | |
31 | case 0x6: | |
32 | switch (model) | |
33 | { | |
34 | case 0x1c: | |
35 | case 0x26: | |
36 | /* Atom. */ | |
37 | assert (__builtin_cpu_is ("atom")); | |
38 | break; | |
39 | case 0x1a: | |
40 | case 0x1e: | |
41 | case 0x1f: | |
42 | case 0x2e: | |
43 | /* Nehalem. */ | |
44 | assert (__builtin_cpu_is ("corei7")); | |
45 | assert (__builtin_cpu_is ("nehalem")); | |
46 | break; | |
47 | case 0x25: | |
48 | case 0x2c: | |
49 | case 0x2f: | |
50 | /* Westmere. */ | |
51 | assert (__builtin_cpu_is ("corei7")); | |
52 | assert (__builtin_cpu_is ("westmere")); | |
53 | break; | |
54 | case 0x2a: | |
55 | /* Sandy Bridge. */ | |
56 | assert (__builtin_cpu_is ("corei7")); | |
57 | assert (__builtin_cpu_is ("sandybridge")); | |
58 | break; | |
59 | case 0x17: | |
60 | case 0x1d: | |
61 | /* Penryn. */ | |
62 | case 0x0f: | |
63 | /* Merom. */ | |
64 | assert (__builtin_cpu_is ("core2")); | |
65 | break; | |
66 | default: | |
67 | break; | |
68 | } | |
69 | break; | |
70 | default: | |
71 | /* We have no idea. */ | |
72 | break; | |
73 | } | |
74 | } | |
75 | } | |
76 | ||
77 | /* Check if the AMD CPU model and sub-model are identified. */ | |
78 | static void | |
79 | check_amd_cpu_model (unsigned int family, unsigned int model) | |
80 | { | |
81 | switch (family) | |
82 | { | |
83 | /* AMD Family 10h. */ | |
84 | case 0x10: | |
85 | switch (model) | |
86 | { | |
87 | case 0x2: | |
88 | /* Barcelona. */ | |
89 | assert (__builtin_cpu_is ("amdfam10h")); | |
90 | assert (__builtin_cpu_is ("barcelona")); | |
91 | break; | |
92 | case 0x4: | |
93 | /* Shanghai. */ | |
94 | assert (__builtin_cpu_is ("amdfam10h")); | |
95 | assert (__builtin_cpu_is ("shanghai")); | |
96 | break; | |
97 | case 0x8: | |
98 | /* Istanbul. */ | |
99 | assert (__builtin_cpu_is ("amdfam10h")); | |
100 | assert (__builtin_cpu_is ("istanbul")); | |
101 | break; | |
102 | default: | |
103 | break; | |
104 | } | |
105 | break; | |
106 | /* AMD Family 15h. */ | |
107 | case 0x15: | |
108 | assert (__builtin_cpu_is ("amdfam15h")); | |
109 | /* Bulldozer version 1. */ | |
110 | if ( model <= 0xf) | |
111 | assert (__builtin_cpu_is ("bdver1")); | |
112 | /* Bulldozer version 2. */ | |
113 | if (model >= 0x10 && model <= 0x1f) | |
114 | assert (__builtin_cpu_is ("bdver2")); | |
115 | break; | |
116 | default: | |
117 | break; | |
118 | } | |
119 | } | |
120 | ||
121 | /* Check if the ISA features are identified. */ | |
122 | static void | |
123 | check_features (unsigned int ecx, unsigned int edx, | |
124 | int max_cpuid_level) | |
125 | { | |
126 | if (edx & bit_CMOV) | |
127 | assert (__builtin_cpu_supports ("cmov")); | |
128 | if (edx & bit_MMX) | |
129 | assert (__builtin_cpu_supports ("mmx")); | |
130 | if (edx & bit_SSE) | |
131 | assert (__builtin_cpu_supports ("sse")); | |
132 | if (edx & bit_SSE2) | |
133 | assert (__builtin_cpu_supports ("sse2")); | |
134 | if (ecx & bit_POPCNT) | |
135 | assert (__builtin_cpu_supports ("popcnt")); | |
136 | if (ecx & bit_SSE3) | |
137 | assert (__builtin_cpu_supports ("sse3")); | |
138 | if (ecx & bit_SSSE3) | |
139 | assert (__builtin_cpu_supports ("ssse3")); | |
140 | if (ecx & bit_SSE4_1) | |
141 | assert (__builtin_cpu_supports ("sse4.1")); | |
142 | if (ecx & bit_SSE4_2) | |
143 | assert (__builtin_cpu_supports ("sse4.2")); | |
144 | if (ecx & bit_AVX) | |
145 | assert (__builtin_cpu_supports ("avx")); | |
146 | ||
147 | /* Get advanced features at level 7 (eax = 7, ecx = 0). */ | |
148 | if (max_cpuid_level >= 7) | |
149 | { | |
150 | unsigned int eax, ebx, ecx, edx; | |
151 | __cpuid_count (7, 0, eax, ebx, ecx, edx); | |
152 | if (ebx & bit_AVX2) | |
153 | assert (__builtin_cpu_supports ("avx2")); | |
154 | } | |
155 | } | |
156 | ||
157 | static int __attribute__ ((noinline)) | |
158 | __get_cpuid_output (unsigned int __level, | |
159 | unsigned int *__eax, unsigned int *__ebx, | |
160 | unsigned int *__ecx, unsigned int *__edx) | |
161 | { | |
162 | return __get_cpuid (__level, __eax, __ebx, __ecx, __edx); | |
163 | } | |
164 | ||
165 | static int | |
166 | check_detailed () | |
167 | { | |
168 | unsigned int eax, ebx, ecx, edx; | |
169 | ||
170 | int max_level; | |
171 | unsigned int vendor; | |
172 | unsigned int model, family, brand_id; | |
173 | unsigned int extended_model, extended_family; | |
174 | ||
175 | /* Assume cpuid insn present. Run in level 0 to get vendor id. */ | |
176 | if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx)) | |
177 | return 0; | |
178 | ||
179 | vendor = ebx; | |
180 | max_level = eax; | |
181 | ||
182 | if (max_level < 1) | |
183 | return 0; | |
184 | ||
185 | if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx)) | |
186 | return 0; | |
187 | ||
188 | model = (eax >> 4) & 0x0f; | |
189 | family = (eax >> 8) & 0x0f; | |
190 | brand_id = ebx & 0xff; | |
191 | extended_model = (eax >> 12) & 0xf0; | |
192 | extended_family = (eax >> 20) & 0xff; | |
193 | ||
194 | if (vendor == SIG_INTEL) | |
195 | { | |
196 | assert (__builtin_cpu_is ("intel")); | |
197 | /* Adjust family and model for Intel CPUs. */ | |
198 | if (family == 0x0f) | |
199 | { | |
200 | family += extended_family; | |
201 | model += extended_model; | |
202 | } | |
203 | else if (family == 0x06) | |
204 | model += extended_model; | |
205 | check_intel_cpu_model (family, model, brand_id); | |
206 | check_features (ecx, edx, max_level); | |
207 | } | |
208 | else if (vendor == SIG_AMD) | |
209 | { | |
210 | assert (__builtin_cpu_is ("amd")); | |
211 | /* Adjust model and family for AMD CPUS. */ | |
212 | if (family == 0x0f) | |
213 | { | |
214 | family += extended_family; | |
215 | model += (extended_model << 4); | |
216 | } | |
217 | check_amd_cpu_model (family, model); | |
218 | check_features (ecx, edx, max_level); | |
219 | } | |
220 | ||
221 | return 0; | |
222 | } | |
223 | ||
224 | static int | |
225 | quick_check () | |
792317cc ST |
226 | { |
227 | /* Check CPU Features. */ | |
228 | assert (__builtin_cpu_supports ("cmov") >= 0); | |
229 | ||
230 | assert (__builtin_cpu_supports ("mmx") >= 0); | |
231 | ||
232 | assert (__builtin_cpu_supports ("popcnt") >= 0); | |
233 | ||
234 | assert (__builtin_cpu_supports ("sse") >= 0); | |
235 | ||
236 | assert (__builtin_cpu_supports ("sse2") >= 0); | |
237 | ||
238 | assert (__builtin_cpu_supports ("sse3") >= 0); | |
239 | ||
240 | assert (__builtin_cpu_supports ("ssse3") >= 0); | |
241 | ||
242 | assert (__builtin_cpu_supports ("sse4.1") >= 0); | |
243 | ||
244 | assert (__builtin_cpu_supports ("sse4.2") >= 0); | |
245 | ||
246 | assert (__builtin_cpu_supports ("avx") >= 0); | |
247 | ||
5ddecff9 ST |
248 | assert (__builtin_cpu_supports ("avx2") >= 0); |
249 | ||
792317cc ST |
250 | /* Check CPU type. */ |
251 | assert (__builtin_cpu_is ("amd") >= 0); | |
252 | ||
253 | assert (__builtin_cpu_is ("intel") >= 0); | |
254 | ||
255 | assert (__builtin_cpu_is ("atom") >= 0); | |
256 | ||
257 | assert (__builtin_cpu_is ("core2") >= 0); | |
258 | ||
259 | assert (__builtin_cpu_is ("corei7") >= 0); | |
260 | ||
261 | assert (__builtin_cpu_is ("nehalem") >= 0); | |
262 | ||
263 | assert (__builtin_cpu_is ("westmere") >= 0); | |
264 | ||
265 | assert (__builtin_cpu_is ("sandybridge") >= 0); | |
266 | ||
267 | assert (__builtin_cpu_is ("amdfam10h") >= 0); | |
268 | ||
269 | assert (__builtin_cpu_is ("barcelona") >= 0); | |
270 | ||
271 | assert (__builtin_cpu_is ("shanghai") >= 0); | |
272 | ||
273 | assert (__builtin_cpu_is ("istanbul") >= 0); | |
274 | ||
275 | assert (__builtin_cpu_is ("amdfam15h") >= 0); | |
276 | ||
277 | assert (__builtin_cpu_is ("bdver1") >= 0); | |
278 | ||
279 | assert (__builtin_cpu_is ("bdver2") >= 0); | |
280 | ||
281 | return 0; | |
282 | } | |
283 | ||
284 | int main () | |
285 | { | |
286 | __builtin_cpu_init (); | |
91fe5efb ST |
287 | quick_check (); |
288 | check_detailed (); | |
289 | return 0; | |
792317cc | 290 | } |