[PATCH] Check for NEON using a signal handler to catch SIGILL
Mike McCormack
mj.mccormack at samsung.com
Wed Dec 8 20:31:41 PST 2010
---
pixman/pixman-cpu.c | 87 ++++++++++++++++++++++++---------------------------
1 files changed, 41 insertions(+), 46 deletions(-)
diff --git a/pixman/pixman-cpu.c b/pixman/pixman-cpu.c
index e4fb1e4..8e0dd15 100644
--- a/pixman/pixman-cpu.c
+++ b/pixman/pixman-cpu.c
@@ -246,60 +246,55 @@ pixman_have_arm_neon (void)
#else /* linux ELF */
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <string.h>
-#include <elf.h>
+#include <signal.h>
+#include <setjmp.h>
-static pixman_bool_t arm_has_v7 = FALSE;
static pixman_bool_t arm_has_v6 = FALSE;
-static pixman_bool_t arm_has_vfp = FALSE;
static pixman_bool_t arm_has_neon = FALSE;
-static pixman_bool_t arm_has_iwmmxt = FALSE;
static pixman_bool_t arm_tests_initialized = FALSE;
+static sigjmp_buf cpu_jmpbuf;
+
static void
-pixman_arm_read_auxv ()
+pixman_catch_sigill(int sig)
{
- int fd;
- Elf32_auxv_t aux;
+ siglongjmp(cpu_jmpbuf, 1);
+}
+
+static void
+pixman_arm_check_neon (void)
+{
+ struct sigaction sa, old_sa;
- fd = open ("/proc/self/auxv", O_RDONLY);
- if (fd >= 0)
+ /* setup the sigaction */
+ sa.sa_handler = pixman_catch_sigill;
+ sa.sa_flags = SA_RESTART;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGILL, &sa, &old_sa);
+
+#if defined(USE_ARM_NEON)
+ if (!sigsetjmp(cpu_jmpbuf, 1))
{
- while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
- {
- if (aux.a_type == AT_HWCAP)
- {
- uint32_t hwcap = aux.a_un.a_val;
- /* hardcode these values to avoid depending on specific
- * versions of the hwcap header, e.g. HWCAP_NEON
- */
- arm_has_vfp = (hwcap & 64) != 0;
- arm_has_iwmmxt = (hwcap & 512) != 0;
- /* this flag is only present on kernel 2.6.29 */
- arm_has_neon = (hwcap & 4096) != 0;
- }
- else if (aux.a_type == AT_PLATFORM)
- {
- const char *plat = (const char*) aux.a_un.a_val;
- if (strncmp (plat, "v7l", 3) == 0)
- {
- arm_has_v7 = TRUE;
- arm_has_v6 = TRUE;
- }
- else if (strncmp (plat, "v6l", 3) == 0)
- {
- arm_has_v6 = TRUE;
- }
- }
- }
- close (fd);
+ asm volatile (
+ ".fpu neon\n"
+ "\tvqadd.u8 d0, d1, d0\n"
+ );
+ arm_has_neon = TRUE;
}
+#endif
+
+#if defined(USE_ARM_SIMD)
+ if (!sigsetjmp(cpu_jmpbuf, 1))
+ {
+ asm volatile (
+ ".arch armv6\n"
+ "\tuqadd8 r1, r1, r2\n"
+ : : :"r1", "r2");
+ arm_has_v6 = TRUE;
+ }
+#endif
+
+ sigaction(SIGILL, &old_sa, NULL);
arm_tests_initialized = TRUE;
}
@@ -309,7 +304,7 @@ pixman_bool_t
pixman_have_arm_simd (void)
{
if (!arm_tests_initialized)
- pixman_arm_read_auxv ();
+ pixman_arm_check_neon ();
return arm_has_v6;
}
@@ -321,7 +316,7 @@ pixman_bool_t
pixman_have_arm_neon (void)
{
if (!arm_tests_initialized)
- pixman_arm_read_auxv ();
+ pixman_arm_check_neon ();
return arm_has_neon;
}
--
1.7.0.4
--Boundary_(ID_sf2VkKyGRW0LeIkqox76Ag)--
More information about the Pixman
mailing list