1169689Skan/* Subroutines for the gcc driver. 2251212Spfg Copyright (C) 2006, 2007 Free Software Foundation, Inc. 3169689Skan 4169689SkanThis file is part of GCC. 5169689Skan 6169689SkanGCC is free software; you can redistribute it and/or modify 7169689Skanit under the terms of the GNU General Public License as published by 8169689Skanthe Free Software Foundation; either version 2, or (at your option) 9169689Skanany later version. 10169689Skan 11169689SkanGCC is distributed in the hope that it will be useful, 12169689Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 13169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14169689SkanGNU General Public License for more details. 15169689Skan 16169689SkanYou should have received a copy of the GNU General Public License 17169689Skanalong with GCC; see the file COPYING. If not, write to 18169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 19169689SkanBoston, MA 02110-1301, USA. */ 20169689Skan 21169689Skan#include "config.h" 22169689Skan#include "system.h" 23169689Skan#include "coretypes.h" 24169689Skan#include "tm.h" 25169689Skan#include <stdlib.h> 26169689Skan 27169689Skanconst char *host_detect_local_cpu (int argc, const char **argv); 28169689Skan 29169689Skan#ifdef GCC_VERSION 30169689Skan#define cpuid(num,a,b,c,d) \ 31169689Skan asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ 32169689Skan : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ 33169689Skan : "0" (num)) 34169689Skan 35169689Skan#define bit_CMPXCHG8B (1 << 8) 36169689Skan#define bit_CMOV (1 << 15) 37169689Skan#define bit_MMX (1 << 23) 38169689Skan#define bit_SSE (1 << 25) 39169689Skan#define bit_SSE2 (1 << 26) 40169689Skan 41169689Skan#define bit_SSE3 (1 << 0) 42219697Smm#define bit_SSSE3 (1 << 9) 43251212Spfg#define bit_SSE4a (1 << 6) 44169689Skan#define bit_CMPXCHG16B (1 << 13) 45169689Skan 46169689Skan#define bit_3DNOW (1 << 31) 47169689Skan#define bit_3DNOWP (1 << 30) 48169689Skan#define bit_LM (1 << 29) 49169689Skan 50169689Skan/* This will be called by the spec parser in gcc.c when it sees 51169689Skan a %:local_cpu_detect(args) construct. Currently it will be called 52169689Skan with either "arch" or "tune" as argument depending on if -march=native 53169689Skan or -mtune=native is to be substituted. 54169689Skan 55169689Skan It returns a string containing new command line parameters to be 56169689Skan put at the place of the above two options, depending on what CPU 57169689Skan this is executed. E.g. "-march=k8" on an AMD64 machine 58169689Skan for -march=native. 59169689Skan 60169689Skan ARGC and ARGV are set depending on the actual arguments given 61169689Skan in the spec. */ 62169689Skanconst char *host_detect_local_cpu (int argc, const char **argv) 63169689Skan{ 64169689Skan const char *cpu = NULL; 65169689Skan enum processor_type processor = PROCESSOR_I386; 66169689Skan unsigned int eax, ebx, ecx, edx; 67169689Skan unsigned int max_level; 68169689Skan unsigned int vendor; 69169689Skan unsigned int ext_level; 70169689Skan unsigned char has_mmx = 0, has_3dnow = 0, has_3dnowp = 0, has_sse = 0; 71219697Smm unsigned char has_sse2 = 0, has_sse3 = 0, has_ssse3 = 0, has_cmov = 0; 72251212Spfg unsigned char has_longmode = 0, has_cmpxchg8b = 0, has_sse4a = 0; 73169689Skan unsigned char is_amd = 0; 74169689Skan unsigned int family = 0; 75169689Skan bool arch; 76169689Skan 77169689Skan if (argc < 1) 78169689Skan return NULL; 79169689Skan 80169689Skan arch = strcmp (argv[0], "arch") == 0; 81169689Skan if (!arch && strcmp (argv[0], "tune")) 82169689Skan return NULL; 83169689Skan 84169689Skan#ifndef __x86_64__ 85169689Skan /* See if we can use cpuid. */ 86169689Skan asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" 87169689Skan "pushl %0; popfl; pushfl; popl %0; popfl" 88169689Skan : "=&r" (eax), "=&r" (ebx) 89169689Skan : "i" (0x00200000)); 90169689Skan 91169689Skan if (((eax ^ ebx) & 0x00200000) == 0) 92169689Skan goto done; 93169689Skan#endif 94169689Skan 95169689Skan processor = PROCESSOR_PENTIUM; 96169689Skan 97169689Skan /* Check the highest input value for eax. */ 98169689Skan cpuid (0, eax, ebx, ecx, edx); 99169689Skan max_level = eax; 100169689Skan /* We only look at the first four characters. */ 101169689Skan vendor = ebx; 102169689Skan if (max_level == 0) 103169689Skan goto done; 104169689Skan 105169689Skan cpuid (1, eax, ebx, ecx, edx); 106169689Skan has_cmpxchg8b = !!(edx & bit_CMPXCHG8B); 107169689Skan has_cmov = !!(edx & bit_CMOV); 108169689Skan has_mmx = !!(edx & bit_MMX); 109169689Skan has_sse = !!(edx & bit_SSE); 110169689Skan has_sse2 = !!(edx & bit_SSE2); 111169689Skan has_sse3 = !!(ecx & bit_SSE3); 112219697Smm has_ssse3 = !!(ecx & bit_SSSE3); 113169689Skan /* We don't care for extended family. */ 114169689Skan family = (eax >> 8) & ~(1 << 4); 115169689Skan 116169689Skan cpuid (0x80000000, eax, ebx, ecx, edx); 117169689Skan ext_level = eax; 118169689Skan if (ext_level >= 0x80000000) 119169689Skan { 120169689Skan cpuid (0x80000001, eax, ebx, ecx, edx); 121169689Skan has_3dnow = !!(edx & bit_3DNOW); 122169689Skan has_3dnowp = !!(edx & bit_3DNOWP); 123169689Skan has_longmode = !!(edx & bit_LM); 124251212Spfg has_sse4a = !!(ecx & bit_SSE4a); 125169689Skan } 126169689Skan 127169689Skan is_amd = vendor == *(unsigned int*)"Auth"; 128169689Skan 129169689Skan if (is_amd) 130169689Skan { 131169689Skan if (has_mmx) 132169689Skan processor = PROCESSOR_K6; 133169689Skan if (has_3dnowp) 134169689Skan processor = PROCESSOR_ATHLON; 135169689Skan if (has_sse2 || has_longmode) 136169689Skan processor = PROCESSOR_K8; 137251212Spfg if (has_sse4a) 138251212Spfg processor = PROCESSOR_AMDFAM10; 139169689Skan } 140169689Skan else 141169689Skan { 142169689Skan switch (family) 143169689Skan { 144169689Skan case 5: 145169689Skan /* Default is PROCESSOR_PENTIUM. */ 146169689Skan break; 147169689Skan case 6: 148169689Skan processor = PROCESSOR_PENTIUMPRO; 149169689Skan break; 150169689Skan case 15: 151169689Skan processor = PROCESSOR_PENTIUM4; 152169689Skan break; 153169689Skan default: 154169689Skan /* We have no idea. Use something reasonable. */ 155169689Skan if (arch) 156169689Skan { 157219697Smm if (has_ssse3) 158219697Smm cpu = "core2"; 159219697Smm else if (has_sse3) 160169689Skan { 161169689Skan if (has_longmode) 162169689Skan cpu = "nocona"; 163169689Skan else 164169689Skan cpu = "prescott"; 165169689Skan } 166169689Skan else if (has_sse2) 167169689Skan cpu = "pentium4"; 168169689Skan else if (has_cmov) 169169689Skan cpu = "pentiumpro"; 170169689Skan else if (has_mmx) 171169689Skan cpu = "pentium-mmx"; 172169689Skan else if (has_cmpxchg8b) 173169689Skan cpu = "pentium"; 174169689Skan else 175169689Skan cpu = "i386"; 176169689Skan } 177169689Skan else 178169689Skan cpu = "generic"; 179169689Skan goto done; 180169689Skan break; 181169689Skan } 182169689Skan } 183169689Skan 184169689Skan switch (processor) 185169689Skan { 186169689Skan case PROCESSOR_I386: 187169689Skan cpu = "i386"; 188169689Skan break; 189169689Skan case PROCESSOR_I486: 190169689Skan cpu = "i486"; 191169689Skan break; 192169689Skan case PROCESSOR_PENTIUM: 193169689Skan if (has_mmx) 194169689Skan cpu = "pentium-mmx"; 195169689Skan else 196169689Skan cpu = "pentium"; 197169689Skan break; 198169689Skan case PROCESSOR_PENTIUMPRO: 199169689Skan if (arch) 200169689Skan { 201169689Skan if (has_sse3) 202169689Skan { 203169689Skan if (has_longmode) 204169689Skan { 205169689Skan /* It is Core 2 Duo. */ 206169689Skan cpu = "nocona"; 207169689Skan } 208169689Skan else 209169689Skan { 210169689Skan /* It is Core Duo. */ 211169689Skan cpu = "prescott"; 212169689Skan } 213169689Skan } 214169689Skan else if (has_sse2) 215169689Skan { 216169689Skan /* It is Pentium M. */ 217169689Skan cpu = "pentium4"; 218169689Skan } 219169689Skan else if (has_sse) 220169689Skan { 221169689Skan /* It is Pentium III. */ 222169689Skan cpu = "pentium3"; 223169689Skan } 224169689Skan else if (has_mmx) 225169689Skan { 226169689Skan /* It is Pentium II. */ 227169689Skan cpu = "pentium2"; 228169689Skan } 229169689Skan else 230169689Skan { 231169689Skan /* Default to Pentium Pro. */ 232169689Skan cpu = "pentiumpro"; 233169689Skan } 234169689Skan } 235169689Skan else 236169689Skan { 237169689Skan /* For -mtune, we default to -mtune=generic. */ 238169689Skan cpu = "generic"; 239169689Skan } 240169689Skan break; 241219697Smm case PROCESSOR_GEODE: 242219697Smm cpu = "geode"; 243219697Smm break; 244169689Skan case PROCESSOR_K6: 245169689Skan if (has_3dnow) 246169689Skan cpu = "k6-3"; 247169689Skan else 248169689Skan cpu = "k6"; 249169689Skan break; 250169689Skan case PROCESSOR_ATHLON: 251169689Skan if (has_sse) 252169689Skan cpu = "athlon-4"; 253169689Skan else 254169689Skan cpu = "athlon"; 255169689Skan break; 256169689Skan case PROCESSOR_PENTIUM4: 257169689Skan if (has_sse3) 258169689Skan { 259169689Skan if (has_longmode) 260169689Skan cpu = "nocona"; 261169689Skan else 262169689Skan cpu = "prescott"; 263169689Skan } 264169689Skan else 265169689Skan cpu = "pentium4"; 266169689Skan break; 267169689Skan case PROCESSOR_K8: 268169689Skan cpu = "k8"; 269169689Skan break; 270169689Skan case PROCESSOR_NOCONA: 271169689Skan cpu = "nocona"; 272169689Skan break; 273251212Spfg case PROCESSOR_AMDFAM10: 274251212Spfg cpu = "amdfam10"; 275251212Spfg break; 276169689Skan case PROCESSOR_GENERIC32: 277169689Skan case PROCESSOR_GENERIC64: 278169689Skan cpu = "generic"; 279169689Skan break; 280169689Skan default: 281169689Skan abort (); 282169689Skan break; 283169689Skan } 284169689Skan 285169689Skandone: 286169689Skan return concat ("-m", argv[0], "=", cpu, NULL); 287169689Skan} 288169689Skan#else 289169689Skan/* If we aren't compiling with GCC we just provide a minimal 290169689Skan default value. */ 291169689Skanconst char *host_detect_local_cpu (int argc, const char **argv) 292169689Skan{ 293169689Skan const char *cpu; 294169689Skan bool arch; 295169689Skan 296169689Skan if (argc < 1) 297169689Skan return NULL; 298169689Skan 299169689Skan arch = strcmp (argv[0], "arch") == 0; 300169689Skan if (!arch && strcmp (argv[0], "tune")) 301169689Skan return NULL; 302169689Skan 303169689Skan if (arch) 304169689Skan { 305169689Skan /* FIXME: i386 is wrong for 64bit compiler. How can we tell if 306169689Skan we are generating 64bit or 32bit code? */ 307169689Skan cpu = "i386"; 308169689Skan } 309169689Skan else 310169689Skan cpu = "generic"; 311169689Skan 312169689Skan return concat ("-m", argv[0], "=", cpu, NULL); 313169689Skan} 314169689Skan#endif /* GCC_VERSION */ 315