1 /* Subroutines for the gcc driver.
2 Copyright (C) 2007-2018 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/>. */
20 #define IN_TARGET_CODE 1
24 #include "coretypes.h"
29 # include <sys/systemcfg.h>
36 #if defined (__APPLE__) || (__FreeBSD__)
37 # include <sys/types.h>
38 # include <sys/sysctl.h>
41 const char *host_detect_local_cpu (int argc
, const char **argv
);
45 /* Returns parameters that describe L1_ASSOC associative cache of size
46 L1_SIZEKB with lines of size L1_LINE, and L2_SIZEKB. */
49 describe_cache (unsigned l1_sizekb
, unsigned l1_line
,
50 unsigned l1_assoc ATTRIBUTE_UNUSED
, unsigned l2_sizekb
)
52 char l1size
[1000], line
[1000], l2size
[1000];
54 /* At the moment, gcc middle-end does not use the information about the
55 associativity of the cache. */
57 sprintf (l1size
, "--param l1-cache-size=%u", l1_sizekb
);
58 sprintf (line
, "--param l1-cache-line-size=%u", l1_line
);
59 sprintf (l2size
, "--param l2-cache-size=%u", l2_sizekb
);
61 return concat (l1size
, " ", line
, " ", l2size
, " ", NULL
);
66 /* Returns the description of caches on Darwin. */
69 detect_caches_darwin (void)
71 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
73 static int l1_size_name
[2] = { CTL_HW
, HW_L1DCACHESIZE
};
74 static int l1_line_name
[2] = { CTL_HW
, HW_CACHELINE
};
75 static int l2_size_name
[2] = { CTL_HW
, HW_L2CACHESIZE
};
77 sysctl (l1_size_name
, 2, &l1_sizekb
, &len
, NULL
, 0);
78 sysctl (l1_line_name
, 2, &l1_line
, &len
, NULL
, 0);
79 sysctl (l2_size_name
, 2, &l2_sizekb
, &len
, NULL
, 0);
82 return describe_cache (l1_sizekb
/ 1024, l1_line
, l1_assoc
,
87 detect_processor_darwin (void)
92 sysctlbyname ("hw.cpusubtype", &proc
, &len
, NULL
, 0);
127 #endif /* __APPLE__ */
131 /* Returns the description of caches on FreeBSD PPC. */
134 detect_caches_freebsd (void)
136 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
139 /* Currently, as of FreeBSD-7.0, there is only the cacheline_size
140 available via sysctl. */
141 sysctlbyname ("machdep.cacheline_size", &l1_line
, &len
, NULL
, 0);
147 return describe_cache (l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
);
150 /* Currently returns default powerpc. */
152 detect_processor_freebsd (void)
157 #endif /* __FreeBSD__ */
161 /* Returns AT_PLATFORM if present, otherwise generic PowerPC. */
168 fd
= open ("/proc/self/auxv", O_RDONLY
);
176 n
= read (fd
, buf
, sizeof (buf
));
181 for (av
= (ElfW(auxv_t
) *) buf
; av
->a_type
!= AT_NULL
; ++av
)
185 return (const char *) av
->a_un
.a_val
;
195 /* Returns AT_DCACHEBSIZE if present, otherwise generic 32. */
198 elf_dcachebsize (void)
202 fd
= open ("/proc/self/auxv", O_RDONLY
);
210 n
= read (fd
, buf
, sizeof (buf
));
215 for (av
= (ElfW(auxv_t
) *) buf
; av
->a_type
!= AT_NULL
; ++av
)
219 return av
->a_un
.a_val
;
229 /* Returns the description of caches on Linux. */
232 detect_caches_linux (void)
234 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
235 const char *platform
;
237 platform
= elf_platform ();
239 if (platform
!= NULL
)
243 if (platform
[5] == '6')
244 /* POWER6 and POWER6x */
251 l1_line
= elf_dcachebsize ();
258 return describe_cache (l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
);
262 detect_processor_linux (void)
264 const char *platform
;
266 platform
= elf_platform ();
268 if (platform
!= NULL
)
274 #endif /* __linux__ */
277 /* Returns the description of caches on AIX. */
280 detect_caches_aix (void)
282 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
284 l1_sizekb
= _system_configuration
.dcache_size
/ 1024;
285 l1_line
= _system_configuration
.dcache_line
;
286 l1_assoc
= _system_configuration
.dcache_asc
;
287 l2_sizekb
= _system_configuration
.L2_cache_size
/ 1024;
289 return describe_cache (l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
);
293 /* Returns the processor implementation on AIX. */
296 detect_processor_aix (void)
298 switch (_system_configuration
.implementation
)
324 if (_system_configuration
.version
== 0x0F0000)
349 * Array to map -mcpu=native names to the switches passed to the assembler.
350 * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here
351 * should be made there as well.
359 static const struct asm_name asm_names
[] = {
361 { "power3", "-m620" },
362 { "power4", "-mpwr4" },
363 { "power5", "-mpwr5" },
364 { "power5+", "-mpwr5x" },
365 { "power6", "-mpwr6" },
366 { "power6x", "-mpwr6" },
367 { "power7", "-mpwr7" },
368 { "power8", "-mpwr8" },
369 { "power9", "-mpwr9" },
370 { "powerpc", "-mppc" },
371 { "rs64a", "-mppc" },
382 %{mpowerpc64: -mppc64} \
384 %{!maltivec: %{!mpowerpc64: %(asm_default)}}}" },
387 { "cell", "-mcell" },
388 { "power3", "-mppc64" },
389 { "power4", "-mpower4" },
390 { "power5", "%(asm_cpu_power5)" },
391 { "power5+", "%(asm_cpu_power5)" },
392 { "power6", "%(asm_cpu_power6) -maltivec" },
393 { "power6x", "%(asm_cpu_power6) -maltivec" },
394 { "power7", "%(asm_cpu_power7)" },
395 { "power8", "%(asm_cpu_power8)" },
396 { "power9", "%(asm_cpu_power9)" },
397 { "powerpc", "-mppc" },
398 { "rs64a", "-mppc64" },
402 { "405fp", "-m405" },
404 { "440fp", "-m440" },
406 { "464fp", "-m440" },
412 { "ec603e", "-mppc" },
415 { "620", "-mppc64" },
416 { "630", "-mppc64" },
420 { "7400", "-mppc -maltivec" },
421 { "7450", "-mppc -maltivec" },
422 { "G4", "-mppc -maltivec" },
427 { "970", "-mpower4 -maltivec" },
428 { "G5", "-mpower4 -maltivec" },
429 { "8540", "-me500" },
430 { "8548", "-me500" },
431 { "e300c2", "-me300" },
432 { "e300c3", "-me300" },
433 { "e500mc", "-me500mc" },
435 %{mpowerpc64*: -mppc64} \
436 %{!mpowerpc64*: %(asm_default)}" },
440 /* This will be called by the spec parser in gcc.c when it sees
441 a %:local_cpu_detect(args) construct. Currently it will be called
442 with either "arch" or "tune" as argument depending on if -march=native
443 or -mtune=native is to be substituted.
445 Additionally it will be called with "asm" to select the appropriate flags
448 It returns a string containing new command line parameters to be
449 put at the place of the above two options, depending on what CPU
452 ARGC and ARGV are set depending on the actual arguments given
455 host_detect_local_cpu (int argc
, const char **argv
)
457 const char *cpu
= NULL
;
458 const char *cache
= "";
459 const char *options
= "";
467 arch
= strcmp (argv
[0], "cpu") == 0;
468 assembler
= (!arch
&& strcmp (argv
[0], "asm") == 0);
469 if (!arch
&& !assembler
&& strcmp (argv
[0], "tune"))
475 cache
= detect_caches_aix ();
476 #elif defined (__APPLE__)
477 cache
= detect_caches_darwin ();
478 #elif defined (__FreeBSD__)
479 cache
= detect_caches_freebsd ();
480 /* FreeBSD PPC does not provide any cache information yet. */
482 #elif defined (__linux__)
483 cache
= detect_caches_linux ();
484 /* PPC Linux does not provide any cache information yet. */
492 cpu
= detect_processor_aix ();
493 #elif defined (__APPLE__)
494 cpu
= detect_processor_darwin ();
495 #elif defined (__FreeBSD__)
496 cpu
= detect_processor_freebsd ();
497 #elif defined (__linux__)
498 cpu
= detect_processor_linux ();
505 for (i
= 0; i
< sizeof (asm_names
) / sizeof (asm_names
[0]); i
++)
507 if (!asm_names
[i
].cpu
|| !strcmp (asm_names
[i
].cpu
, cpu
))
508 return asm_names
[i
].asm_sw
;
514 return concat (cache
, "-m", argv
[0], "=", cpu
, " ", options
, NULL
);
517 #else /* GCC_VERSION */
519 /* If we aren't compiling with GCC we just provide a minimal
522 host_detect_local_cpu (int argc
, const char **argv
)
530 arch
= strcmp (argv
[0], "cpu") == 0;
531 if (!arch
&& strcmp (argv
[0], "tune"))
537 return concat ("-m", argv
[0], "=", cpu
, NULL
);
540 #endif /* GCC_VERSION */