xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/rs6000/driver-rs6000.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /* Subroutines for the gcc driver.
2    Copyright (C) 2007, 2008, 2009 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 <link.h>
32 #endif
33 
34 #if defined (__APPLE__) || (__FreeBSD__)
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 __FreeBSD__
128 
129 /* Returns the description of caches on FreeBSD PPC.  */
130 
131 static char *
132 detect_caches_freebsd (void)
133 {
134   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
135   size_t len = 4;
136 
137   /* Currently, as of FreeBSD-7.0, there is only the cacheline_size
138      available via sysctl.  */
139   sysctlbyname ("machdep.cacheline_size", &l1_line, &len, NULL, 0);
140 
141   l1_sizekb = 32;
142   l1_assoc = 0;
143   l2_sizekb = 512;
144 
145   return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
146 }
147 
148 /* Currently returns default powerpc.  */
149 static const char *
150 detect_processor_freebsd (void)
151 {
152   return "powerpc";
153 }
154 
155 #endif /* __FreeBSD__  */
156 
157 #ifdef __linux__
158 
159 /* Returns AT_PLATFORM if present, otherwise generic PowerPC.  */
160 
161 static const char *
162 elf_platform (void)
163 {
164   int fd;
165 
166   fd = open ("/proc/self/auxv", O_RDONLY);
167 
168   if (fd != -1)
169     {
170       char buf[1024];
171       ElfW(auxv_t) *av;
172       ssize_t n;
173 
174       n = read (fd, buf, sizeof (buf));
175       close (fd);
176 
177       if (n > 0)
178 	{
179 	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
180 	    switch (av->a_type)
181 	      {
182 	      case AT_PLATFORM:
183 		return (const char *) av->a_un.a_val;
184 
185 	      default:
186 		break;
187 	      }
188 	}
189     }
190   return NULL;
191 }
192 
193 /* Returns AT_PLATFORM if present, otherwise generic 32.  */
194 
195 static int
196 elf_dcachebsize (void)
197 {
198   int fd;
199 
200   fd = open ("/proc/self/auxv", O_RDONLY);
201 
202   if (fd != -1)
203     {
204       char buf[1024];
205       ElfW(auxv_t) *av;
206       ssize_t n;
207 
208       n = read (fd, buf, sizeof (buf));
209       close (fd);
210 
211       if (n > 0)
212 	{
213 	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
214 	    switch (av->a_type)
215 	      {
216 	      case AT_DCACHEBSIZE:
217 		return av->a_un.a_val;
218 
219 	      default:
220 		break;
221 	      }
222 	}
223     }
224   return 32;
225 }
226 
227 /* Returns the description of caches on Linux.  */
228 
229 static char *
230 detect_caches_linux (void)
231 {
232   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
233   const char *platform;
234 
235   platform = elf_platform ();
236 
237   if (platform != NULL)
238     {
239       l1_line = 128;
240 
241       if (platform[5] == '6')
242 	/* POWER6 and POWER6x */
243 	l1_sizekb = 64;
244       else
245 	l1_sizekb = 32;
246     }
247   else
248     {
249       l1_line = elf_dcachebsize ();
250       l1_sizekb = 32;
251     }
252 
253   l1_assoc = 0;
254   l2_sizekb = 512;
255 
256   return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
257 }
258 
259 static const char *
260 detect_processor_linux (void)
261 {
262   const char *platform;
263 
264   platform = elf_platform ();
265 
266   if (platform != NULL)
267     return platform;
268   else
269     return "powerpc";
270 }
271 
272 #endif /* __linux__ */
273 
274 #ifdef _AIX
275 /* Returns the description of caches on AIX.  */
276 
277 static char *
278 detect_caches_aix (void)
279 {
280   unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
281 
282   l1_sizekb = _system_configuration.dcache_size / 1024;
283   l1_line = _system_configuration.dcache_line;
284   l1_assoc = _system_configuration.dcache_asc;
285   l2_sizekb = _system_configuration.L2_cache_size / 1024;
286 
287   return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
288 }
289 
290 
291 /* Returns the processor implementation on AIX.  */
292 
293 static const char *
294 detect_processor_aix (void)
295 {
296   switch (_system_configuration.implementation)
297     {
298     case 0x0001:
299       return "rios1";
300 
301     case 0x0002:
302       return "rsc";
303 
304     case 0x0004:
305       return "rios2";
306 
307     case 0x0008:
308       return "601";
309 
310     case 0x0020:
311       return "603";
312 
313     case 0x0010:
314       return "604";
315 
316     case 0x0040:
317       return "620";
318 
319     case 0x0080:
320       return "630";
321 
322     case 0x0100:
323     case 0x0200:
324     case 0x0400:
325       return "rs64";
326 
327     case 0x0800:
328       return "power4";
329 
330     case 0x2000:
331       if (_system_configuration.version == 0x0F0000)
332 	return "power5";
333       else
334 	return "power5+";
335 
336     case 0x4000:
337       return "power6";
338 
339     default:
340       return "powerpc";
341     }
342 }
343 #endif /* _AIX */
344 
345 
346 /*
347  * Array to map -mcpu=native names to the switches passed to the assembler.
348  * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here
349  * should be made there as well.
350  */
351 
352 struct asm_name {
353   const char *cpu;
354   const char *asm_sw;
355 };
356 
357 static const struct asm_name asm_names[] = {
358 #if defined (_AIX)
359   { "power3",	"-m620" },
360   { "power4",	"-mpwr4" },
361   { "power5",	"-mpwr5" },
362   { "power5+",	"-mpwr5x" },
363   { "power6",	"-mpwr6" },
364   { "power6x",	"-mpwr6" },
365   { "power7",	"-mpwr7" },
366   { "powerpc",	"-mppc" },
367   { "rs64a",	"-mppc" },
368   { "603",	"-m603" },
369   { "603e",	"-m603" },
370   { "604",	"-m604" },
371   { "604e",	"-m604" },
372   { "620",	"-m620" },
373   { "630",	"-m620" },
374   { "970",	"-m970" },
375   { "G5",	"-m970" },
376   { NULL,	"\
377 %{!maix64: \
378 %{mpowerpc64: -mppc64} \
379 %{maltivec: -m970} \
380 %{!maltivec: %{!mpower64: %(asm_default)}}}" },
381 
382 #else
383   { "common",	"-mcom" },
384   { "cell",	"-mcell" },
385   { "power",	"-mpwr" },
386   { "power2",	"-mpwrx" },
387   { "power3",	"-mppc64" },
388   { "power4",	"-mpower4" },
389   { "power5",	"%(asm_cpu_power5)" },
390   { "power5+",	"%(asm_cpu_power5)" },
391   { "power6",	"%(asm_cpu_power6) -maltivec" },
392   { "power6x",	"%(asm_cpu_power6) -maltivec" },
393   { "power7",	"%(asm_cpu_power7)" },
394   { "powerpc",	"-mppc" },
395   { "rios",	"-mpwr" },
396   { "rios1",	"-mpwr" },
397   { "rios2",	"-mpwrx" },
398   { "rsc",	"-mpwr" },
399   { "rsc1",	"-mpwr" },
400   { "rs64a",	"-mppc64" },
401   { "401",	"-mppc" },
402   { "403",	"-m403" },
403   { "405",	"-m405" },
404   { "405fp",	"-m405" },
405   { "440",	"-m440" },
406   { "440fp",	"-m440" },
407   { "464",	"-m440" },
408   { "464fp",	"-m440" },
409   { "505",	"-mppc" },
410   { "601",	"-m601" },
411   { "602",	"-mppc" },
412   { "603",	"-mppc" },
413   { "603e",	"-mppc" },
414   { "ec603e",	"-mppc" },
415   { "604",	"-mppc" },
416   { "604e",	"-mppc" },
417   { "620",	"-mppc64" },
418   { "630",	"-mppc64" },
419   { "740",	"-mppc" },
420   { "750",	"-mppc" },
421   { "G3",	"-mppc" },
422   { "7400",	"-mppc -maltivec" },
423   { "7450",	"-mppc -maltivec" },
424   { "G4",	"-mppc -maltivec" },
425   { "801",	"-mppc" },
426   { "821",	"-mppc" },
427   { "823",	"-mppc" },
428   { "860",	"-mppc" },
429   { "970",	"-mpower4 -maltivec" },
430   { "G5",	"-mpower4 -maltivec" },
431   { "8540",	"-me500" },
432   { "8548",	"-me500" },
433   { "e300c2",	"-me300" },
434   { "e300c3",	"-me300" },
435   { "e500mc",	"-me500mc" },
436   { NULL,	"\
437 %{mpower: %{!mpower2: -mpwr}} \
438 %{mpower2: -mpwrx} \
439 %{mpowerpc64*: -mppc64} \
440 %{!mpowerpc64*: %{mpowerpc*: -mppc}} \
441 %{mno-power: %{!mpowerpc*: -mcom}} \
442 %{!mno-power: %{!mpower*: %(asm_default)}}" },
443 #endif
444 };
445 
446 /* This will be called by the spec parser in gcc.c when it sees
447    a %:local_cpu_detect(args) construct.  Currently it will be called
448    with either "arch" or "tune" as argument depending on if -march=native
449    or -mtune=native is to be substituted.
450 
451    Additionally it will be called with "asm" to select the appropriate flags
452    for the assembler.
453 
454    It returns a string containing new command line parameters to be
455    put at the place of the above two options, depending on what CPU
456    this is executed.
457 
458    ARGC and ARGV are set depending on the actual arguments given
459    in the spec.  */
460 const char *
461 host_detect_local_cpu (int argc, const char **argv)
462 {
463   const char *cpu = NULL;
464   const char *cache = "";
465   const char *options = "";
466   bool arch;
467   bool assembler;
468   size_t i;
469 
470   if (argc < 1)
471     return NULL;
472 
473   arch = strcmp (argv[0], "cpu") == 0;
474   assembler = (!arch && strcmp (argv[0], "asm") == 0);
475   if (!arch && !assembler && strcmp (argv[0], "tune"))
476     return NULL;
477 
478   if (! assembler)
479     {
480 #if defined (_AIX)
481       cache = detect_caches_aix ();
482 #elif defined (__APPLE__)
483       cache = detect_caches_darwin ();
484 #elif defined (__FreeBSD__)
485       cache = detect_caches_freebsd ();
486       /* FreeBSD PPC does not provide any cache information yet.  */
487       cache = "";
488 #elif defined (__linux__)
489       cache = detect_caches_linux ();
490       /* PPC Linux does not provide any cache information yet.  */
491       cache = "";
492 #else
493       cache = "";
494 #endif
495     }
496 
497 #if defined (_AIX)
498   cpu = detect_processor_aix ();
499 #elif defined (__APPLE__)
500   cpu = detect_processor_darwin ();
501 #elif defined (__FreeBSD__)
502   cpu = detect_processor_freebsd ();
503 #elif defined (__linux__)
504   cpu = detect_processor_linux ();
505 #else
506   cpu = "powerpc";
507 #endif
508 
509   if (assembler)
510     {
511       for (i = 0; i < sizeof (asm_names) / sizeof (asm_names[0]); i++)
512 	{
513 	  if (!asm_names[i].cpu || !strcmp (asm_names[i].cpu, cpu))
514 	    return asm_names[i].asm_sw;
515 	}
516 
517       return NULL;
518     }
519 
520   return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL);
521 }
522 
523 #else /* GCC_VERSION */
524 
525 /* If we aren't compiling with GCC we just provide a minimal
526    default value.  */
527 const char *
528 host_detect_local_cpu (int argc, const char **argv)
529 {
530   const char *cpu;
531   bool arch;
532 
533   if (argc < 1)
534     return NULL;
535 
536   arch = strcmp (argv[0], "cpu") == 0;
537   if (!arch && strcmp (argv[0], "tune"))
538     return NULL;
539 
540   if (arch)
541     cpu = "powerpc";
542 
543   return concat ("-m", argv[0], "=", cpu, NULL);
544 }
545 
546 #endif /* GCC_VERSION */
547 
548