1 /* Subroutines for the gcc driver.
2 Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
4 This file is part of GCC.
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)
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.
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/>. */
22 #include "coretypes.h"
27 # include <sys/systemcfg.h>
34 #if defined (__APPLE__) || (__FreeBSD__)
35 # include <sys/types.h>
36 # include <sys/sysctl.h>
39 const char *host_detect_local_cpu (int argc
, const char **argv
);
43 /* Returns parameters that describe L1_ASSOC associative cache of size
44 L1_SIZEKB with lines of size L1_LINE, and L2_SIZEKB. */
47 describe_cache (unsigned l1_sizekb
, unsigned l1_line
,
48 unsigned l1_assoc ATTRIBUTE_UNUSED
, unsigned l2_sizekb
)
50 char l1size
[1000], line
[1000], l2size
[1000];
52 /* At the moment, gcc middle-end does not use the information about the
53 associativity of the cache. */
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
);
59 return concat (l1size
, " ", line
, " ", l2size
, " ", NULL
);
64 /* Returns the description of caches on Darwin. */
67 detect_caches_darwin (void)
69 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
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
};
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);
80 return describe_cache (l1_sizekb
/ 1024, l1_line
, l1_assoc
,
85 detect_processor_darwin (void)
90 sysctlbyname ("hw.cpusubtype", &proc
, &len
, NULL
, 0);
125 #endif /* __APPLE__ */
129 /* Returns the description of caches on FreeBSD PPC. */
132 detect_caches_freebsd (void)
134 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
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);
145 return describe_cache (l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
);
148 /* Currently returns default powerpc. */
150 detect_processor_freebsd (void)
155 #endif /* __FreeBSD__ */
159 /* Returns AT_PLATFORM if present, otherwise generic PowerPC. */
166 fd
= open ("/proc/self/auxv", O_RDONLY
);
174 n
= read (fd
, buf
, sizeof (buf
));
179 for (av
= (ElfW(auxv_t
) *) buf
; av
->a_type
!= AT_NULL
; ++av
)
183 return (const char *) av
->a_un
.a_val
;
193 /* Returns AT_PLATFORM if present, otherwise generic 32. */
196 elf_dcachebsize (void)
200 fd
= open ("/proc/self/auxv", O_RDONLY
);
208 n
= read (fd
, buf
, sizeof (buf
));
213 for (av
= (ElfW(auxv_t
) *) buf
; av
->a_type
!= AT_NULL
; ++av
)
217 return av
->a_un
.a_val
;
227 /* Returns the description of caches on Linux. */
230 detect_caches_linux (void)
232 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
233 const char *platform
;
235 platform
= elf_platform ();
237 if (platform
!= NULL
)
241 if (platform
[5] == '6')
242 /* POWER6 and POWER6x */
249 l1_line
= elf_dcachebsize ();
256 return describe_cache (l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
);
260 detect_processor_linux (void)
262 const char *platform
;
264 platform
= elf_platform ();
266 if (platform
!= NULL
)
272 #endif /* __linux__ */
275 /* Returns the description of caches on AIX. */
278 detect_caches_aix (void)
280 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
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;
287 return describe_cache (l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
);
291 /* Returns the processor implementation on AIX. */
294 detect_processor_aix (void)
296 switch (_system_configuration
.implementation
)
331 if (_system_configuration
.version
== 0x0F0000)
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.
357 static const struct asm_name asm_names
[] = {
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" },
378 %{mpowerpc64: -mppc64} \
380 %{!maltivec: %{!mpower64: %(asm_default)}}}" },
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" },
396 { "rios1", "-mpwr" },
397 { "rios2", "-mpwrx" },
400 { "rs64a", "-mppc64" },
404 { "405fp", "-m405" },
406 { "440fp", "-m440" },
408 { "464fp", "-m440" },
414 { "ec603e", "-mppc" },
417 { "620", "-mppc64" },
418 { "630", "-mppc64" },
422 { "7400", "-mppc -maltivec" },
423 { "7450", "-mppc -maltivec" },
424 { "G4", "-mppc -maltivec" },
429 { "970", "-mpower4 -maltivec" },
430 { "G5", "-mpower4 -maltivec" },
431 { "8540", "-me500" },
432 { "8548", "-me500" },
433 { "e300c2", "-me300" },
434 { "e300c3", "-me300" },
435 { "e500mc", "-me500mc" },
437 %{mpower: %{!mpower2: -mpwr}} \
439 %{mpowerpc64*: -mppc64} \
440 %{!mpowerpc64*: %{mpowerpc*: -mppc}} \
441 %{mno-power: %{!mpowerpc*: -mcom}} \
442 %{!mno-power: %{!mpower*: %(asm_default)}}" },
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.
451 Additionally it will be called with "asm" to select the appropriate flags
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
458 ARGC and ARGV are set depending on the actual arguments given
461 host_detect_local_cpu (int argc
, const char **argv
)
463 const char *cpu
= NULL
;
464 const char *cache
= "";
465 const char *options
= "";
473 arch
= strcmp (argv
[0], "cpu") == 0;
474 assembler
= (!arch
&& strcmp (argv
[0], "asm") == 0);
475 if (!arch
&& !assembler
&& strcmp (argv
[0], "tune"))
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. */
488 #elif defined (__linux__)
489 cache
= detect_caches_linux ();
490 /* PPC Linux does not provide any cache information yet. */
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 ();
511 for (i
= 0; i
< sizeof (asm_names
) / sizeof (asm_names
[0]); i
++)
513 if (!asm_names
[i
].cpu
|| !strcmp (asm_names
[i
].cpu
, cpu
))
514 return asm_names
[i
].asm_sw
;
520 return concat (cache
, "-m", argv
[0], "=", cpu
, " ", options
, NULL
);
523 #else /* GCC_VERSION */
525 /* If we aren't compiling with GCC we just provide a minimal
528 host_detect_local_cpu (int argc
, const char **argv
)
536 arch
= strcmp (argv
[0], "cpu") == 0;
537 if (!arch
&& strcmp (argv
[0], "tune"))
543 return concat ("-m", argv
[0], "=", cpu
, NULL
);
546 #endif /* GCC_VERSION */