1169689Skan/* Subroutines for the gcc driver.
2251212Spfg   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
3169689Skan
4169689SkanThis file is part of GCC.
5169689Skan
6169689SkanGCC is free software; you can redistribute it and/or modify
7169689Skanit under the terms of the GNU General Public License as published by
8169689Skanthe Free Software Foundation; either version 2, or (at your option)
9169689Skanany later version.
10169689Skan
11169689SkanGCC is distributed in the hope that it will be useful,
12169689Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of
13169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14169689SkanGNU General Public License for more details.
15169689Skan
16169689SkanYou should have received a copy of the GNU General Public License
17169689Skanalong with GCC; see the file COPYING.  If not, write to
18169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
19169689SkanBoston, MA 02110-1301, USA.  */
20169689Skan
21169689Skan#include "config.h"
22169689Skan#include "system.h"
23169689Skan#include "coretypes.h"
24169689Skan#include "tm.h"
25169689Skan#include <stdlib.h>
26169689Skan
27169689Skanconst char *host_detect_local_cpu (int argc, const char **argv);
28169689Skan
29169689Skan#ifdef GCC_VERSION
30169689Skan#define cpuid(num,a,b,c,d) \
31169689Skan  asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
32169689Skan		: "=a" (a), "=r" (b), "=c" (c), "=d" (d)  \
33169689Skan		: "0" (num))
34169689Skan
35169689Skan#define bit_CMPXCHG8B (1 << 8)
36169689Skan#define bit_CMOV (1 << 15)
37169689Skan#define bit_MMX (1 << 23)
38169689Skan#define bit_SSE (1 << 25)
39169689Skan#define bit_SSE2 (1 << 26)
40169689Skan
41169689Skan#define bit_SSE3 (1 << 0)
42219697Smm#define bit_SSSE3 (1 << 9)
43251212Spfg#define bit_SSE4a (1 << 6)
44169689Skan#define bit_CMPXCHG16B (1 << 13)
45169689Skan
46169689Skan#define bit_3DNOW (1 << 31)
47169689Skan#define bit_3DNOWP (1 << 30)
48169689Skan#define bit_LM (1 << 29)
49169689Skan
50169689Skan/* This will be called by the spec parser in gcc.c when it sees
51169689Skan   a %:local_cpu_detect(args) construct.  Currently it will be called
52169689Skan   with either "arch" or "tune" as argument depending on if -march=native
53169689Skan   or -mtune=native is to be substituted.
54169689Skan
55169689Skan   It returns a string containing new command line parameters to be
56169689Skan   put at the place of the above two options, depending on what CPU
57169689Skan   this is executed.  E.g. "-march=k8" on an AMD64 machine
58169689Skan   for -march=native.
59169689Skan
60169689Skan   ARGC and ARGV are set depending on the actual arguments given
61169689Skan   in the spec.  */
62169689Skanconst char *host_detect_local_cpu (int argc, const char **argv)
63169689Skan{
64169689Skan  const char *cpu = NULL;
65169689Skan  enum processor_type processor = PROCESSOR_I386;
66169689Skan  unsigned int eax, ebx, ecx, edx;
67169689Skan  unsigned int max_level;
68169689Skan  unsigned int vendor;
69169689Skan  unsigned int ext_level;
70169689Skan  unsigned char has_mmx = 0, has_3dnow = 0, has_3dnowp = 0, has_sse = 0;
71219697Smm  unsigned char has_sse2 = 0, has_sse3 = 0, has_ssse3 = 0, has_cmov = 0;
72251212Spfg  unsigned char has_longmode = 0, has_cmpxchg8b = 0, has_sse4a = 0;
73169689Skan  unsigned char is_amd = 0;
74169689Skan  unsigned int family = 0;
75169689Skan  bool arch;
76169689Skan
77169689Skan  if (argc < 1)
78169689Skan    return NULL;
79169689Skan
80169689Skan  arch = strcmp (argv[0], "arch") == 0;
81169689Skan  if (!arch && strcmp (argv[0], "tune"))
82169689Skan    return NULL;
83169689Skan
84169689Skan#ifndef __x86_64__
85169689Skan  /* See if we can use cpuid.  */
86169689Skan  asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
87169689Skan		"pushl %0; popfl; pushfl; popl %0; popfl"
88169689Skan		: "=&r" (eax), "=&r" (ebx)
89169689Skan		: "i" (0x00200000));
90169689Skan
91169689Skan  if (((eax ^ ebx) & 0x00200000) == 0)
92169689Skan    goto done;
93169689Skan#endif
94169689Skan
95169689Skan  processor = PROCESSOR_PENTIUM;
96169689Skan
97169689Skan  /* Check the highest input value for eax.  */
98169689Skan  cpuid (0, eax, ebx, ecx, edx);
99169689Skan  max_level = eax;
100169689Skan  /* We only look at the first four characters.  */
101169689Skan  vendor = ebx;
102169689Skan  if (max_level == 0)
103169689Skan    goto done;
104169689Skan
105169689Skan  cpuid (1, eax, ebx, ecx, edx);
106169689Skan  has_cmpxchg8b = !!(edx & bit_CMPXCHG8B);
107169689Skan  has_cmov = !!(edx & bit_CMOV);
108169689Skan  has_mmx = !!(edx & bit_MMX);
109169689Skan  has_sse = !!(edx & bit_SSE);
110169689Skan  has_sse2 = !!(edx & bit_SSE2);
111169689Skan  has_sse3 = !!(ecx & bit_SSE3);
112219697Smm  has_ssse3 = !!(ecx & bit_SSSE3);
113169689Skan  /* We don't care for extended family.  */
114169689Skan  family = (eax >> 8) & ~(1 << 4);
115169689Skan
116169689Skan  cpuid (0x80000000, eax, ebx, ecx, edx);
117169689Skan  ext_level = eax;
118169689Skan  if (ext_level >= 0x80000000)
119169689Skan    {
120169689Skan      cpuid (0x80000001, eax, ebx, ecx, edx);
121169689Skan      has_3dnow = !!(edx & bit_3DNOW);
122169689Skan      has_3dnowp = !!(edx & bit_3DNOWP);
123169689Skan      has_longmode = !!(edx & bit_LM);
124251212Spfg      has_sse4a = !!(ecx & bit_SSE4a);
125169689Skan    }
126169689Skan
127169689Skan  is_amd = vendor == *(unsigned int*)"Auth";
128169689Skan
129169689Skan  if (is_amd)
130169689Skan    {
131169689Skan      if (has_mmx)
132169689Skan	processor = PROCESSOR_K6;
133169689Skan      if (has_3dnowp)
134169689Skan	processor = PROCESSOR_ATHLON;
135169689Skan      if (has_sse2 || has_longmode)
136169689Skan	processor = PROCESSOR_K8;
137251212Spfg      if (has_sse4a)
138251212Spfg	processor = PROCESSOR_AMDFAM10;
139169689Skan    }
140169689Skan  else
141169689Skan    {
142169689Skan      switch (family)
143169689Skan	{
144169689Skan	case 5:
145169689Skan	  /* Default is PROCESSOR_PENTIUM.  */
146169689Skan	  break;
147169689Skan	case 6:
148169689Skan	  processor = PROCESSOR_PENTIUMPRO;
149169689Skan	  break;
150169689Skan	case 15:
151169689Skan	  processor = PROCESSOR_PENTIUM4;
152169689Skan	  break;
153169689Skan	default:
154169689Skan	  /* We have no idea.  Use something reasonable.  */
155169689Skan	  if (arch)
156169689Skan	    {
157219697Smm	      if (has_ssse3)
158219697Smm		cpu = "core2";
159219697Smm	      else if (has_sse3)
160169689Skan		{
161169689Skan		  if (has_longmode)
162169689Skan		    cpu = "nocona";
163169689Skan		  else
164169689Skan		    cpu = "prescott";
165169689Skan		}
166169689Skan	      else if (has_sse2)
167169689Skan		cpu = "pentium4";
168169689Skan	      else if (has_cmov)
169169689Skan		cpu = "pentiumpro";
170169689Skan	      else if (has_mmx)
171169689Skan		cpu = "pentium-mmx";
172169689Skan	      else if (has_cmpxchg8b)
173169689Skan		cpu = "pentium";
174169689Skan	      else
175169689Skan		cpu = "i386";
176169689Skan	    }
177169689Skan	  else
178169689Skan	    cpu = "generic";
179169689Skan	  goto done;
180169689Skan	  break;
181169689Skan	}
182169689Skan    }
183169689Skan
184169689Skan  switch (processor)
185169689Skan    {
186169689Skan    case PROCESSOR_I386:
187169689Skan      cpu = "i386";
188169689Skan      break;
189169689Skan    case PROCESSOR_I486:
190169689Skan      cpu = "i486";
191169689Skan      break;
192169689Skan    case PROCESSOR_PENTIUM:
193169689Skan      if (has_mmx)
194169689Skan	cpu = "pentium-mmx";
195169689Skan      else
196169689Skan	cpu = "pentium";
197169689Skan      break;
198169689Skan    case PROCESSOR_PENTIUMPRO:
199169689Skan      if (arch)
200169689Skan	{
201169689Skan	  if (has_sse3)
202169689Skan	    {
203169689Skan	      if (has_longmode)
204169689Skan		{
205169689Skan		  /* It is Core 2 Duo.  */
206169689Skan		  cpu = "nocona";
207169689Skan		}
208169689Skan	      else
209169689Skan		{
210169689Skan		  /* It is Core Duo.  */
211169689Skan		  cpu = "prescott";
212169689Skan		}
213169689Skan	    }
214169689Skan	  else if (has_sse2)
215169689Skan	    {
216169689Skan	      /* It is Pentium M.  */
217169689Skan	      cpu = "pentium4";
218169689Skan	    }
219169689Skan	  else if (has_sse)
220169689Skan	    {
221169689Skan	      /* It is Pentium III.  */
222169689Skan	      cpu = "pentium3";
223169689Skan	    }
224169689Skan	  else if (has_mmx)
225169689Skan	    {
226169689Skan	      /* It is Pentium II.  */
227169689Skan	      cpu = "pentium2";
228169689Skan	    }
229169689Skan	  else
230169689Skan	    {
231169689Skan	      /* Default to Pentium Pro.  */
232169689Skan	      cpu = "pentiumpro";
233169689Skan	    }
234169689Skan	}
235169689Skan      else
236169689Skan	{
237169689Skan	  /* For -mtune, we default to -mtune=generic.  */
238169689Skan	  cpu = "generic";
239169689Skan	}
240169689Skan      break;
241219697Smm    case PROCESSOR_GEODE:
242219697Smm      cpu = "geode";
243219697Smm      break;
244169689Skan    case PROCESSOR_K6:
245169689Skan      if (has_3dnow)
246169689Skan        cpu = "k6-3";
247169689Skan      else
248169689Skan	cpu = "k6";
249169689Skan      break;
250169689Skan    case PROCESSOR_ATHLON:
251169689Skan      if (has_sse)
252169689Skan	cpu = "athlon-4";
253169689Skan      else
254169689Skan	cpu = "athlon";
255169689Skan      break;
256169689Skan    case PROCESSOR_PENTIUM4:
257169689Skan      if (has_sse3)
258169689Skan	{
259169689Skan	  if (has_longmode)
260169689Skan	    cpu = "nocona";
261169689Skan	  else
262169689Skan	    cpu = "prescott";
263169689Skan	}
264169689Skan      else
265169689Skan	cpu = "pentium4";
266169689Skan      break;
267169689Skan    case PROCESSOR_K8:
268169689Skan      cpu = "k8";
269169689Skan      break;
270169689Skan    case PROCESSOR_NOCONA:
271169689Skan      cpu = "nocona";
272169689Skan      break;
273251212Spfg    case PROCESSOR_AMDFAM10:
274251212Spfg      cpu = "amdfam10";
275251212Spfg      break;
276169689Skan    case PROCESSOR_GENERIC32:
277169689Skan    case PROCESSOR_GENERIC64:
278169689Skan      cpu = "generic";
279169689Skan      break;
280169689Skan    default:
281169689Skan      abort ();
282169689Skan      break;
283169689Skan    }
284169689Skan
285169689Skandone:
286169689Skan  return concat ("-m", argv[0], "=", cpu, NULL);
287169689Skan}
288169689Skan#else
289169689Skan/* If we aren't compiling with GCC we just provide a minimal
290169689Skan   default value.  */
291169689Skanconst char *host_detect_local_cpu (int argc, const char **argv)
292169689Skan{
293169689Skan  const char *cpu;
294169689Skan  bool arch;
295169689Skan
296169689Skan  if (argc < 1)
297169689Skan    return NULL;
298169689Skan
299169689Skan  arch = strcmp (argv[0], "arch") == 0;
300169689Skan  if (!arch && strcmp (argv[0], "tune"))
301169689Skan    return NULL;
302169689Skan
303169689Skan  if (arch)
304169689Skan    {
305169689Skan      /* FIXME: i386 is wrong for 64bit compiler.  How can we tell if
306169689Skan	 we are generating 64bit or 32bit code?  */
307169689Skan      cpu = "i386";
308169689Skan    }
309169689Skan  else
310169689Skan    cpu = "generic";
311169689Skan
312169689Skan  return concat ("-m", argv[0], "=", cpu, NULL);
313169689Skan}
314169689Skan#endif /* GCC_VERSION */
315