1 /* Subroutines for the gcc driver.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GCC.
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 2, or (at your option)
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.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to
18 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA. */
25 const char *host_detect_local_cpu (int argc
, const char **argv
);
28 #define cpuid(num,a,b,c,d) \
29 asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
30 : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
33 #define bit_CMPXCHG8B (1 << 8)
34 #define bit_CMOV (1 << 15)
35 #define bit_MMX (1 << 23)
36 #define bit_SSE (1 << 25)
37 #define bit_SSE2 (1 << 26)
39 #define bit_SSE3 (1 << 0)
40 #define bit_CMPXCHG16B (1 << 13)
42 #define bit_3DNOW (1 << 31)
43 #define bit_3DNOWP (1 << 30)
44 #define bit_LM (1 << 29)
46 /* This will be called by the spec parser in gcc.c when it sees
47 a %:local_cpu_detect(args) construct. Currently it will be called
48 with either "arch" or "tune" as argument depending on if -march=native
49 or -mtune=native is to be substituted.
51 It returns a string containing new command line parameters to be
52 put at the place of the above two options, depending on what CPU
53 this is executed. E.g. "-march=k8" on an AMD64 machine
56 ARGC and ARGV are set depending on the actual arguments given
58 const char *host_detect_local_cpu (int argc
, const char **argv
)
60 const char *cpu
= "i386";
61 unsigned int eax
, ebx
, ecx
, edx
;
62 unsigned int max_level
;
64 unsigned int ext_level
;
65 unsigned char has_mmx
= 0, has_3dnow
= 0, has_3dnowp
= 0, has_sse
= 0;
66 unsigned char has_sse2
= 0, has_sse3
= 0, has_cmov
= 0;
67 unsigned char has_longmode
= 0;
68 unsigned char is_amd
= 0;
69 unsigned int family
= 0;
71 || (strcmp (argv
[0], "arch")
72 && strcmp (argv
[0], "tune")))
76 /* See if we can use cpuid. */
77 asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
78 "pushl %0; popfl; pushfl; popl %0; popfl"
79 : "=&r" (eax
), "=&r" (ebx
)
82 if (((eax
^ ebx
) & 0x00200000) == 0)
88 /* Check the highest input value for eax. */
89 cpuid (0, eax
, ebx
, ecx
, edx
);
91 /* We only look at the first four characters. */
96 cpuid (1, eax
, ebx
, ecx
, edx
);
97 has_cmov
= !!(edx
& bit_CMOV
);
98 has_mmx
= !!(edx
& bit_MMX
);
99 has_sse
= !!(edx
& bit_SSE
);
100 has_sse2
= !!(edx
& bit_SSE2
);
101 has_sse3
= !!(ecx
& bit_SSE3
);
102 /* We don't care for extended family. */
103 family
= (eax
>> 8) & ~(1 << 4);
105 cpuid (0x80000000, eax
, ebx
, ecx
, edx
);
107 if (ext_level
>= 0x80000000)
109 cpuid (0x80000001, eax
, ebx
, ecx
, edx
);
110 has_3dnow
= !!(edx
& bit_3DNOW
);
111 has_3dnowp
= !!(edx
& bit_3DNOWP
);
112 has_longmode
= !!(edx
& bit_LM
);
115 is_amd
= vendor
== *(unsigned int*)"Auth";
127 if (has_sse2
|| has_longmode
)
144 /* It's a pentiumpro with sse2 --> pentium-m */
147 /* Would have to look at extended family, but it's at least
161 return concat ("-m", argv
[0], "=", cpu
, NULL
);
164 /* If we aren't compiling with GCC we just provide a minimal
166 const char *host_detect_local_cpu (int argc
, const char **argv
)
168 return concat ("-m", argv
[0], "=i386", NULL
);
170 #endif /* GCC_VERSION */