1 /* Subroutines for the gcc driver.
2 Copyright (C) 2007-2024 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"
26 #include "diagnostic.h"
31 # include <sys/systemcfg.h>
38 #if defined (__APPLE__) || (__FreeBSD__)
39 # include <sys/types.h>
40 # include <sys/sysctl.h>
44 /* Canonical GCC cpu name table. */
45 static const char *rs6000_supported_cpu_names
[] =
47 #define RS6000_CPU(NAME, CPU, FLAGS) NAME,
48 #include "rs6000-cpus.def"
52 /* This table holds a list of cpus where their Linux AT_PLATFORM name differs
53 from their GCC canonical name. The first column in a row contains the GCC
54 canonical cpu name and the other columns in that row contain AT_PLATFORM
55 names that should be mapped to the canonical name. */
57 static const char *linux_cpu_translation_table
[][4] = {
58 { "403", "ppc403", NULL
},
59 { "405", "ppc405", NULL
},
60 { "440", "ppc440", "ppc440gp", NULL
},
61 { "476", "ppc470", NULL
},
62 { "601", "ppc601", NULL
},
63 { "603", "ppc603", NULL
},
64 { "604", "ppc604", NULL
},
65 { "7400", "ppc7400", NULL
},
66 { "7450", "ppc7450", NULL
},
67 { "750", "ppc750", NULL
},
68 { "823", "ppc823", NULL
},
69 { "8540", "ppc8540", NULL
},
70 { "8548", "ppc8548", NULL
},
71 { "970", "ppc970", NULL
},
72 { "cell", "ppc-cell-be", NULL
},
73 { "e500mc", "ppce500mc", NULL
},
74 { "e5500", "ppce5500", NULL
},
75 { "e6500", "ppce6500", NULL
},
76 { "power7", "power7+", NULL
},
77 { NULL
} /* End of table sentinel. */
81 const char *host_detect_local_cpu (int argc
, const char **argv
);
85 /* Returns parameters that describe L1_ASSOC associative cache of size
86 L1_SIZEKB with lines of size L1_LINE, and L2_SIZEKB. */
89 describe_cache (unsigned l1_sizekb
, unsigned l1_line
,
90 unsigned l1_assoc ATTRIBUTE_UNUSED
, unsigned l2_sizekb
)
92 char l1size
[1000], line
[1000], l2size
[1000];
94 /* At the moment, gcc middle-end does not use the information about the
95 associativity of the cache. */
97 sprintf (l1size
, "--param l1-cache-size=%u", l1_sizekb
);
98 sprintf (line
, "--param l1-cache-line-size=%u", l1_line
);
99 sprintf (l2size
, "--param l2-cache-size=%u", l2_sizekb
);
101 return concat (l1size
, " ", line
, " ", l2size
, " ", NULL
);
106 /* Returns the description of caches on Darwin. */
109 detect_caches_darwin (void)
111 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
113 static int l1_size_name
[2] = { CTL_HW
, HW_L1DCACHESIZE
};
114 static int l1_line_name
[2] = { CTL_HW
, HW_CACHELINE
};
115 static int l2_size_name
[2] = { CTL_HW
, HW_L2CACHESIZE
};
117 sysctl (l1_size_name
, 2, &l1_sizekb
, &len
, NULL
, 0);
118 sysctl (l1_line_name
, 2, &l1_line
, &len
, NULL
, 0);
119 sysctl (l2_size_name
, 2, &l2_sizekb
, &len
, NULL
, 0);
122 return describe_cache (l1_sizekb
/ 1024, l1_line
, l1_assoc
,
127 detect_processor_darwin (void)
132 sysctlbyname ("hw.cpusubtype", &proc
, &len
, NULL
, 0);
167 #endif /* __APPLE__ */
171 /* Returns the description of caches on FreeBSD PPC. */
174 detect_caches_freebsd (void)
176 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
179 /* Currently, as of FreeBSD-7.0, there is only the cacheline_size
180 available via sysctl. */
181 sysctlbyname ("machdep.cacheline_size", &l1_line
, &len
, NULL
, 0);
187 return describe_cache (l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
);
190 /* Currently returns default powerpc. */
192 detect_processor_freebsd (void)
197 #endif /* __FreeBSD__ */
201 /* Returns the canonical AT_PLATFORM if present, otherwise NULL. */
206 /* Used to cache the result we determine below. */
207 static const char *cpu
= NULL
;
209 /* Use the cached AT_PLATFORM cpu name if we've already determined it. */
213 int fd
= open ("/proc/self/auxv", O_RDONLY
);
221 n
= read (fd
, buf
, sizeof (buf
));
226 for (av
= (ElfW(auxv_t
) *) buf
; av
->a_type
!= AT_NULL
; ++av
)
227 if (av
->a_type
== AT_PLATFORM
)
229 /* Cache the result. */
230 cpu
= (const char *) av
->a_un
.a_val
;
235 /* Verify that CPU is either a valid -mcpu=<cpu> option name, or is a
236 valid alternative name. If it is a valid alternative name, then use
237 the canonical name. */
243 /* Check if AT_PLATFORM is a GCC canonical cpu name. */
244 for (i
= 0; i
< ARRAY_SIZE (rs6000_supported_cpu_names
); i
++)
245 if (!strcmp (cpu
, rs6000_supported_cpu_names
[i
]))
248 /* Check if AT_PLATFORM can be translated to a canonical cpu name. */
249 for (i
= 0; linux_cpu_translation_table
[i
][0] != NULL
; i
++)
251 const char *canonical
= linux_cpu_translation_table
[i
][0];
252 for (j
= 1; linux_cpu_translation_table
[i
][j
] != NULL
; j
++)
253 if (!strcmp (cpu
, linux_cpu_translation_table
[i
][j
]))
255 /* Cache the result. */
261 /* The kernel returned an AT_PLATFORM name we do not support. */
262 auto_vec
<const char *> candidates
;
263 for (i
= 0; i
< ARRAY_SIZE (rs6000_supported_cpu_names
); i
++)
264 candidates
.safe_push (rs6000_supported_cpu_names
[i
]);
265 candidates_list_and_hint (cpu
, s
, candidates
);
266 error ("unsupported cpu name returned from kernel "
267 "for %<-mcpu=native%>: %s", cpu
);
268 fatal_error (input_location
, "please use an explicit cpu name; "
269 "valid cpu names are: %s", s
);
275 /* Returns AT_DCACHEBSIZE if present, otherwise generic 32. */
278 elf_dcachebsize (void)
282 fd
= open ("/proc/self/auxv", O_RDONLY
);
290 n
= read (fd
, buf
, sizeof (buf
));
295 for (av
= (ElfW(auxv_t
) *) buf
; av
->a_type
!= AT_NULL
; ++av
)
299 return av
->a_un
.a_val
;
309 /* Returns the description of caches on Linux. */
312 detect_caches_linux (void)
314 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
315 const char *platform
;
317 platform
= elf_platform ();
319 if (platform
!= NULL
)
323 if (platform
[5] == '6')
324 /* POWER6 and POWER6x */
331 l1_line
= elf_dcachebsize ();
338 return describe_cache (l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
);
342 detect_processor_linux (void)
344 const char *platform
;
346 platform
= elf_platform ();
348 if (platform
!= NULL
)
354 #endif /* __linux__ */
357 /* Returns the description of caches on AIX. */
360 detect_caches_aix (void)
362 unsigned l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
;
364 l1_sizekb
= _system_configuration
.dcache_size
/ 1024;
365 l1_line
= _system_configuration
.dcache_line
;
366 l1_assoc
= _system_configuration
.dcache_asc
;
367 l2_sizekb
= _system_configuration
.L2_cache_size
/ 1024;
369 return describe_cache (l1_sizekb
, l1_line
, l1_assoc
, l2_sizekb
);
373 /* Returns the processor implementation on AIX. */
376 detect_processor_aix (void)
378 switch (_system_configuration
.implementation
)
404 if (_system_configuration
.version
== 0x0F0000)
432 * Array to map -mcpu=native names to the switches passed to the assembler.
433 * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here
434 * should be made there as well.
442 static const struct asm_name asm_names
[] = {
444 { "power3", "-m620" },
445 { "power4", "-mpwr4" },
446 { "power5", "-mpwr5" },
447 { "power5+", "-mpwr5x" },
448 { "power6", "-mpwr6" },
449 { "power6x", "-mpwr6" },
450 { "power7", "-mpwr7" },
451 { "power8", "-mpwr8" },
452 { "power9", "-mpwr9" },
453 { "power10", "-mpwr10" },
454 { "power11", "-mpwr11" },
455 { "powerpc", "-mppc" },
468 maix64|mpowerpc64: -mppc64; \
469 : %(asm_default)}" },
472 { "cell", "-mcell" },
473 { "power3", "-mppc64" },
474 { "power4", "-mpower4" },
475 { "power5", "-mpower5" },
476 { "power5+", "-mpower5" },
477 { "power6", "-mpower6 %{!mvsx:%{!maltivec:-maltivec}}" },
478 { "power6x", "-mpower6 %{!mvsx:%{!maltivec:-maltivec}}" },
479 { "power7", "-mpower7" },
480 { "power8", "-mpower8" },
481 { "power9", "-mpower9" },
482 { "power10", "-mpower10" },
483 { "power11", "-mpower11" },
485 { "powerpc", "-mppc" },
486 { "powerpc64", "-mppc64" },
487 { "powerpc64le", "-mpower8" },
488 { "rs64", "-mppc64" },
492 { "405fp", "-m405" },
494 { "440fp", "-m440" },
496 { "464fp", "-m440" },
498 { "476fp", "-m476" },
504 { "ec603e", "-mppc" },
507 { "620", "-mppc64" },
508 { "630", "-mppc64" },
512 { "7400", "-mppc %{!mvsx:%{!maltivec:-maltivec}}" },
513 { "7450", "-mppc %{!mvsx:%{!maltivec:-maltivec}}" },
514 { "G4", "-mppc %{!mvsx:%{!maltivec:-maltivec}}" },
519 { "970", "-mpower4 %{!mvsx:%{!maltivec:-maltivec}}" },
520 { "G5", "-mpower4 %{!mvsx:%{!maltivec:-maltivec}}" },
521 { "8540", "-me500" },
522 { "8548", "-me500" },
523 { "e300c2", "-me300" },
524 { "e300c3", "-me300" },
525 { "e500mc", "-me500mc" },
526 { "e500mc64", "-me500mc64" },
527 { "e5500", "-me5500" },
528 { "e6500", "-me6500" },
529 { "titan", "-mtitan" },
531 %{mcrypto|mdirect-move|mhtm: -mpower8; \
533 mpowerpc64: -mppc64; \
534 : %(asm_default)}" },
538 /* This will be called by the spec parser in gcc.cc when it sees
539 a %:local_cpu_detect(args) construct. Currently it will be called
540 with either "arch" or "tune" as argument depending on if -march=native
541 or -mtune=native is to be substituted.
543 Additionally it will be called with "asm" to select the appropriate flags
546 It returns a string containing new command line parameters to be
547 put at the place of the above two options, depending on what CPU
550 ARGC and ARGV are set depending on the actual arguments given
553 host_detect_local_cpu (int argc
, const char **argv
)
555 const char *cpu
= NULL
;
556 const char *cache
= "";
557 const char *options
= "";
565 arch
= strcmp (argv
[0], "cpu") == 0;
566 assembler
= (!arch
&& strcmp (argv
[0], "asm") == 0);
567 if (!arch
&& !assembler
&& strcmp (argv
[0], "tune"))
573 cache
= detect_caches_aix ();
574 #elif defined (__APPLE__)
575 cache
= detect_caches_darwin ();
576 #elif defined (__FreeBSD__)
577 cache
= detect_caches_freebsd ();
578 /* FreeBSD PPC does not provide any cache information yet. */
580 #elif defined (__linux__)
581 cache
= detect_caches_linux ();
582 /* PPC Linux does not provide any cache information yet. */
590 cpu
= detect_processor_aix ();
591 #elif defined (__APPLE__)
592 cpu
= detect_processor_darwin ();
593 #elif defined (__FreeBSD__)
594 cpu
= detect_processor_freebsd ();
595 #elif defined (__linux__)
596 cpu
= detect_processor_linux ();
603 for (i
= 0; i
< ARRAY_SIZE (asm_names
); i
++)
605 if (!asm_names
[i
].cpu
|| !strcmp (asm_names
[i
].cpu
, cpu
))
606 return asm_names
[i
].asm_sw
;
612 return concat (cache
, "-m", argv
[0], "=", cpu
, " ", options
, NULL
);
615 #else /* GCC_VERSION */
617 /* If we aren't compiling with GCC we just provide a minimal
620 host_detect_local_cpu (int argc
, const char **argv
)
628 arch
= strcmp (argv
[0], "cpu") == 0;
629 if (!arch
&& strcmp (argv
[0], "tune"))
635 return concat ("-m", argv
[0], "=", cpu
, NULL
);
638 #endif /* GCC_VERSION */