LCOV - code coverage report
Current view: top level - gfx/cairo/libpixman/src - pixman-x86.c (source / functions) Hit Total Coverage
Test: output.info Lines: 28 41 68.3 %
Date: 2017-07-14 16:53:18 Functions: 5 5 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             : #if defined(USE_X86_MMX) || defined (USE_SSE2)
      29             : 
      30             : /* The CPU detection code needs to be in a file not compiled with
      31             :  * "-mmmx -msse", as gcc would generate CMOV instructions otherwise
      32             :  * that would lead to SIGILL instructions on old CPUs that don't have
      33             :  * it.
      34             :  */
      35             : 
      36             : typedef enum
      37             : {
      38             :     X86_MMX                     = (1 << 0),
      39             :     X86_MMX_EXTENSIONS          = (1 << 1),
      40             :     X86_SSE                     = (1 << 2) | X86_MMX_EXTENSIONS,
      41             :     X86_SSE2                    = (1 << 3),
      42             :     X86_CMOV                    = (1 << 4)
      43             : } cpu_features_t;
      44             : 
      45             : #ifdef HAVE_GETISAX
      46             : 
      47             : #include <sys/auxv.h>
      48             : 
      49             : static cpu_features_t
      50             : detect_cpu_features (void)
      51             : {
      52             :     cpu_features_t features = 0;
      53             :     unsigned int result = 0;
      54             : 
      55             :     if (getisax (&result, 1))
      56             :     {
      57             :         if (result & AV_386_CMOV)
      58             :             features |= X86_CMOV;
      59             :         if (result & AV_386_MMX)
      60             :             features |= X86_MMX;
      61             :         if (result & AV_386_AMD_MMX)
      62             :             features |= X86_MMX_EXTENSIONS;
      63             :         if (result & AV_386_SSE)
      64             :             features |= X86_SSE;
      65             :         if (result & AV_386_SSE2)
      66             :             features |= X86_SSE2;
      67             :     }
      68             : 
      69             :     return features;
      70             : }
      71             : 
      72             : #else
      73             : 
      74             : #define _PIXMAN_X86_64                                                  \
      75             :     (defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64))
      76             : 
      77             : static pixman_bool_t
      78           1 : have_cpuid (void)
      79             : {
      80             : #if _PIXMAN_X86_64 || defined (_MSC_VER)
      81             : 
      82           1 :     return TRUE;
      83             : 
      84             : #elif defined (__GNUC__)
      85             :     uint32_t result;
      86             : 
      87             :     __asm__ volatile (
      88             :         "pushf"                               "\n\t"
      89             :         "pop %%eax"                   "\n\t"
      90             :         "mov %%eax, %%ecx"            "\n\t"
      91             :         "xor $0x00200000, %%eax"      "\n\t"
      92             :         "push %%eax"                  "\n\t"
      93             :         "popf"                                "\n\t"
      94             :         "pushf"                               "\n\t"
      95             :         "pop %%eax"                   "\n\t"
      96             :         "xor %%ecx, %%eax"            "\n\t"
      97             :         "mov %%eax, %0"                       "\n\t"
      98             :         : "=r" (result)
      99             :         :
     100             :         : "%eax", "%ecx");
     101             : 
     102             :     return !!result;
     103             : 
     104             : #else
     105             : #error "Unknown compiler"
     106             : #endif
     107             : }
     108             : 
     109             : #ifdef _MSC_VER
     110             : #include <intrin.h> /* for __cpuid */
     111             : #endif
     112             : 
     113             : static void
     114           1 : pixman_cpuid (uint32_t feature,
     115             :               uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
     116             : {
     117             : #if defined (__GNUC__)
     118             : 
     119             : #if _PIXMAN_X86_64
     120           1 :     __asm__ volatile (
     121             :         "cpuid"                               "\n\t"
     122             :         : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)
     123             :         : "a" (feature));
     124             : #else
     125             :     /* On x86-32 we need to be careful about the handling of %ebx
     126             :      * and %esp. We can't declare either one as clobbered
     127             :      * since they are special registers (%ebx is the "PIC
     128             :      * register" holding an offset to global data, %esp the
     129             :      * stack pointer), so we need to make sure that %ebx is
     130             :      * preserved, and that %esp has its original value when
     131             :      * accessing the output operands.
     132             :      */
     133             :     __asm__ volatile (
     134             :         "xchg %%ebx, %1"              "\n\t"
     135             :         "cpuid"                               "\n\t"
     136             :         "xchg %%ebx, %1"              "\n\t"
     137             :         : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
     138             :         : "a" (feature));
     139             : #endif
     140             : 
     141             : #elif defined (_MSC_VER)
     142             :     int info[4];
     143             : 
     144             :     __cpuid (info, feature);
     145             : 
     146             :     *a = info[0];
     147             :     *b = info[1];
     148             :     *c = info[2];
     149             :     *d = info[3];
     150             : #else
     151             : #error Unknown compiler
     152             : #endif
     153           1 : }
     154             : 
     155             : static cpu_features_t
     156           1 : detect_cpu_features (void)
     157             : {
     158             :     uint32_t a, b, c, d;
     159           1 :     cpu_features_t features = 0;
     160             : 
     161           1 :     if (!have_cpuid())
     162           0 :         return features;
     163             : 
     164             :     /* Get feature bits */
     165           1 :     pixman_cpuid (0x01, &a, &b, &c, &d);
     166           1 :     if (d & (1 << 15))
     167           1 :         features |= X86_CMOV;
     168           1 :     if (d & (1 << 23))
     169           1 :         features |= X86_MMX;
     170           1 :     if (d & (1 << 25))
     171           1 :         features |= X86_SSE;
     172           1 :     if (d & (1 << 26))
     173           1 :         features |= X86_SSE2;
     174             : 
     175             :     /* Check for AMD specific features */
     176           1 :     if ((features & X86_MMX) && !(features & X86_SSE))
     177             :     {
     178             :         char vendor[13];
     179             : 
     180             :         /* Get vendor string */
     181           0 :         memset (vendor, 0, sizeof vendor);
     182             : 
     183           0 :         pixman_cpuid (0x00, &a, &b, &c, &d);
     184           0 :         memcpy (vendor + 0, &b, 4);
     185           0 :         memcpy (vendor + 4, &d, 4);
     186           0 :         memcpy (vendor + 8, &c, 4);
     187             : 
     188           0 :         if (strcmp (vendor, "AuthenticAMD") == 0 ||
     189           0 :             strcmp (vendor, "Geode by NSC") == 0)
     190             :         {
     191           0 :             pixman_cpuid (0x80000000, &a, &b, &c, &d);
     192           0 :             if (a >= 0x80000001)
     193             :             {
     194           0 :                 pixman_cpuid (0x80000001, &a, &b, &c, &d);
     195             : 
     196           0 :                 if (d & (1 << 22))
     197           0 :                     features |= X86_MMX_EXTENSIONS;
     198             :             }
     199             :         }
     200             :     }
     201             : 
     202           1 :     return features;
     203             : }
     204             : 
     205             : #endif
     206             : 
     207             : static pixman_bool_t
     208           1 : have_feature (cpu_features_t feature)
     209             : {
     210             :     static pixman_bool_t initialized;
     211             :     static cpu_features_t features;
     212             : 
     213           1 :     if (!initialized)
     214             :     {
     215           1 :         features = detect_cpu_features();
     216           1 :         initialized = TRUE;
     217             :     }
     218             : 
     219           1 :     return (features & feature) == feature;
     220             : }
     221             : 
     222             : #endif
     223             : 
     224             : pixman_implementation_t *
     225           1 : _pixman_x86_get_implementations (pixman_implementation_t *imp)
     226             : {
     227             : #define MMX_BITS  (X86_MMX | X86_MMX_EXTENSIONS)
     228             : #define SSE2_BITS (X86_MMX | X86_MMX_EXTENSIONS | X86_SSE | X86_SSE2)
     229             : 
     230             : #ifdef USE_X86_MMX
     231             :     if (!_pixman_disabled ("mmx") && have_feature (MMX_BITS))
     232             :         imp = _pixman_implementation_create_mmx (imp);
     233             : #endif
     234             : 
     235             : #ifdef USE_SSE2
     236           1 :     if (!_pixman_disabled ("sse2") && have_feature (SSE2_BITS))
     237           1 :         imp = _pixman_implementation_create_sse2 (imp);
     238             : #endif
     239             : 
     240           1 :     return imp;
     241             : }

Generated by: LCOV version 1.13