1/* Subroutines for the gcc driver. 2 Copyright (C) 2006, 2007 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 2, 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 COPYING. If not, write to 18the Free Software Foundation, 51 Franklin Street, Fifth Floor, 19Boston, MA 02110-1301, USA. */ 20 21#include "config.h" 22#include "system.h" 23#include "coretypes.h" 24#include "tm.h" 25#include <stdlib.h> 26 27const char *host_detect_local_cpu (int argc, const char **argv); 28 29#ifdef GCC_VERSION 30#define cpuid(num,a,b,c,d) \ 31 asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ 32 : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ 33 : "0" (num)) 34 35#define bit_CMPXCHG8B (1 << 8) 36#define bit_CMOV (1 << 15) 37#define bit_MMX (1 << 23) 38#define bit_SSE (1 << 25) 39#define bit_SSE2 (1 << 26) 40 41#define bit_SSE3 (1 << 0) 42#define bit_SSSE3 (1 << 9) 43#define bit_SSE4a (1 << 6) 44#define bit_CMPXCHG16B (1 << 13) 45 46#define bit_3DNOW (1 << 31) 47#define bit_3DNOWP (1 << 30) 48#define bit_LM (1 << 29) 49 50/* This will be called by the spec parser in gcc.c when it sees 51 a %:local_cpu_detect(args) construct. Currently it will be called 52 with either "arch" or "tune" as argument depending on if -march=native 53 or -mtune=native is to be substituted. 54 55 It returns a string containing new command line parameters to be 56 put at the place of the above two options, depending on what CPU 57 this is executed. E.g. "-march=k8" on an AMD64 machine 58 for -march=native. 59 60 ARGC and ARGV are set depending on the actual arguments given 61 in the spec. */ 62const char *host_detect_local_cpu (int argc, const char **argv) 63{ 64 const char *cpu = NULL; 65 enum processor_type processor = PROCESSOR_I386; 66 unsigned int eax, ebx, ecx, edx; 67 unsigned int max_level; 68 unsigned int vendor; 69 unsigned int ext_level; 70 unsigned char has_mmx = 0, has_3dnow = 0, has_3dnowp = 0, has_sse = 0; 71 unsigned char has_sse2 = 0, has_sse3 = 0, has_ssse3 = 0, has_cmov = 0; 72 unsigned char has_longmode = 0, has_cmpxchg8b = 0, has_sse4a = 0; 73 unsigned char is_amd = 0; 74 unsigned int family = 0; 75 bool arch; 76 77 if (argc < 1) 78 return NULL; 79 80 arch = strcmp (argv[0], "arch") == 0; 81 if (!arch && strcmp (argv[0], "tune")) 82 return NULL; 83 84#ifndef __x86_64__ 85 /* See if we can use cpuid. */ 86 asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" 87 "pushl %0; popfl; pushfl; popl %0; popfl" 88 : "=&r" (eax), "=&r" (ebx) 89 : "i" (0x00200000)); 90 91 if (((eax ^ ebx) & 0x00200000) == 0) 92 goto done; 93#endif 94 95 processor = PROCESSOR_PENTIUM; 96 97 /* Check the highest input value for eax. */ 98 cpuid (0, eax, ebx, ecx, edx); 99 max_level = eax; 100 /* We only look at the first four characters. */ 101 vendor = ebx; 102 if (max_level == 0) 103 goto done; 104 105 cpuid (1, eax, ebx, ecx, edx); 106 has_cmpxchg8b = !!(edx & bit_CMPXCHG8B); 107 has_cmov = !!(edx & bit_CMOV); 108 has_mmx = !!(edx & bit_MMX); 109 has_sse = !!(edx & bit_SSE); 110 has_sse2 = !!(edx & bit_SSE2); 111 has_sse3 = !!(ecx & bit_SSE3); 112 has_ssse3 = !!(ecx & bit_SSSE3); 113 /* We don't care for extended family. */ 114 family = (eax >> 8) & ~(1 << 4); 115 116 cpuid (0x80000000, eax, ebx, ecx, edx); 117 ext_level = eax; 118 if (ext_level >= 0x80000000) 119 { 120 cpuid (0x80000001, eax, ebx, ecx, edx); 121 has_3dnow = !!(edx & bit_3DNOW); 122 has_3dnowp = !!(edx & bit_3DNOWP); 123 has_longmode = !!(edx & bit_LM); 124 has_sse4a = !!(ecx & bit_SSE4a); 125 } 126 127 is_amd = vendor == *(unsigned int*)"Auth"; 128 129 if (is_amd) 130 { 131 if (has_mmx) 132 processor = PROCESSOR_K6; 133 if (has_3dnowp) 134 processor = PROCESSOR_ATHLON; 135 if (has_sse2 || has_longmode) 136 processor = PROCESSOR_K8; 137 if (has_sse4a) 138 processor = PROCESSOR_AMDFAM10; 139 } 140 else 141 { 142 switch (family) 143 { 144 case 5: 145 /* Default is PROCESSOR_PENTIUM. */ 146 break; 147 case 6: 148 processor = PROCESSOR_PENTIUMPRO; 149 break; 150 case 15: 151 processor = PROCESSOR_PENTIUM4; 152 break; 153 default: 154 /* We have no idea. Use something reasonable. */ 155 if (arch) 156 { 157 if (has_ssse3) 158 cpu = "core2"; 159 else if (has_sse3) 160 { 161 if (has_longmode) 162 cpu = "nocona"; 163 else 164 cpu = "prescott"; 165 } 166 else if (has_sse2) 167 cpu = "pentium4"; 168 else if (has_cmov) 169 cpu = "pentiumpro"; 170 else if (has_mmx) 171 cpu = "pentium-mmx"; 172 else if (has_cmpxchg8b) 173 cpu = "pentium"; 174 else 175 cpu = "i386"; 176 } 177 else 178 cpu = "generic"; 179 goto done; 180 break; 181 } 182 } 183 184 switch (processor) 185 { 186 case PROCESSOR_I386: 187 cpu = "i386"; 188 break; 189 case PROCESSOR_I486: 190 cpu = "i486"; 191 break; 192 case PROCESSOR_PENTIUM: 193 if (has_mmx) 194 cpu = "pentium-mmx"; 195 else 196 cpu = "pentium"; 197 break; 198 case PROCESSOR_PENTIUMPRO: 199 if (arch) 200 { 201 if (has_sse3) 202 { 203 if (has_longmode) 204 { 205 /* It is Core 2 Duo. */ 206 cpu = "nocona"; 207 } 208 else 209 { 210 /* It is Core Duo. */ 211 cpu = "prescott"; 212 } 213 } 214 else if (has_sse2) 215 { 216 /* It is Pentium M. */ 217 cpu = "pentium4"; 218 } 219 else if (has_sse) 220 { 221 /* It is Pentium III. */ 222 cpu = "pentium3"; 223 } 224 else if (has_mmx) 225 { 226 /* It is Pentium II. */ 227 cpu = "pentium2"; 228 } 229 else 230 { 231 /* Default to Pentium Pro. */ 232 cpu = "pentiumpro"; 233 } 234 } 235 else 236 { 237 /* For -mtune, we default to -mtune=generic. */ 238 cpu = "generic"; 239 } 240 break; 241 case PROCESSOR_GEODE: 242 cpu = "geode"; 243 break; 244 case PROCESSOR_K6: 245 if (has_3dnow) 246 cpu = "k6-3"; 247 else 248 cpu = "k6"; 249 break; 250 case PROCESSOR_ATHLON: 251 if (has_sse) 252 cpu = "athlon-4"; 253 else 254 cpu = "athlon"; 255 break; 256 case PROCESSOR_PENTIUM4: 257 if (has_sse3) 258 { 259 if (has_longmode) 260 cpu = "nocona"; 261 else 262 cpu = "prescott"; 263 } 264 else 265 cpu = "pentium4"; 266 break; 267 case PROCESSOR_K8: 268 cpu = "k8"; 269 break; 270 case PROCESSOR_NOCONA: 271 cpu = "nocona"; 272 break; 273 case PROCESSOR_AMDFAM10: 274 cpu = "amdfam10"; 275 break; 276 case PROCESSOR_GENERIC32: 277 case PROCESSOR_GENERIC64: 278 cpu = "generic"; 279 break; 280 default: 281 abort (); 282 break; 283 } 284 285done: 286 return concat ("-m", argv[0], "=", cpu, NULL); 287} 288#else 289/* If we aren't compiling with GCC we just provide a minimal 290 default value. */ 291const char *host_detect_local_cpu (int argc, const char **argv) 292{ 293 const char *cpu; 294 bool arch; 295 296 if (argc < 1) 297 return NULL; 298 299 arch = strcmp (argv[0], "arch") == 0; 300 if (!arch && strcmp (argv[0], "tune")) 301 return NULL; 302 303 if (arch) 304 { 305 /* FIXME: i386 is wrong for 64bit compiler. How can we tell if 306 we are generating 64bit or 32bit code? */ 307 cpu = "i386"; 308 } 309 else 310 cpu = "generic"; 311 312 return concat ("-m", argv[0], "=", cpu, NULL); 313} 314#endif /* GCC_VERSION */ 315