1 /* Subroutines for the gcc driver. 2 Copyright (C) 2011-2015 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 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) 9 any later version. 10 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. 15 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/>. */ 19 20 #include "config.h" 21 #include "system.h" 22 #include "coretypes.h" 23 #include "tm.h" 24 25 static const struct cpu_names { 26 const char *const name; 27 const char *const cpu; 28 } cpu_names[] = { 29 #if defined __sun__ && defined __svr4__ 30 { "TMS390S10", "supersparc" }, /* Texas Instruments microSPARC I */ 31 { "TMS390Z50", "supersparc" }, /* Texas Instruments SuperSPARC I */ 32 { "TMS390Z55", "supersparc" }, /* Texas Instruments 33 SuperSPARC I with SuperCache */ 34 { "MB86904", "supersparc" }, /* Fujitsu microSPARC II */ 35 { "MB86907", "supersparc" }, /* Fujitsu TurboSPARC */ 36 { "RT623", "hypersparc" }, /* Ross hyperSPARC */ 37 { "RT625", "hypersparc" }, 38 { "RT626", "hypersparc" }, 39 { "UltraSPARC-I", "ultrasparc" }, 40 { "UltraSPARC-II", "ultrasparc" }, 41 { "UltraSPARC-IIe", "ultrasparc" }, 42 { "UltraSPARC-IIi", "ultrasparc" }, 43 { "SPARC64-III", "ultrasparc" }, 44 { "SPARC64-IV", "ultrasparc" }, 45 { "UltraSPARC-III", "ultrasparc3" }, 46 { "UltraSPARC-III+", "ultrasparc3" }, 47 { "UltraSPARC-IIIi", "ultrasparc3" }, 48 { "UltraSPARC-IIIi+", "ultrasparc3" }, 49 { "UltraSPARC-IV", "ultrasparc3" }, 50 { "UltraSPARC-IV+", "ultrasparc3" }, 51 { "SPARC64-V", "ultrasparc3" }, 52 { "SPARC64-VI", "ultrasparc3" }, 53 { "SPARC64-VII", "ultrasparc3" }, 54 { "UltraSPARC-T1", "niagara" }, 55 { "UltraSPARC-T2", "niagara2" }, 56 { "UltraSPARC-T2", "niagara2" }, 57 { "UltraSPARC-T2+", "niagara2" }, 58 { "SPARC-T3", "niagara3" }, 59 { "SPARC-T4", "niagara4" }, 60 #else 61 { "SuperSparc", "supersparc" }, 62 { "HyperSparc", "hypersparc" }, 63 { "SpitFire", "ultrasparc" }, 64 { "BlackBird", "ultrasparc" }, 65 { "Sabre", "ultrasparc" }, 66 { "Hummingbird", "ultrasparc" }, 67 { "Cheetah", "ultrasparc3" }, 68 { "Jalapeno", "ultrasparc3" }, 69 { "Jaguar", "ultrasparc3" }, 70 { "Panther", "ultrasparc3" }, 71 { "Serrano", "ultrasparc3" }, 72 { "UltraSparc T1", "niagara" }, 73 { "UltraSparc T2", "niagara2" }, 74 { "UltraSparc T3", "niagara3" }, 75 { "UltraSparc T4", "niagara4" }, 76 { "LEON", "leon3" }, 77 #endif 78 { NULL, NULL } 79 }; 80 81 #if defined __sun__ && defined __svr4__ 82 #include <kstat.h> 83 #endif 84 85 /* This will be called by the spec parser in gcc.c when it sees 86 a %:local_cpu_detect(args) construct. Currently it will be called 87 with either "cpu" or "tune" as argument depending on if -mcpu=native 88 or -mtune=native is to be substituted. 89 90 It returns a string containing new command line parameters to be 91 put at the place of the above two options, depending on what CPU 92 this is executed. E.g. "-mcpu=ultrasparc3" on an UltraSPARC III for 93 -mcpu=native. If the routine can't detect a known processor, 94 the -mcpu or -mtune option is discarded. 95 96 ARGC and ARGV are set depending on the actual arguments given 97 in the spec. */ 98 const char * 99 host_detect_local_cpu (int argc, const char **argv) 100 { 101 const char *cpu = NULL; 102 #if defined __sun__ && defined __svr4__ 103 char *buf = NULL; 104 kstat_ctl_t *kc; 105 kstat_t *ksp; 106 kstat_named_t *brand = NULL; 107 #else 108 char buf[128]; 109 FILE *f; 110 #endif 111 int i; 112 113 if (argc < 1) 114 return NULL; 115 116 if (strcmp (argv[0], "cpu") && strcmp (argv[0], "tune")) 117 return NULL; 118 119 #if defined __sun__ && defined __svr4__ 120 kc = kstat_open (); 121 if (kc != NULL) 122 { 123 ksp = kstat_lookup (kc, CONST_CAST2 (char *, const char *, "cpu_info"), 124 -1, NULL); 125 if (ksp != NULL 126 && kstat_read (kc, ksp, NULL) != -1 127 && ksp->ks_type == KSTAT_TYPE_NAMED) 128 brand = (kstat_named_t *) 129 kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *, "brand")); 130 /* "brand" was only introduced in Solaris 10. */ 131 if (brand == NULL) 132 brand = (kstat_named_t *) 133 kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *, 134 "implementation")); 135 /* KSTAT_DATA_STRING was introduced in Solaris 9. */ 136 #ifdef KSTAT_DATA_STRING 137 if (brand != NULL && brand->data_type == KSTAT_DATA_STRING) 138 buf = KSTAT_NAMED_STR_PTR (brand); 139 #else 140 if (brand != NULL && brand->data_type == KSTAT_DATA_CHAR) 141 buf = brand->value.c; 142 #endif 143 } 144 kstat_close (kc); 145 146 for (i = 0; cpu_names[i].name != NULL; i++) 147 if (strcmp (buf, cpu_names[i].name) == 0) 148 cpu = cpu_names[i].cpu; 149 #else 150 f = fopen ("/proc/cpuinfo", "r"); 151 if (f == NULL) 152 return NULL; 153 154 while (fgets (buf, sizeof (buf), f) != NULL) 155 if (strncmp (buf, "cpu\t\t:", sizeof ("cpu\t\t:") - 1) == 0) 156 { 157 for (i = 0; cpu_names [i].name; i++) 158 if (strstr (buf, cpu_names [i].name) != NULL) 159 { 160 cpu = cpu_names [i].cpu; 161 break; 162 } 163 break; 164 } 165 166 fclose (f); 167 #endif 168 169 if (cpu == NULL) 170 return NULL; 171 172 return concat ("-m", argv[0], "=", cpu, NULL); 173 } 174