1/* Subroutines for the gcc driver.
2   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING.  If not, write to
18the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19Boston, MA 02110-1301, USA.  */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include <stdlib.h>
26
27const char *host_detect_local_cpu (int argc, const char **argv);
28
29#ifdef GCC_VERSION
30#define cpuid(num,a,b,c,d) \
31  asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
32		: "=a" (a), "=r" (b), "=c" (c), "=d" (d)  \
33		: "0" (num))
34
35#define bit_CMPXCHG8B (1 << 8)
36#define bit_CMOV (1 << 15)
37#define bit_MMX (1 << 23)
38#define bit_SSE (1 << 25)
39#define bit_SSE2 (1 << 26)
40
41#define bit_SSE3 (1 << 0)
42#define bit_SSSE3 (1 << 9)
43#define bit_SSE4a (1 << 6)
44#define bit_CMPXCHG16B (1 << 13)
45
46#define bit_3DNOW (1 << 31)
47#define bit_3DNOWP (1 << 30)
48#define bit_LM (1 << 29)
49
50/* This will be called by the spec parser in gcc.c when it sees
51   a %:local_cpu_detect(args) construct.  Currently it will be called
52   with either "arch" or "tune" as argument depending on if -march=native
53   or -mtune=native is to be substituted.
54
55   It returns a string containing new command line parameters to be
56   put at the place of the above two options, depending on what CPU
57   this is executed.  E.g. "-march=k8" on an AMD64 machine
58   for -march=native.
59
60   ARGC and ARGV are set depending on the actual arguments given
61   in the spec.  */
62const char *host_detect_local_cpu (int argc, const char **argv)
63{
64  const char *cpu = NULL;
65  enum processor_type processor = PROCESSOR_I386;
66  unsigned int eax, ebx, ecx, edx;
67  unsigned int max_level;
68  unsigned int vendor;
69  unsigned int ext_level;
70  unsigned char has_mmx = 0, has_3dnow = 0, has_3dnowp = 0, has_sse = 0;
71  unsigned char has_sse2 = 0, has_sse3 = 0, has_ssse3 = 0, has_cmov = 0;
72  unsigned char has_longmode = 0, has_cmpxchg8b = 0, has_sse4a = 0;
73  unsigned char is_amd = 0;
74  unsigned int family = 0;
75  bool arch;
76
77  if (argc < 1)
78    return NULL;
79
80  arch = strcmp (argv[0], "arch") == 0;
81  if (!arch && strcmp (argv[0], "tune"))
82    return NULL;
83
84#ifndef __x86_64__
85  /* See if we can use cpuid.  */
86  asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
87		"pushl %0; popfl; pushfl; popl %0; popfl"
88		: "=&r" (eax), "=&r" (ebx)
89		: "i" (0x00200000));
90
91  if (((eax ^ ebx) & 0x00200000) == 0)
92    goto done;
93#endif
94
95  processor = PROCESSOR_PENTIUM;
96
97  /* Check the highest input value for eax.  */
98  cpuid (0, eax, ebx, ecx, edx);
99  max_level = eax;
100  /* We only look at the first four characters.  */
101  vendor = ebx;
102  if (max_level == 0)
103    goto done;
104
105  cpuid (1, eax, ebx, ecx, edx);
106  has_cmpxchg8b = !!(edx & bit_CMPXCHG8B);
107  has_cmov = !!(edx & bit_CMOV);
108  has_mmx = !!(edx & bit_MMX);
109  has_sse = !!(edx & bit_SSE);
110  has_sse2 = !!(edx & bit_SSE2);
111  has_sse3 = !!(ecx & bit_SSE3);
112  has_ssse3 = !!(ecx & bit_SSSE3);
113  /* We don't care for extended family.  */
114  family = (eax >> 8) & ~(1 << 4);
115
116  cpuid (0x80000000, eax, ebx, ecx, edx);
117  ext_level = eax;
118  if (ext_level >= 0x80000000)
119    {
120      cpuid (0x80000001, eax, ebx, ecx, edx);
121      has_3dnow = !!(edx & bit_3DNOW);
122      has_3dnowp = !!(edx & bit_3DNOWP);
123      has_longmode = !!(edx & bit_LM);
124      has_sse4a = !!(ecx & bit_SSE4a);
125    }
126
127  is_amd = vendor == *(unsigned int*)"Auth";
128
129  if (is_amd)
130    {
131      if (has_mmx)
132	processor = PROCESSOR_K6;
133      if (has_3dnowp)
134	processor = PROCESSOR_ATHLON;
135      if (has_sse2 || has_longmode)
136	processor = PROCESSOR_K8;
137      if (has_sse4a)
138	processor = PROCESSOR_AMDFAM10;
139    }
140  else
141    {
142      switch (family)
143	{
144	case 5:
145	  /* Default is PROCESSOR_PENTIUM.  */
146	  break;
147	case 6:
148	  processor = PROCESSOR_PENTIUMPRO;
149	  break;
150	case 15:
151	  processor = PROCESSOR_PENTIUM4;
152	  break;
153	default:
154	  /* We have no idea.  Use something reasonable.  */
155	  if (arch)
156	    {
157	      if (has_ssse3)
158		cpu = "core2";
159	      else if (has_sse3)
160		{
161		  if (has_longmode)
162		    cpu = "nocona";
163		  else
164		    cpu = "prescott";
165		}
166	      else if (has_sse2)
167		cpu = "pentium4";
168	      else if (has_cmov)
169		cpu = "pentiumpro";
170	      else if (has_mmx)
171		cpu = "pentium-mmx";
172	      else if (has_cmpxchg8b)
173		cpu = "pentium";
174	      else
175		cpu = "i386";
176	    }
177	  else
178	    cpu = "generic";
179	  goto done;
180	  break;
181	}
182    }
183
184  switch (processor)
185    {
186    case PROCESSOR_I386:
187      cpu = "i386";
188      break;
189    case PROCESSOR_I486:
190      cpu = "i486";
191      break;
192    case PROCESSOR_PENTIUM:
193      if (has_mmx)
194	cpu = "pentium-mmx";
195      else
196	cpu = "pentium";
197      break;
198    case PROCESSOR_PENTIUMPRO:
199      if (arch)
200	{
201	  if (has_sse3)
202	    {
203	      if (has_longmode)
204		{
205		  /* It is Core 2 Duo.  */
206		  cpu = "nocona";
207		}
208	      else
209		{
210		  /* It is Core Duo.  */
211		  cpu = "prescott";
212		}
213	    }
214	  else if (has_sse2)
215	    {
216	      /* It is Pentium M.  */
217	      cpu = "pentium4";
218	    }
219	  else if (has_sse)
220	    {
221	      /* It is Pentium III.  */
222	      cpu = "pentium3";
223	    }
224	  else if (has_mmx)
225	    {
226	      /* It is Pentium II.  */
227	      cpu = "pentium2";
228	    }
229	  else
230	    {
231	      /* Default to Pentium Pro.  */
232	      cpu = "pentiumpro";
233	    }
234	}
235      else
236	{
237	  /* For -mtune, we default to -mtune=generic.  */
238	  cpu = "generic";
239	}
240      break;
241    case PROCESSOR_GEODE:
242      cpu = "geode";
243      break;
244    case PROCESSOR_K6:
245      if (has_3dnow)
246        cpu = "k6-3";
247      else
248	cpu = "k6";
249      break;
250    case PROCESSOR_ATHLON:
251      if (has_sse)
252	cpu = "athlon-4";
253      else
254	cpu = "athlon";
255      break;
256    case PROCESSOR_PENTIUM4:
257      if (has_sse3)
258	{
259	  if (has_longmode)
260	    cpu = "nocona";
261	  else
262	    cpu = "prescott";
263	}
264      else
265	cpu = "pentium4";
266      break;
267    case PROCESSOR_K8:
268      cpu = "k8";
269      break;
270    case PROCESSOR_NOCONA:
271      cpu = "nocona";
272      break;
273    case PROCESSOR_AMDFAM10:
274      cpu = "amdfam10";
275      break;
276    case PROCESSOR_GENERIC32:
277    case PROCESSOR_GENERIC64:
278      cpu = "generic";
279      break;
280    default:
281      abort ();
282      break;
283    }
284
285done:
286  return concat ("-m", argv[0], "=", cpu, NULL);
287}
288#else
289/* If we aren't compiling with GCC we just provide a minimal
290   default value.  */
291const char *host_detect_local_cpu (int argc, const char **argv)
292{
293  const char *cpu;
294  bool arch;
295
296  if (argc < 1)
297    return NULL;
298
299  arch = strcmp (argv[0], "arch") == 0;
300  if (!arch && strcmp (argv[0], "tune"))
301    return NULL;
302
303  if (arch)
304    {
305      /* FIXME: i386 is wrong for 64bit compiler.  How can we tell if
306	 we are generating 64bit or 32bit code?  */
307      cpu = "i386";
308    }
309  else
310    cpu = "generic";
311
312  return concat ("-m", argv[0], "=", cpu, NULL);
313}
314#endif /* GCC_VERSION */
315