OSDN Git Service

gcc/cp/
[pf3gnuchains/gcc-fork.git] / gcc / config / rs6000 / driver-rs6000.c
1 /* Subroutines for the gcc driver.
2    Copyright (C) 2007 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 3, 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 COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include <stdlib.h>
25
26 #ifdef _AIX
27 # include <sys/systemcfg.h>
28 #endif
29
30 #ifdef __linux__
31 # include <elf.h>
32 #endif
33
34 #ifdef __APPLE__
35 # include <sys/types.h>
36 # include <sys/sysctl.h>
37 #endif
38
39 const char *host_detect_local_cpu (int argc, const char **argv);
40
41 #if GCC_VERSION >= 0
42
43 /* Returns parameters that describe L1_ASSOC associative cache of size
44    L1_SIZEKB with lines of size L1_LINE, and L2_SIZEKB.  */
45
46 static char *
47 describe_cache (unsigned l1_sizekb, unsigned l1_line,
48                 unsigned l1_assoc ATTRIBUTE_UNUSED, unsigned l2_sizekb)
49 {
50   char l1size[1000], line[1000], l2size[1000];
51
52   /* At the moment, gcc middle-end does not use the information about the
53      associativity of the cache.  */
54
55   sprintf (l1size, "--param l1-cache-size=%u", l1_sizekb);
56   sprintf (line, "--param l1-cache-line-size=%u", l1_line);
57   sprintf (l2size, "--param l2-cache-size=%u", l2_sizekb);
58
59   return concat (l1size, " ", line, " ", l2size, " ", NULL);
60 }
61
62 #ifdef __APPLE__
63
64 /* Returns the description of caches on Darwin.  */
65
66 static char *
67 detect_caches_darwin (void)
68 {
69   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
70   size_t len = 4;
71   static int l1_size_name[2] = { CTL_HW, HW_L1DCACHESIZE };
72   static int l1_line_name[2] = { CTL_HW, HW_CACHELINE };
73   static int l2_size_name[2] = { CTL_HW, HW_L2CACHESIZE };
74
75   sysctl (l1_size_name, 2, &l1_sizekb, &len, NULL, 0);
76   sysctl (l1_line_name, 2, &l1_line, &len, NULL, 0);
77   sysctl (l2_size_name, 2, &l2_sizekb, &len, NULL, 0);
78   l1_assoc = 0;
79
80   return describe_cache (l1_sizekb / 1024, l1_line, l1_assoc,
81                          l2_sizekb / 1024);
82 }
83
84 static const char *
85 detect_processor_darwin (void)
86 {
87   unsigned int proc;
88   size_t len = 4;
89
90   sysctlbyname ("hw.cpusubtype", &proc, &len, NULL, 0);
91
92   if (len > 0)
93     switch (proc)
94       {
95       case 1:
96         return "601";
97       case 2:
98         return "602";
99       case 3:
100         return "603";
101       case 4:
102       case 5:
103         return "603e";
104       case 6:
105         return "604";
106       case 7:
107         return "604e";
108       case 8:
109         return "620";
110       case 9:
111         return "750";
112       case 10:
113         return "7400";
114       case 11:
115         return "7450";
116       case 100:
117         return "970";
118       default:
119         return "powerpc";
120       }
121
122   return "powerpc";
123 }
124
125 #endif /* __APPLE__ */
126
127 #ifdef __linux__
128
129 /* Returns AT_PLATFORM if present, otherwise generic PowerPC.  */
130
131 static const char *
132 elf_platform (void)
133 {
134   int fd;
135
136   fd = open ("/proc/self/auxv", O_RDONLY);
137
138   if (fd != -1)
139     {
140       char buf[1024];
141       Elf32_auxv_t *av;
142       ssize_t n;
143
144       n = read (fd, buf, sizeof (buf));
145       close (fd);
146
147       if (n > 0)
148         {
149           for (av = (Elf32_auxv_t *) buf; av->a_type != AT_NULL; ++av)
150             switch (av->a_type)
151               {
152               case AT_PLATFORM:
153                 return (const char *) av->a_un.a_val;
154
155               default:
156                 break;
157               }
158         }
159     }
160   return NULL;
161 }
162
163 /* Returns AT_PLATFORM if present, otherwise generic 32.  */
164
165 static int
166 elf_dcachebsize (void)
167 {
168   int fd;
169
170   fd = open ("/proc/self/auxv", O_RDONLY);
171
172   if (fd != -1)
173     {
174       char buf[1024];
175       Elf32_auxv_t *av;
176       ssize_t n;
177
178       n = read (fd, buf, sizeof (buf));
179       close (fd);
180
181       if (n > 0)
182         {
183           for (av = (Elf32_auxv_t *) buf; av->a_type != AT_NULL; ++av)
184             switch (av->a_type)
185               {
186               case AT_DCACHEBSIZE:
187                 return av->a_un.a_val;
188
189               default:
190                 break;
191               }
192         }
193     }
194   return 32;
195 }
196
197 /* Returns the description of caches on Linux.  */
198
199 static char *
200 detect_caches_linux (void)
201 {
202   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
203   const char *platform;
204
205   platform = elf_platform ();
206
207   if (platform != NULL)
208     {
209       l1_line = 128;
210
211       if (platform[5] == '6')
212         /* POWER6 and POWER6x */
213         l1_sizekb = 64;
214       else
215         l1_sizekb = 32;
216     }
217   else
218     {
219       l1_line = elf_dcachebsize ();
220       l1_sizekb = 32;
221     }
222
223   l1_assoc = 0;
224   l2_sizekb = 512;
225
226   return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
227 }
228
229 static const char *
230 detect_processor_linux (void)
231 {
232   const char *platform;
233
234   platform = elf_platform ();
235
236   if (platform != NULL)
237     return platform;
238   else
239     return "powerpc";
240 }
241
242 #endif /* __linux__ */
243
244 #ifdef _AIX
245 /* Returns the description of caches on AIX.  */
246
247 static char *
248 detect_caches_aix (void)
249 {
250   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
251
252   l1_sizekb = _system_configuration.dcache_size / 1024;
253   l1_line = _system_configuration.dcache_line;
254   l1_assoc = _system_configuration.dcache_asc;
255   l2_sizekb = _system_configuration.L2_cache_size / 1024;
256
257   return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
258 }
259
260
261 /* Returns the processor implementation on AIX.  */
262
263 static const char *
264 detect_processor_aix (void)
265 {
266   switch (_system_configuration.implementation)
267     {
268     case 0x0001:
269       return "rios1";
270
271     case 0x0002:
272       return "rsc";
273
274     case 0x0004:
275       return "rios2";
276
277     case 0x0008:
278       return "601";
279
280     case 0x0020:
281       return "603";
282
283     case 0x0010:
284       return "604";
285
286     case 0x0040:
287       return "620";
288
289     case 0x0080:
290       return "630";
291
292     case 0x0100:
293     case 0x0200:
294     case 0x0400:
295       return "rs64";
296
297     case 0x0800:
298       return "power4";
299
300     case 0x2000:
301       if (_system_configuration.version == 0x0F0000)
302         return "power5";
303       else
304         return "power5+";
305
306     case 0x4000:
307       return "power6";
308
309     default:
310       return "powerpc";
311     }
312 }
313 #endif /* _AIX */
314
315
316 /* This will be called by the spec parser in gcc.c when it sees
317    a %:local_cpu_detect(args) construct.  Currently it will be called
318    with either "arch" or "tune" as argument depending on if -march=native
319    or -mtune=native is to be substituted.
320
321    It returns a string containing new command line parameters to be
322    put at the place of the above two options, depending on what CPU
323    this is executed.
324
325    ARGC and ARGV are set depending on the actual arguments given
326    in the spec.  */
327 const char
328 *host_detect_local_cpu (int argc, const char **argv)
329 {
330   const char *cpu = NULL;
331   const char *cache = "";
332   const char *options = "";
333   bool arch;
334
335   if (argc < 1)
336     return NULL;
337
338   arch = strcmp (argv[0], "cpu") == 0;
339   if (!arch && strcmp (argv[0], "tune"))
340     return NULL;
341
342 #if defined (_AIX)
343   cache = detect_caches_aix ();
344 #elif defined (__APPLE__)
345   cache = detect_caches_darwin ();
346 #elif defined (__linux__)
347   cache = detect_caches_linux ();
348   /* PPC Linux does not provide any cache information yet.  */
349   cache = "";
350 #else
351   cache = "";
352 #endif
353
354 #if defined (_AIX)
355   cpu = detect_processor_aix ();
356 #elif defined (__APPLE__)
357   cpu = detect_processor_darwin ();
358 #elif defined (__linux__)
359   cpu = detect_processor_linux ();
360 #else
361   cpu = "powerpc";
362 #endif
363
364   return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL);
365 }
366
367 #else /* GCC_VERSION */
368
369 /* If we aren't compiling with GCC we just provide a minimal
370    default value.  */
371 const char *host_detect_local_cpu (int argc, const char **argv)
372 {
373   const char *cpu;
374   bool arch;
375
376   if (argc < 1)
377     return NULL;
378
379   arch = strcmp (argv[0], "cpu") == 0;
380   if (!arch && strcmp (argv[0], "tune"))
381     return NULL;
382   
383   if (arch)
384     cpu = "powerpc";
385
386   return concat ("-m", argv[0], "=", cpu, NULL);
387 }
388
389 #endif /* GCC_VERSION */
390