]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/rs6000/driver-rs6000.c
Update Copyright years for files modified in 2010.
[thirdparty/gcc.git] / gcc / config / rs6000 / driver-rs6000.c
CommitLineData
0eab6840 1/* Subroutines for the gcc driver.
cacf1ca8 2 Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
0eab6840
DE
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 3, 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 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__
656ca3ad 31# include <link.h>
0eab6840
DE
32#endif
33
3b7abfda 34#if defined (__APPLE__) || (__FreeBSD__)
0eab6840
DE
35# include <sys/types.h>
36# include <sys/sysctl.h>
37#endif
38
39const 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
46static char *
47describe_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
66static char *
67detect_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
84static const char *
85detect_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
3b7abfda
AT
127#ifdef __FreeBSD__
128
129/* Returns the description of caches on FreeBSD PPC. */
130
131static char *
132detect_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. */
149static const char *
150detect_processor_freebsd (void)
151{
152 return "powerpc";
153}
154
155#endif /* __FreeBSD__ */
156
0eab6840
DE
157#ifdef __linux__
158
159/* Returns AT_PLATFORM if present, otherwise generic PowerPC. */
160
161static const char *
162elf_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];
656ca3ad 171 ElfW(auxv_t) *av;
0eab6840
DE
172 ssize_t n;
173
174 n = read (fd, buf, sizeof (buf));
175 close (fd);
176
177 if (n > 0)
178 {
656ca3ad 179 for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
0eab6840
DE
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
195static int
196elf_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];
656ca3ad 205 ElfW(auxv_t) *av;
0eab6840
DE
206 ssize_t n;
207
208 n = read (fd, buf, sizeof (buf));
209 close (fd);
210
211 if (n > 0)
212 {
656ca3ad 213 for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
0eab6840
DE
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
229static char *
230detect_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
259static const char *
260detect_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
277static char *
278detect_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
293static const char *
294detect_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
cacf1ca8
MM
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
352struct asm_name {
353 const char *cpu;
354 const char *asm_sw;
355};
356
357static 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
0eab6840
DE
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
cacf1ca8
MM
451 Additionally it will be called with "asm" to select the appropriate flags
452 for the assembler.
453
0eab6840
DE
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. */
cacf1ca8
MM
460const char *
461host_detect_local_cpu (int argc, const char **argv)
0eab6840
DE
462{
463 const char *cpu = NULL;
464 const char *cache = "";
465 const char *options = "";
466 bool arch;
cacf1ca8
MM
467 bool assembler;
468 size_t i;
0eab6840
DE
469
470 if (argc < 1)
471 return NULL;
472
473 arch = strcmp (argv[0], "cpu") == 0;
cacf1ca8
MM
474 assembler = (!arch && strcmp (argv[0], "asm") == 0);
475 if (!arch && !assembler && strcmp (argv[0], "tune"))
0eab6840
DE
476 return NULL;
477
cacf1ca8
MM
478 if (! assembler)
479 {
0eab6840 480#if defined (_AIX)
cacf1ca8 481 cache = detect_caches_aix ();
0eab6840 482#elif defined (__APPLE__)
cacf1ca8 483 cache = detect_caches_darwin ();
3b7abfda 484#elif defined (__FreeBSD__)
cacf1ca8
MM
485 cache = detect_caches_freebsd ();
486 /* FreeBSD PPC does not provide any cache information yet. */
487 cache = "";
0eab6840 488#elif defined (__linux__)
cacf1ca8
MM
489 cache = detect_caches_linux ();
490 /* PPC Linux does not provide any cache information yet. */
491 cache = "";
0eab6840 492#else
cacf1ca8 493 cache = "";
0eab6840 494#endif
cacf1ca8 495 }
0eab6840
DE
496
497#if defined (_AIX)
498 cpu = detect_processor_aix ();
499#elif defined (__APPLE__)
500 cpu = detect_processor_darwin ();
3b7abfda
AT
501#elif defined (__FreeBSD__)
502 cpu = detect_processor_freebsd ();
0eab6840
DE
503#elif defined (__linux__)
504 cpu = detect_processor_linux ();
505#else
506 cpu = "powerpc";
507#endif
508
cacf1ca8
MM
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
0eab6840
DE
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. */
cacf1ca8
MM
527const char *
528host_detect_local_cpu (int argc, const char **argv)
0eab6840
DE
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