1 /* Subroutines for the gcc driver. 2 Copyright (C) 2015-2020 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 #define IN_TARGET_CODE 1 21 22 #include "config.h" 23 #include "system.h" 24 #include "coretypes.h" 25 #include "tm.h" 26 27 /* This will be called by the spec parser in gcc.c when it sees 28 a %:local_cpu_detect(args) construct. Currently it will be called 29 with either "arch" or "tune" as argument depending on if -march=native 30 or -mtune=native is to be substituted. 31 32 It returns a string containing new command line parameters to be 33 put at the place of the above two options, depending on what CPU 34 this is executed. E.g. "-march=zEC12" on a zEC12 for -march=native. 35 If the routine can't detect a known processor, the -march or -mtune 36 option is discarded. 37 38 ARGC and ARGV are set depending on the actual arguments given 39 in the spec. */ 40 const char * 41 s390_host_detect_local_cpu (int argc, const char **argv) 42 { 43 const char *cpu = NULL; 44 char buf[256]; 45 FILE *f; 46 bool arch; 47 const char *options = ""; 48 unsigned int has_features; 49 unsigned int has_processor; 50 unsigned int is_cpu_z9_109 = 0; 51 unsigned int has_highgprs = 0; 52 unsigned int has_dfp = 0; 53 unsigned int has_te = 0; 54 unsigned int has_vx = 0; 55 unsigned int has_opt_esa_zarch = 0; 56 int i; 57 58 if (argc < 1) 59 return NULL; 60 61 arch = strcmp (argv[0], "arch") == 0; 62 if (!arch && strcmp (argv[0], "tune")) 63 return NULL; 64 for (i = 1; i < argc; i++) 65 if (strcmp (argv[i], "mesa_mzarch") == 0) 66 has_opt_esa_zarch = 1; 67 68 f = fopen ("/proc/cpuinfo", "r"); 69 if (f == NULL) 70 return NULL; 71 72 for (has_features = 0, has_processor = 0; 73 (has_features == 0 || has_processor == 0) 74 && fgets (buf, sizeof (buf), f) != NULL; ) 75 { 76 if (has_processor == 0 && strncmp (buf, "processor", 9) == 0) 77 { 78 const char *p; 79 long machine_id; 80 81 p = strstr (buf, "machine = "); 82 if (p == NULL) 83 continue; 84 p += 10; 85 has_processor = 1; 86 machine_id = strtol (p, NULL, 16); 87 switch (machine_id) 88 { 89 case 0x2064: 90 case 0x2066: 91 cpu = "z900"; 92 break; 93 case 0x2084: 94 case 0x2086: 95 cpu = "z990"; 96 break; 97 case 0x2094: 98 case 0x2096: 99 cpu = "z9-109"; 100 is_cpu_z9_109 = 1; 101 break; 102 case 0x2097: 103 case 0x2098: 104 cpu = "z10"; 105 break; 106 case 0x2817: 107 case 0x2818: 108 cpu = "z196"; 109 break; 110 case 0x2827: 111 case 0x2828: 112 cpu = "zEC12"; 113 break; 114 case 0x2964: 115 case 0x2965: 116 cpu = "z13"; 117 break; 118 case 0x3906: 119 case 0x3907: 120 cpu = "z14"; 121 break; 122 case 0x8561: 123 case 0x8562: 124 cpu = "z15"; 125 break; 126 default: 127 cpu = "z15"; 128 break; 129 } 130 } 131 if (has_features == 0 && strncmp (buf, "features", 8) == 0) 132 { 133 const char *p; 134 135 p = strchr (buf, ':'); 136 if (p == NULL) 137 continue; 138 p++; 139 while (*p != 0) 140 { 141 int i; 142 143 while (ISSPACE (*p)) 144 p++; 145 for (i = 0; !ISSPACE (p[i]) && p[i] != 0; i++) 146 ; 147 if (i == 3 && strncmp (p, "dfp", 3) == 0) 148 has_dfp = 1; 149 else if (i == 2 && strncmp (p, "te", 2) == 0) 150 has_te = 1; 151 else if (i == 2 && strncmp (p, "vx", 2) == 0) 152 has_vx = 1; 153 else if (i == 8 && strncmp (p, "highgprs", 8) == 0) 154 has_highgprs = 1; 155 p += i; 156 } 157 has_features = 1; 158 } 159 } 160 161 fclose (f); 162 163 if (cpu == NULL) 164 return NULL; 165 166 if (arch) 167 { 168 const char *opt_htm = ""; 169 const char *opt_vx = ""; 170 const char *opt_esa_zarch = ""; 171 172 /* We may switch off these cpu features but never switch the on 173 explicitly. This overrides options specified on the command line. */ 174 if (!has_te) 175 opt_htm = " -mno-htm"; 176 if (!has_vx) 177 opt_vx = " -mno-vx"; 178 /* However, we set -mzarch only if neither -mzarch nor -mesa are used on 179 the command line. This allows the user to switch to -mesa manually. 180 */ 181 if (!has_opt_esa_zarch && has_highgprs) 182 opt_esa_zarch = " -mzarch"; 183 options = concat (options, opt_htm, opt_vx, opt_esa_zarch, NULL); 184 } 185 if (has_dfp && is_cpu_z9_109) 186 cpu = "z9-ec"; 187 188 return concat ("-m", argv[0], "=", cpu, options, NULL); 189 } 190