123 lines
2.7 KiB
Diff
123 lines
2.7 KiB
Diff
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;
|
|
}
|