diff options
author | David Schleef <ds@ginger.bigkitten.com> | 2008-03-13 00:23:21 -0700 |
---|---|---|
committer | David Schleef <ds@ginger.bigkitten.com> | 2008-03-13 00:23:21 -0700 |
commit | df0e54862b788e44e4bc21fab4c10032be664056 (patch) | |
tree | f4cbe90e4620e8f28763c7111b67de324ad67cf1 /liboil | |
parent | 3952640898d5b767e30ef6e96267384602824c05 (diff) |
Use /proc/self/auxv to test for altivec on Linux. Patch from #14914
Diffstat (limited to 'liboil')
-rw-r--r-- | liboil/liboilcpu-powerpc.c | 79 |
1 files changed, 68 insertions, 11 deletions
diff --git a/liboil/liboilcpu-powerpc.c b/liboil/liboilcpu-powerpc.c index a0f029f..6ae591b 100644 --- a/liboil/liboilcpu-powerpc.c +++ b/liboil/liboilcpu-powerpc.c @@ -34,15 +34,20 @@ #include <liboil/liboilfault.h> #include <liboil/liboilutils.h> -//#include <unistd.h> -//#include <fcntl.h> -//#include <stdlib.h> -//#include <string.h> -//#include <stdio.h> -//#include <setjmp.h> -//#include <signal.h> -//#include <sys/time.h> -//#include <time.h> +#if defined(__linux__) +#include <linux/auxvec.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> + +#ifndef PPC_FEATURE_HAS_ALTIVEC +/* From linux-2.6/include/asm-powerpc/cputable.h */ +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#endif + +#endif #if defined(__FreeBSD__) #include <sys/types.h> @@ -67,7 +72,7 @@ test_altivec (void * ignored) } #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -void +static void oil_check_altivec_sysctl_freebsd (void) { int ret, av; @@ -82,7 +87,7 @@ oil_check_altivec_sysctl_freebsd (void) #endif #if defined(__APPLE__) -void +static void oil_check_altivec_sysctl_darwin (void) { int ret, vu; @@ -96,6 +101,56 @@ oil_check_altivec_sysctl_darwin (void) } #endif +#if defined(__linux__) +static void +oil_check_altivec_proc_auxv (void) +{ + static int available = -1; + int new_avail = 0; + unsigned long buf[64]; + ssize_t count; + int fd, i; + + /* Flags already set */ + if (available != -1) { + return; + } + + fd = open("/proc/self/auxv", O_RDONLY); + if (fd < 0) { + goto out; + } + +more: + count = read(fd, buf, sizeof(buf)); + if (count < 0) { + goto out_close; + } + + for (i=0; i < (count / sizeof(unsigned long)); i += 2) { + if (buf[i] == AT_HWCAP) { + new_avail = !!(buf[i+1] & PPC_FEATURE_HAS_ALTIVEC); + goto out_close; + } else if (buf[i] == AT_NULL) { + goto out_close; + } + } + + if (count == sizeof(buf)) { + goto more; + } + +out_close: + close(fd); + +out: + available = new_avail; + if (available) { + oil_cpu_flags |= OIL_IMPL_FLAG_ALTIVEC; + } +} +#endif + void oil_check_altivec_fault (void) { @@ -114,6 +169,8 @@ oil_cpu_detect_arch(void) oil_check_altivec_sysctl_freebsd(); #elif defined(__APPLE__) oil_check_altivec_sysctl_darwin(); +#elif defined(__linux__) + oil_check_altivec_proc_auxv(); #else oil_check_altivec_fault(); #endif |