1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/libpixman/src/pixman-arm.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,229 @@ 1.4 +/* 1.5 + * Copyright © 2000 SuSE, Inc. 1.6 + * Copyright © 2007 Red Hat, Inc. 1.7 + * 1.8 + * Permission to use, copy, modify, distribute, and sell this software and its 1.9 + * documentation for any purpose is hereby granted without fee, provided that 1.10 + * the above copyright notice appear in all copies and that both that 1.11 + * copyright notice and this permission notice appear in supporting 1.12 + * documentation, and that the name of SuSE not be used in advertising or 1.13 + * publicity pertaining to distribution of the software without specific, 1.14 + * written prior permission. SuSE makes no representations about the 1.15 + * suitability of this software for any purpose. It is provided "as is" 1.16 + * without express or implied warranty. 1.17 + * 1.18 + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 1.19 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 1.20 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.21 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 1.22 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 1.23 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1.24 + */ 1.25 +#ifdef HAVE_CONFIG_H 1.26 +#include <config.h> 1.27 +#endif 1.28 + 1.29 +#include "pixman-private.h" 1.30 + 1.31 +typedef enum 1.32 +{ 1.33 + ARM_V7 = (1 << 0), 1.34 + ARM_V6 = (1 << 1), 1.35 + ARM_VFP = (1 << 2), 1.36 + ARM_NEON = (1 << 3), 1.37 + ARM_IWMMXT = (1 << 4) 1.38 +} arm_cpu_features_t; 1.39 + 1.40 +#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT) 1.41 + 1.42 +#if defined(_MSC_VER) 1.43 + 1.44 +/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */ 1.45 +#include <windows.h> 1.46 + 1.47 +extern int pixman_msvc_try_arm_neon_op (); 1.48 +extern int pixman_msvc_try_arm_simd_op (); 1.49 + 1.50 +static arm_cpu_features_t 1.51 +detect_cpu_features (void) 1.52 +{ 1.53 + arm_cpu_features_t features = 0; 1.54 + 1.55 + __try 1.56 + { 1.57 + pixman_msvc_try_arm_simd_op (); 1.58 + features |= ARM_V6; 1.59 + } 1.60 + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) 1.61 + { 1.62 + } 1.63 + 1.64 + __try 1.65 + { 1.66 + pixman_msvc_try_arm_neon_op (); 1.67 + features |= ARM_NEON; 1.68 + } 1.69 + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) 1.70 + { 1.71 + } 1.72 + 1.73 + return features; 1.74 +} 1.75 + 1.76 +#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) /* iOS */ 1.77 + 1.78 +#include "TargetConditionals.h" 1.79 + 1.80 +static arm_cpu_features_t 1.81 +detect_cpu_features (void) 1.82 +{ 1.83 + arm_cpu_features_t features = 0; 1.84 + 1.85 + features |= ARM_V6; 1.86 + 1.87 + /* Detection of ARM NEON on iOS is fairly simple because iOS binaries 1.88 + * contain separate executable images for each processor architecture. 1.89 + * So all we have to do is detect the armv7 architecture build. The 1.90 + * operating system automatically runs the armv7 binary for armv7 devices 1.91 + * and the armv6 binary for armv6 devices. 1.92 + */ 1.93 +#if defined(__ARM_NEON__) 1.94 + features |= ARM_NEON; 1.95 +#endif 1.96 + 1.97 + return features; 1.98 +} 1.99 + 1.100 +#elif defined(__ANDROID__) || defined(ANDROID) /* Android */ 1.101 + 1.102 +static arm_cpu_features_t 1.103 +detect_cpu_features (void) 1.104 +{ 1.105 + arm_cpu_features_t features = 0; 1.106 + char buf[1024]; 1.107 + char* pos; 1.108 + const char* ver_token = "CPU architecture: "; 1.109 + FILE* f = fopen("/proc/cpuinfo", "r"); 1.110 + if (!f) { 1.111 + return features; 1.112 + } 1.113 + 1.114 + fread(buf, sizeof(char), sizeof(buf), f); 1.115 + fclose(f); 1.116 + pos = strstr(buf, ver_token); 1.117 + if (pos) { 1.118 + char vchar = *(pos + strlen(ver_token)); 1.119 + if (vchar >= '0' && vchar <= '9') { 1.120 + int ver = vchar - '0'; 1.121 + if (ver >= 7) 1.122 + features |= ARM_V7; 1.123 + } 1.124 + } 1.125 + if (strstr(buf, "neon") != NULL) 1.126 + features |= ARM_NEON; 1.127 + if (strstr(buf, "vfp") != NULL) 1.128 + features |= ARM_VFP; 1.129 + 1.130 + return features; 1.131 +} 1.132 + 1.133 +#elif defined (__linux__) /* linux ELF */ 1.134 + 1.135 +#include <unistd.h> 1.136 +#include <sys/types.h> 1.137 +#include <sys/stat.h> 1.138 +#include <sys/mman.h> 1.139 +#include <fcntl.h> 1.140 +#include <string.h> 1.141 +#include <elf.h> 1.142 + 1.143 +static arm_cpu_features_t 1.144 +detect_cpu_features (void) 1.145 +{ 1.146 + arm_cpu_features_t features = 0; 1.147 + Elf32_auxv_t aux; 1.148 + int fd; 1.149 + 1.150 + fd = open ("/proc/self/auxv", O_RDONLY); 1.151 + if (fd >= 0) 1.152 + { 1.153 + while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) 1.154 + { 1.155 + if (aux.a_type == AT_HWCAP) 1.156 + { 1.157 + uint32_t hwcap = aux.a_un.a_val; 1.158 + 1.159 + /* hardcode these values to avoid depending on specific 1.160 + * versions of the hwcap header, e.g. HWCAP_NEON 1.161 + */ 1.162 + if ((hwcap & 64) != 0) 1.163 + features |= ARM_VFP; 1.164 + if ((hwcap & 512) != 0) 1.165 + features |= ARM_IWMMXT; 1.166 + /* this flag is only present on kernel 2.6.29 */ 1.167 + if ((hwcap & 4096) != 0) 1.168 + features |= ARM_NEON; 1.169 + } 1.170 + else if (aux.a_type == AT_PLATFORM) 1.171 + { 1.172 + const char *plat = (const char*) aux.a_un.a_val; 1.173 + 1.174 + if (strncmp (plat, "v7l", 3) == 0) 1.175 + features |= (ARM_V7 | ARM_V6); 1.176 + else if (strncmp (plat, "v6l", 3) == 0) 1.177 + features |= ARM_V6; 1.178 + } 1.179 + } 1.180 + close (fd); 1.181 + } 1.182 + 1.183 + return features; 1.184 +} 1.185 + 1.186 +#else /* Unknown */ 1.187 + 1.188 +static arm_cpu_features_t 1.189 +detect_cpu_features (void) 1.190 +{ 1.191 + return 0; 1.192 +} 1.193 + 1.194 +#endif /* Linux elf */ 1.195 + 1.196 +static pixman_bool_t 1.197 +have_feature (arm_cpu_features_t feature) 1.198 +{ 1.199 + static pixman_bool_t initialized; 1.200 + static arm_cpu_features_t features; 1.201 + 1.202 + if (!initialized) 1.203 + { 1.204 + features = detect_cpu_features(); 1.205 + initialized = TRUE; 1.206 + } 1.207 + 1.208 + return (features & feature) == feature; 1.209 +} 1.210 + 1.211 +#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ 1.212 + 1.213 +pixman_implementation_t * 1.214 +_pixman_arm_get_implementations (pixman_implementation_t *imp) 1.215 +{ 1.216 +#ifdef USE_ARM_SIMD 1.217 + if (!_pixman_disabled ("arm-simd") && have_feature (ARM_V6)) 1.218 + imp = _pixman_implementation_create_arm_simd (imp); 1.219 +#endif 1.220 + 1.221 +#ifdef USE_ARM_IWMMXT 1.222 + if (!_pixman_disabled ("arm-iwmmxt") && have_feature (ARM_IWMMXT)) 1.223 + imp = _pixman_implementation_create_mmx (imp); 1.224 +#endif 1.225 + 1.226 +#ifdef USE_ARM_NEON 1.227 + if (!_pixman_disabled ("arm-neon") && have_feature (ARM_NEON)) 1.228 + imp = _pixman_implementation_create_arm_neon (imp); 1.229 +#endif 1.230 + 1.231 + return imp; 1.232 +}