Update contrib.
2 * LIBOIL - Library of Optimized Inner Loops
3 * Copyright (c) 2003,2004 David A. Schleef <ds@schleef.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
31 #include <liboil/liboilfunction.h>
32 #include <liboil/liboildebug.h>
33 #include <liboil/liboilcpu.h>
34 #include <liboil/liboilfault.h>
35 #include <liboil/liboilutils.h>
46 #ifdef HAVE_SYS_TIME_H
51 #if defined(__FreeBSD__) || defined(__APPLE__)
52 #include <sys/types.h>
53 #include <sys/sysctl.h>
60 /***** i386, amd64 *****/
63 #define USE_I386_GETISAX
65 #define USE_I386_CPUID
69 #ifdef USE_I386_CPUINFO
71 oil_cpu_i386_getflags_cpuinfo (char *cpuinfo)
77 cpuinfo_flags = get_tag_value (cpuinfo, "flags");
78 if (cpuinfo_flags == NULL) {
83 flags = strsplit(cpuinfo_flags);
84 for (f = flags; *f; f++) {
85 if (strcmp (*f, "cmov") == 0) {
86 OIL_DEBUG ("cpu flag %s", *f);
87 oil_cpu_flags |= OIL_IMPL_FLAG_CMOV;
89 if (strcmp (*f, "mmx") == 0) {
90 OIL_DEBUG ("cpu flag %s", *f);
91 oil_cpu_flags |= OIL_IMPL_FLAG_MMX;
93 if (strcmp (*f, "sse") == 0) {
94 OIL_DEBUG ("cpu flag %s", *f);
95 oil_cpu_flags |= OIL_IMPL_FLAG_SSE;
97 if (strcmp (*f, "mmxext") == 0) {
98 OIL_DEBUG ("cpu flag %s", *f);
99 oil_cpu_flags |= OIL_IMPL_FLAG_MMXEXT;
101 if (strcmp (*f, "sse2") == 0) {
102 OIL_DEBUG ("cpu flag %s", *f);
103 oil_cpu_flags |= OIL_IMPL_FLAG_SSE2;
104 oil_cpu_flags |= OIL_IMPL_FLAG_MMXEXT;
106 if (strcmp (*f, "3dnow") == 0) {
107 OIL_DEBUG ("cpu flag %s", *f);
108 oil_cpu_flags |= OIL_IMPL_FLAG_3DNOW;
110 if (strcmp (*f, "3dnowext") == 0) {
111 OIL_DEBUG ("cpu flag %s", *f);
112 oil_cpu_flags |= OIL_IMPL_FLAG_3DNOWEXT;
114 if (strcmp (*f, "sse3") == 0) {
115 OIL_DEBUG ("cpu flag %s", *f);
116 oil_cpu_flags |= OIL_IMPL_FLAG_SSE3;
117 oil_cpu_flags |= OIL_IMPL_FLAG_SSE2;
118 oil_cpu_flags |= OIL_IMPL_FLAG_MMXEXT;
120 if (strcmp (*f, "ssse3") == 0) {
121 OIL_DEBUG ("cpu flag %s", *f);
122 oil_cpu_flags |= OIL_IMPL_FLAG_SSSE3;
123 oil_cpu_flags |= OIL_IMPL_FLAG_SSE3;
124 oil_cpu_flags |= OIL_IMPL_FLAG_SSE2;
125 oil_cpu_flags |= OIL_IMPL_FLAG_MMXEXT;
132 free (cpuinfo_flags);
138 oil_profile_stamp_rdtsc(void)
141 __asm__ __volatile__("rdtsc\n" : "=a" (ts) : : "edx");
146 #ifdef USE_I386_CPUID
149 get_cpuid (uint32_t op, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
155 " mov %%ebx, %%esi\n"
157 : "=a" (*a), "=S" (*b), "=c" (*c), "=d" (*d)
165 get_cpuid (uint32_t op, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
170 " mov %%ebx, %%esi\n"
172 : "=a" (*a), "=S" (*b), "=c" (*c), "=d" (*d)
178 test_cpuid (void *ignored)
180 uint32_t eax, ebx, ecx, edx;
182 get_cpuid (0x00000000, &eax, &ebx, &ecx, &edx);
186 oil_cpu_detect_cpuid (void)
188 uint32_t eax, ebx, ecx, edx;
190 char vendor[13] = { 0 };
193 oil_fault_check_enable ();
194 ret = oil_fault_check_try(test_cpuid, NULL);
195 oil_fault_check_disable ();
197 /* CPU thinks cpuid is an illegal instruction. */
201 get_cpuid (0x00000000, &level, (uint32_t *)(vendor+0),
202 (uint32_t *)(vendor+8), (uint32_t *)(vendor+4));
204 OIL_DEBUG("cpuid %d %s", level, vendor);
210 get_cpuid (0x00000001, &eax, &ebx, &ecx, &edx);
214 _oil_profile_stamp = oil_profile_stamp_rdtsc;
220 oil_cpu_flags |= OIL_IMPL_FLAG_CMOV;
223 oil_cpu_flags |= OIL_IMPL_FLAG_MMX;
226 oil_cpu_flags |= OIL_IMPL_FLAG_SSE;
229 oil_cpu_flags |= OIL_IMPL_FLAG_SSE2;
230 oil_cpu_flags |= OIL_IMPL_FLAG_MMXEXT;
233 oil_cpu_flags |= OIL_IMPL_FLAG_SSE3;
236 if (memcmp (vendor, "AuthenticAMD", 12) == 0) {
237 get_cpuid (0x80000001, &eax, &ebx, &ecx, &edx);
241 oil_cpu_flags |= OIL_IMPL_FLAG_MMXEXT;
244 oil_cpu_flags |= OIL_IMPL_FLAG_3DNOW;
247 oil_cpu_flags |= OIL_IMPL_FLAG_3DNOWEXT;
250 get_cpuid (0x80000005, &eax, &ebx, &ecx, &edx);
252 OIL_INFO("L1 D-cache: %d kbytes, %d-way, %d lines/tag, %d line size",
253 (ecx>>24)&0xff, (ecx>>16)&0xff, (ecx>>8)&0xff, ecx&0xff);
254 OIL_INFO("L1 I-cache: %d kbytes, %d-way, %d lines/tag, %d line size",
255 (edx>>24)&0xff, (edx>>16)&0xff, (edx>>8)&0xff, edx&0xff);
257 get_cpuid (0x80000006, &eax, &ebx, &ecx, &edx);
258 OIL_INFO("L2 cache: %d kbytes, %d assoc, %d lines/tag, %d line size",
259 (ecx>>16)&0xffff, (ecx>>12)&0xf, (ecx>>8)&0xf, ecx&0xff);
264 #ifdef USE_I386_GETISAX
266 oil_cpu_detect_getisax (void)
272 if (ui & AV_386_CMOV) {
273 oil_cpu_flags |= OIL_IMPL_FLAG_CMOV;
275 if (ui & AV_386_MMX) {
276 oil_cpu_flags |= OIL_IMPL_FLAG_MMX;
278 if (ui & AV_386_SSE) {
279 oil_cpu_flags |= OIL_IMPL_FLAG_SSE;
281 if (ui & AV_386_SSE2) {
282 oil_cpu_flags |= OIL_IMPL_FLAG_SSE2;
283 oil_cpu_flags |= OIL_IMPL_FLAG_MMXEXT;
285 if (ui & AV_386_SSE3) {
286 oil_cpu_flags |= OIL_IMPL_FLAG_SSE3;
288 if (ui & AV_386_AMD_3DNow) {
289 oil_cpu_flags |= OIL_IMPL_FLAG_3DNOW;
291 if (ui & AV_386_AMD_3DNowx) {
292 oil_cpu_flags |= OIL_IMPL_FLAG_3DNOWEXT;
294 if (ui & AV_386_AMD_MMX) {
295 oil_cpu_flags |= OIL_IMPL_FLAG_MMXEXT;
300 /* Reduce the set of CPU capabilities detected by whatever detection mechanism
301 * was chosen, according to kernel limitations. SSE requires kernel support for
305 oil_cpu_detect_kernel_support (void)
307 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
311 len = sizeof(enabled);
312 ret = sysctlbyname("hw.instruction_sse", &enabled, &len, NULL, 0);
313 if (ret || !enabled) {
314 oil_cpu_flags &= ~(OIL_IMPL_FLAG_SSE | OIL_IMPL_FLAG_SSE2 |
315 OIL_IMPL_FLAG_MMXEXT | OIL_IMPL_FLAG_SSE3);
317 #elif defined(__linux__)
319 * Might also want to grow a check for the old RedHat + Linux 2.2
320 * unmasked SSE FPU exception bug. Other than that, if /proc/cpuinfo
321 * reported SSE, then it's safe.
325 #elif defined(__NetBSD__)
329 OIL_WARNING("Operating system is not known to support SSE. "
330 "Assuming it does, which might cause problems");
332 oil_cpu_flags &= ~(OIL_IMPL_FLAG_SSE | OIL_IMPL_FLAG_SSE2 |
333 OIL_IMPL_FLAG_MMXEXT | OIL_IMPL_FLAG_SSE3);
339 oil_cpu_detect_arch(void)
341 #ifdef USE_I386_CPUID
342 oil_cpu_detect_cpuid ();
344 #ifdef USE_I386_GETISAX
345 oil_cpu_detect_getisax ();
347 #ifdef USE_I386_CPUINFO
348 oil_cpu_detect_cpuinfo ();
351 oil_cpu_detect_kernel_support ();