LCOV - code coverage report
Current view: top level - gfx/cairo/libpixman/src - pixman-arm.c (source / functions) Hit Total Coverage
Test: output.info Lines: 2 2 100.0 %
Date: 2017-07-14 16:53:18 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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
      25             : 
      26             : #include "pixman-private.h"
      27             : 
      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;
      36             : 
      37             : #if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT)
      38             : 
      39             : #if defined(_MSC_VER)
      40             : 
      41             : /* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
      42             : #include <windows.h>
      43             : 
      44             : extern int pixman_msvc_try_arm_neon_op ();
      45             : extern int pixman_msvc_try_arm_simd_op ();
      46             : 
      47             : static arm_cpu_features_t
      48             : detect_cpu_features (void)
      49             : {
      50             :     arm_cpu_features_t features = 0;
      51             : 
      52             :     __try
      53             :     {
      54             :         pixman_msvc_try_arm_simd_op ();
      55             :         features |= ARM_V6;
      56             :     }
      57             :     __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
      58             :     {
      59             :     }
      60             : 
      61             :     __try
      62             :     {
      63             :         pixman_msvc_try_arm_neon_op ();
      64             :         features |= ARM_NEON;
      65             :     }
      66             :     __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
      67             :     {
      68             :     }
      69             : 
      70             :     return features;
      71             : }
      72             : 
      73             : #elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) /* iOS */
      74             : 
      75             : #include "TargetConditionals.h"
      76             : 
      77             : static arm_cpu_features_t
      78             : detect_cpu_features (void)
      79             : {
      80             :     arm_cpu_features_t features = 0;
      81             : 
      82             :     features |= ARM_V6;
      83             : 
      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
      93             : 
      94             :     return features;
      95             : }
      96             : 
      97             : #elif defined(__ANDROID__) || defined(ANDROID) /* Android */
      98             : 
      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             :     }
     110             : 
     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;
     126             : 
     127             :     return features;
     128             : }
     129             : 
     130             : #elif defined (__linux__) /* linux ELF */
     131             : 
     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>
     139             : 
     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;
     146             : 
     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;
     155             : 
     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;
     170             : 
     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             :     }
     179             : 
     180             :     return features;
     181             : }
     182             : 
     183             : #else /* Unknown */
     184             : 
     185             : static arm_cpu_features_t
     186             : detect_cpu_features (void)
     187             : {
     188             :     return 0;
     189             : }
     190             : 
     191             : #endif /* Linux elf */
     192             : 
     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;
     198             : 
     199             :     if (!initialized)
     200             :     {
     201             :         features = detect_cpu_features();
     202             :         initialized = TRUE;
     203             :     }
     204             : 
     205             :     return (features & feature) == feature;
     206             : }
     207             : 
     208             : #endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */
     209             : 
     210             : pixman_implementation_t *
     211           1 : _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
     217             : 
     218             : #ifdef USE_ARM_IWMMXT
     219             :     if (!_pixman_disabled ("arm-iwmmxt") && have_feature (ARM_IWMMXT))
     220             :         imp = _pixman_implementation_create_mmx (imp);
     221             : #endif
     222             : 
     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
     227             : 
     228           1 :     return imp;
     229             : }

Generated by: LCOV version 1.13