gfx/cairo/libpixman/src/pixman-arm.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2  * Copyright © 2000 SuSE, Inc.
     3  * Copyright © 2007 Red Hat, Inc.
     4  *
     5  * Permission to use, copy, modify, distribute, and sell this software and its
     6  * documentation for any purpose is hereby granted without fee, provided that
     7  * the above copyright notice appear in all copies and that both that
     8  * copyright notice and this permission notice appear in supporting
     9  * documentation, and that the name of SuSE not be used in advertising or
    10  * publicity pertaining to distribution of the software without specific,
    11  * written prior permission.  SuSE makes no representations about the
    12  * suitability of this software for any purpose.  It is provided "as is"
    13  * without express or implied warranty.
    14  *
    15  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
    16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
    17  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
    19  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
    20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    21  */
    22 #ifdef HAVE_CONFIG_H
    23 #include <config.h>
    24 #endif
    26 #include "pixman-private.h"
    28 typedef enum
    29 {
    30     ARM_V7		= (1 << 0),
    31     ARM_V6		= (1 << 1),
    32     ARM_VFP		= (1 << 2),
    33     ARM_NEON		= (1 << 3),
    34     ARM_IWMMXT		= (1 << 4)
    35 } arm_cpu_features_t;
    37 #if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT)
    39 #if defined(_MSC_VER)
    41 /* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
    42 #include <windows.h>
    44 extern int pixman_msvc_try_arm_neon_op ();
    45 extern int pixman_msvc_try_arm_simd_op ();
    47 static arm_cpu_features_t
    48 detect_cpu_features (void)
    49 {
    50     arm_cpu_features_t features = 0;
    52     __try
    53     {
    54 	pixman_msvc_try_arm_simd_op ();
    55 	features |= ARM_V6;
    56     }
    57     __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
    58     {
    59     }
    61     __try
    62     {
    63 	pixman_msvc_try_arm_neon_op ();
    64 	features |= ARM_NEON;
    65     }
    66     __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
    67     {
    68     }
    70     return features;
    71 }
    73 #elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) /* iOS */
    75 #include "TargetConditionals.h"
    77 static arm_cpu_features_t
    78 detect_cpu_features (void)
    79 {
    80     arm_cpu_features_t features = 0;
    82     features |= ARM_V6;
    84     /* Detection of ARM NEON on iOS is fairly simple because iOS binaries
    85      * contain separate executable images for each processor architecture.
    86      * So all we have to do is detect the armv7 architecture build. The
    87      * operating system automatically runs the armv7 binary for armv7 devices
    88      * and the armv6 binary for armv6 devices.
    89      */
    90 #if defined(__ARM_NEON__)
    91     features |= ARM_NEON;
    92 #endif
    94     return features;
    95 }
    97 #elif defined(__ANDROID__) || defined(ANDROID) /* Android */
    99 static arm_cpu_features_t
   100 detect_cpu_features (void)
   101 {
   102     arm_cpu_features_t features = 0;
   103     char buf[1024];
   104     char* pos;
   105     const char* ver_token = "CPU architecture: ";
   106     FILE* f = fopen("/proc/cpuinfo", "r");
   107     if (!f) {
   108 	return features;
   109     }
   111     fread(buf, sizeof(char), sizeof(buf), f);
   112     fclose(f);
   113     pos = strstr(buf, ver_token);
   114     if (pos) {
   115 	char vchar = *(pos + strlen(ver_token));
   116 	if (vchar >= '0' && vchar <= '9') {
   117 	    int ver = vchar - '0';
   118 	    if (ver >= 7)
   119 		features |= ARM_V7;
   120 	}
   121     }
   122     if (strstr(buf, "neon") != NULL)
   123 	features |= ARM_NEON;
   124     if (strstr(buf, "vfp") != NULL)
   125 	features |= ARM_VFP;
   127     return features;
   128 }
   130 #elif defined (__linux__) /* linux ELF */
   132 #include <unistd.h>
   133 #include <sys/types.h>
   134 #include <sys/stat.h>
   135 #include <sys/mman.h>
   136 #include <fcntl.h>
   137 #include <string.h>
   138 #include <elf.h>
   140 static arm_cpu_features_t
   141 detect_cpu_features (void)
   142 {
   143     arm_cpu_features_t features = 0;
   144     Elf32_auxv_t aux;
   145     int fd;
   147     fd = open ("/proc/self/auxv", O_RDONLY);
   148     if (fd >= 0)
   149     {
   150 	while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
   151 	{
   152 	    if (aux.a_type == AT_HWCAP)
   153 	    {
   154 		uint32_t hwcap = aux.a_un.a_val;
   156 		/* hardcode these values to avoid depending on specific
   157 		 * versions of the hwcap header, e.g. HWCAP_NEON
   158 		 */
   159 		if ((hwcap & 64) != 0)
   160 		    features |= ARM_VFP;
   161 		if ((hwcap & 512) != 0)
   162 		    features |= ARM_IWMMXT;
   163 		/* this flag is only present on kernel 2.6.29 */
   164 		if ((hwcap & 4096) != 0)
   165 		    features |= ARM_NEON;
   166 	    }
   167 	    else if (aux.a_type == AT_PLATFORM)
   168 	    {
   169 		const char *plat = (const char*) aux.a_un.a_val;
   171 		if (strncmp (plat, "v7l", 3) == 0)
   172 		    features |= (ARM_V7 | ARM_V6);
   173 		else if (strncmp (plat, "v6l", 3) == 0)
   174 		    features |= ARM_V6;
   175 	    }
   176 	}
   177 	close (fd);
   178     }
   180     return features;
   181 }
   183 #else /* Unknown */
   185 static arm_cpu_features_t
   186 detect_cpu_features (void)
   187 {
   188     return 0;
   189 }
   191 #endif /* Linux elf */
   193 static pixman_bool_t
   194 have_feature (arm_cpu_features_t feature)
   195 {
   196     static pixman_bool_t initialized;
   197     static arm_cpu_features_t features;
   199     if (!initialized)
   200     {
   201 	features = detect_cpu_features();
   202 	initialized = TRUE;
   203     }
   205     return (features & feature) == feature;
   206 }
   208 #endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */
   210 pixman_implementation_t *
   211 _pixman_arm_get_implementations (pixman_implementation_t *imp)
   212 {
   213 #ifdef USE_ARM_SIMD
   214     if (!_pixman_disabled ("arm-simd") && have_feature (ARM_V6))
   215 	imp = _pixman_implementation_create_arm_simd (imp);
   216 #endif
   218 #ifdef USE_ARM_IWMMXT
   219     if (!_pixman_disabled ("arm-iwmmxt") && have_feature (ARM_IWMMXT))
   220 	imp = _pixman_implementation_create_mmx (imp);
   221 #endif
   223 #ifdef USE_ARM_NEON
   224     if (!_pixman_disabled ("arm-neon") && have_feature (ARM_NEON))
   225 	imp = _pixman_implementation_create_arm_neon (imp);
   226 #endif
   228     return imp;
   229 }

mercurial