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