1/* Subroutines for the gcc driver. 2 Copyright (C) 2007-2020 Free Software Foundation, Inc. 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#define IN_TARGET_CODE 1 21 22#include "config.h" 23#include "system.h" 24#include "coretypes.h" 25#include "tm.h" 26#include "diagnostic.h" 27#include "opts.h" 28#include <stdlib.h> 29 30#ifdef _AIX 31# include <sys/systemcfg.h> 32#endif 33 34#ifdef __linux__ 35# include <link.h> 36#endif 37 38#if defined (__APPLE__) || (__FreeBSD__) 39# include <sys/types.h> 40# include <sys/sysctl.h> 41#endif 42 43#ifdef __linux__ 44/* Canonical GCC cpu name table. */ 45static const char *rs6000_supported_cpu_names[] = 46{ 47#define RS6000_CPU(NAME, CPU, FLAGS) NAME, 48#include "rs6000-cpus.def" 49#undef RS6000_CPU 50}; 51 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. */ 56 57static 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. */ 78}; 79#endif 80 81const char *host_detect_local_cpu (int argc, const char **argv); 82 83#if GCC_VERSION >= 0 84 85/* Returns parameters that describe L1_ASSOC associative cache of size 86 L1_SIZEKB with lines of size L1_LINE, and L2_SIZEKB. */ 87 88static char * 89describe_cache (unsigned l1_sizekb, unsigned l1_line, 90 unsigned l1_assoc ATTRIBUTE_UNUSED, unsigned l2_sizekb) 91{ 92 char l1size[1000], line[1000], l2size[1000]; 93 94 /* At the moment, gcc middle-end does not use the information about the 95 associativity of the cache. */ 96 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); 100 101 return concat (l1size, " ", line, " ", l2size, " ", NULL); 102} 103 104#ifdef __APPLE__ 105 106/* Returns the description of caches on Darwin. */ 107 108static char * 109detect_caches_darwin (void) 110{ 111 unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb; 112 size_t len = 4; 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 }; 116 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); 120 l1_assoc = 0; 121 122 return describe_cache (l1_sizekb / 1024, l1_line, l1_assoc, 123 l2_sizekb / 1024); 124} 125 126static const char * 127detect_processor_darwin (void) 128{ 129 unsigned int proc; 130 size_t len = 4; 131 132 sysctlbyname ("hw.cpusubtype", &proc, &len, NULL, 0); 133 134 if (len > 0) 135 switch (proc) 136 { 137 case 1: 138 return "601"; 139 case 2: 140 return "602"; 141 case 3: 142 return "603"; 143 case 4: 144 case 5: 145 return "603e"; 146 case 6: 147 return "604"; 148 case 7: 149 return "604e"; 150 case 8: 151 return "620"; 152 case 9: 153 return "750"; 154 case 10: 155 return "7400"; 156 case 11: 157 return "7450"; 158 case 100: 159 return "970"; 160 default: 161 return "powerpc"; 162 } 163 164 return "powerpc"; 165} 166 167#endif /* __APPLE__ */ 168 169#ifdef __FreeBSD__ 170 171/* Returns the description of caches on FreeBSD PPC. */ 172 173static char * 174detect_caches_freebsd (void) 175{ 176 unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb; 177 size_t len = 4; 178 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); 182 183 l1_sizekb = 32; 184 l1_assoc = 0; 185 l2_sizekb = 512; 186 187 return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb); 188} 189 190/* Currently returns default powerpc. */ 191static const char * 192detect_processor_freebsd (void) 193{ 194 return "powerpc"; 195} 196 197#endif /* __FreeBSD__ */ 198 199#ifdef __linux__ 200 201/* Returns the canonical AT_PLATFORM if present, otherwise NULL. */ 202 203static const char * 204elf_platform (void) 205{ 206 /* Used to cache the result we determine below. */ 207 static const char *cpu = NULL; 208 209 /* Use the cached AT_PLATFORM cpu name if we've already determined it. */ 210 if (cpu != NULL) 211 return cpu; 212 213 int fd = open ("/proc/self/auxv", O_RDONLY); 214 215 if (fd != -1) 216 { 217 char buf[1024]; 218 ElfW(auxv_t) *av; 219 ssize_t n; 220 221 n = read (fd, buf, sizeof (buf)); 222 close (fd); 223 224 if (n > 0) 225 { 226 for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av) 227 if (av->a_type == AT_PLATFORM) 228 { 229 /* Cache the result. */ 230 cpu = (const char *) av->a_un.a_val; 231 break; 232 } 233 } 234 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. */ 238 if (cpu != NULL) 239 { 240 size_t i, j; 241 char *s; 242 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])) 246 return cpu; 247 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++) 250 { 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])) 254 { 255 /* Cache the result. */ 256 cpu = canonical; 257 return cpu; 258 } 259 } 260 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); 270 } 271 } 272 return NULL; 273} 274 275/* Returns AT_DCACHEBSIZE if present, otherwise generic 32. */ 276 277static int 278elf_dcachebsize (void) 279{ 280 int fd; 281 282 fd = open ("/proc/self/auxv", O_RDONLY); 283 284 if (fd != -1) 285 { 286 char buf[1024]; 287 ElfW(auxv_t) *av; 288 ssize_t n; 289 290 n = read (fd, buf, sizeof (buf)); 291 close (fd); 292 293 if (n > 0) 294 { 295 for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av) 296 switch (av->a_type) 297 { 298 case AT_DCACHEBSIZE: 299 return av->a_un.a_val; 300 301 default: 302 break; 303 } 304 } 305 } 306 return 32; 307} 308 309/* Returns the description of caches on Linux. */ 310 311static char * 312detect_caches_linux (void) 313{ 314 unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb; 315 const char *platform; 316 317 platform = elf_platform (); 318 319 if (platform != NULL) 320 { 321 l1_line = 128; 322 323 if (platform[5] == '6') 324 /* POWER6 and POWER6x */ 325 l1_sizekb = 64; 326 else 327 l1_sizekb = 32; 328 } 329 else 330 { 331 l1_line = elf_dcachebsize (); 332 l1_sizekb = 32; 333 } 334 335 l1_assoc = 0; 336 l2_sizekb = 512; 337 338 return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb); 339} 340 341static const char * 342detect_processor_linux (void) 343{ 344 const char *platform; 345 346 platform = elf_platform (); 347 348 if (platform != NULL) 349 return platform; 350 else 351 return "powerpc"; 352} 353 354#endif /* __linux__ */ 355 356#ifdef _AIX 357/* Returns the description of caches on AIX. */ 358 359static char * 360detect_caches_aix (void) 361{ 362 unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb; 363 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; 368 369 return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb); 370} 371 372 373/* Returns the processor implementation on AIX. */ 374 375static const char * 376detect_processor_aix (void) 377{ 378 switch (_system_configuration.implementation) 379 { 380 case 0x0008: 381 return "601"; 382 383 case 0x0020: 384 return "603"; 385 386 case 0x0010: 387 return "604"; 388 389 case 0x0040: 390 return "620"; 391 392 case 0x0080: 393 return "630"; 394 395 case 0x0100: 396 case 0x0200: 397 case 0x0400: 398 return "rs64"; 399 400 case 0x0800: 401 return "power4"; 402 403 case 0x2000: 404 if (_system_configuration.version == 0x0F0000) 405 return "power5"; 406 else 407 return "power5+"; 408 409 case 0x4000: 410 return "power6"; 411 412 case 0x8000: 413 return "power7"; 414 415 case 0x10000: 416 return "power8"; 417 418 case 0x20000: 419 return "power9"; 420 421 default: 422 return "powerpc"; 423 } 424} 425#endif /* _AIX */ 426 427 428/* 429 * Array to map -mcpu=native names to the switches passed to the assembler. 430 * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here 431 * should be made there as well. 432 */ 433 434struct asm_name { 435 const char *cpu; 436 const char *asm_sw; 437}; 438 439static const struct asm_name asm_names[] = { 440#if defined (_AIX) 441 { "power3", "-m620" }, 442 { "power4", "-mpwr4" }, 443 { "power5", "-mpwr5" }, 444 { "power5+", "-mpwr5x" }, 445 { "power6", "-mpwr6" }, 446 { "power6x", "-mpwr6" }, 447 { "power7", "-mpwr7" }, 448 { "power8", "-mpwr8" }, 449 { "power9", "-mpwr9" }, 450 { "power10", "-mpwr10" }, 451 { "powerpc", "-mppc" }, 452 { "rs64", "-mppc" }, 453 { "603", "-m603" }, 454 { "603e", "-m603" }, 455 { "604", "-m604" }, 456 { "604e", "-m604" }, 457 { "620", "-m620" }, 458 { "630", "-m620" }, 459 { "970", "-m970" }, 460 { "G5", "-m970" }, 461 { NULL, "\ 462 %{mvsx: -mpwr6; \ 463 maltivec: -m970; \ 464 maix64|mpowerpc64: -mppc64; \ 465 : %(asm_default)}" }, 466 467#else 468 { "cell", "-mcell" }, 469 { "power3", "-mppc64" }, 470 { "power4", "-mpower4" }, 471 { "power5", "-mpower5" }, 472 { "power5+", "-mpower5" }, 473 { "power6", "-mpower6 %{!mvsx:%{!maltivec:-maltivec}}" }, 474 { "power6x", "-mpower6 %{!mvsx:%{!maltivec:-maltivec}}" }, 475 { "power7", "-mpower7" }, 476 { "power8", "%{mpower9-vector:-mpower9;:-mpower8}" }, 477 { "power9", "-mpower9" }, 478 { "power10", "-mpower10" }, 479 { "a2", "-ma2" }, 480 { "powerpc", "-mppc" }, 481 { "powerpc64", "-mppc64" }, 482 { "powerpc64le", "%{mpower9-vector:-mpower9;:-mpower8}" }, 483 { "rs64", "-mppc64" }, 484 { "401", "-mppc" }, 485 { "403", "-m403" }, 486 { "405", "-m405" }, 487 { "405fp", "-m405" }, 488 { "440", "-m440" }, 489 { "440fp", "-m440" }, 490 { "464", "-m440" }, 491 { "464fp", "-m440" }, 492 { "476", "-m476" }, 493 { "476fp", "-m476" }, 494 { "505", "-mppc" }, 495 { "601", "-m601" }, 496 { "602", "-mppc" }, 497 { "603", "-mppc" }, 498 { "603e", "-mppc" }, 499 { "ec603e", "-mppc" }, 500 { "604", "-mppc" }, 501 { "604e", "-mppc" }, 502 { "620", "-mppc64" }, 503 { "630", "-mppc64" }, 504 { "740", "-mppc" }, 505 { "750", "-mppc" }, 506 { "G3", "-mppc" }, 507 { "7400", "-mppc %{!mvsx:%{!maltivec:-maltivec}}" }, 508 { "7450", "-mppc %{!mvsx:%{!maltivec:-maltivec}}" }, 509 { "G4", "-mppc %{!mvsx:%{!maltivec:-maltivec}}" }, 510 { "801", "-mppc" }, 511 { "821", "-mppc" }, 512 { "823", "-mppc" }, 513 { "860", "-mppc" }, 514 { "970", "-mpower4 %{!mvsx:%{!maltivec:-maltivec}}" }, 515 { "G5", "-mpower4 %{!mvsx:%{!maltivec:-maltivec}}" }, 516 { "8540", "-me500" }, 517 { "8548", "-me500" }, 518 { "e300c2", "-me300" }, 519 { "e300c3", "-me300" }, 520 { "e500mc", "-me500mc" }, 521 { "e500mc64", "-me500mc64" }, 522 { "e5500", "-me5500" }, 523 { "e6500", "-me6500" }, 524 { "titan", "-mtitan" }, 525 { NULL, "\ 526%{mpower9-vector: -mpower9; \ 527 mpower8-vector|mcrypto|mdirect-move|mhtm: -mpower8; \ 528 mvsx: -mpower7; \ 529 mpowerpc64: -mppc64; \ 530 : %(asm_default)}" }, 531#endif 532}; 533 534/* This will be called by the spec parser in gcc.c when it sees 535 a %:local_cpu_detect(args) construct. Currently it will be called 536 with either "arch" or "tune" as argument depending on if -march=native 537 or -mtune=native is to be substituted. 538 539 Additionally it will be called with "asm" to select the appropriate flags 540 for the assembler. 541 542 It returns a string containing new command line parameters to be 543 put at the place of the above two options, depending on what CPU 544 this is executed. 545 546 ARGC and ARGV are set depending on the actual arguments given 547 in the spec. */ 548const char * 549host_detect_local_cpu (int argc, const char **argv) 550{ 551 const char *cpu = NULL; 552 const char *cache = ""; 553 const char *options = ""; 554 bool arch; 555 bool assembler; 556 size_t i; 557 558 if (argc < 1) 559 return NULL; 560 561 arch = strcmp (argv[0], "cpu") == 0; 562 assembler = (!arch && strcmp (argv[0], "asm") == 0); 563 if (!arch && !assembler && strcmp (argv[0], "tune")) 564 return NULL; 565 566 if (! assembler) 567 { 568#if defined (_AIX) 569 cache = detect_caches_aix (); 570#elif defined (__APPLE__) 571 cache = detect_caches_darwin (); 572#elif defined (__FreeBSD__) 573 cache = detect_caches_freebsd (); 574 /* FreeBSD PPC does not provide any cache information yet. */ 575 cache = ""; 576#elif defined (__linux__) 577 cache = detect_caches_linux (); 578 /* PPC Linux does not provide any cache information yet. */ 579 cache = ""; 580#else 581 cache = ""; 582#endif 583 } 584 585#if defined (_AIX) 586 cpu = detect_processor_aix (); 587#elif defined (__APPLE__) 588 cpu = detect_processor_darwin (); 589#elif defined (__FreeBSD__) 590 cpu = detect_processor_freebsd (); 591#elif defined (__linux__) 592 cpu = detect_processor_linux (); 593#else 594 cpu = "powerpc"; 595#endif 596 597 if (assembler) 598 { 599 for (i = 0; i < sizeof (asm_names) / sizeof (asm_names[0]); i++) 600 { 601 if (!asm_names[i].cpu || !strcmp (asm_names[i].cpu, cpu)) 602 return asm_names[i].asm_sw; 603 } 604 605 return NULL; 606 } 607 608 return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL); 609} 610 611#else /* GCC_VERSION */ 612 613/* If we aren't compiling with GCC we just provide a minimal 614 default value. */ 615const char * 616host_detect_local_cpu (int argc, const char **argv) 617{ 618 const char *cpu; 619 bool arch; 620 621 if (argc < 1) 622 return NULL; 623 624 arch = strcmp (argv[0], "cpu") == 0; 625 if (!arch && strcmp (argv[0], "tune")) 626 return NULL; 627 628 if (arch) 629 cpu = "powerpc"; 630 631 return concat ("-m", argv[0], "=", cpu, NULL); 632} 633 634#endif /* GCC_VERSION */ 635 636