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