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