tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pixman-x86.c (4854B)


      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 <pixman-config.h>
     24 #endif
     25 
     26 #include "pixman-private.h"
     27 
     28 #if defined(USE_X86_MMX) || defined (USE_SSE2) || defined (USE_SSSE3)
     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    X86_SSSE3			= (1 << 5)
     44 } cpu_features_t;
     45 
     46 #ifdef HAVE_GETISAX
     47 
     48 #include <sys/auxv.h>
     49 
     50 static cpu_features_t
     51 detect_cpu_features (void)
     52 {
     53    cpu_features_t features = 0;
     54    unsigned int result = 0;
     55 
     56    if (getisax (&result, 1))
     57    {
     58 if (result & AV_386_CMOV)
     59     features |= X86_CMOV;
     60 if (result & AV_386_MMX)
     61     features |= X86_MMX;
     62 if (result & AV_386_AMD_MMX)
     63     features |= X86_MMX_EXTENSIONS;
     64 if (result & AV_386_SSE)
     65     features |= X86_SSE;
     66 if (result & AV_386_SSE2)
     67     features |= X86_SSE2;
     68 if (result & AV_386_SSSE3)
     69     features |= X86_SSSE3;
     70    }
     71 
     72    return features;
     73 }
     74 
     75 #else
     76 
     77 #if defined (__GNUC__)
     78 #include <cpuid.h>
     79 #elif defined(_MSC_VER)
     80 #include <intrin.h>
     81 #endif
     82 
     83 static void
     84 pixman_cpuid (uint32_t feature,
     85       uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
     86 {
     87 #if defined (__GNUC__)
     88    *a = *b = *c = *d = 0;
     89    __get_cpuid(feature, a, b, c, d);
     90 #elif defined (_MSC_VER)
     91    int info[4];
     92 
     93    __cpuid (info, feature);
     94 
     95    *a = info[0];
     96    *b = info[1];
     97    *c = info[2];
     98    *d = info[3];
     99 #else
    100 #error Unknown compiler
    101 #endif
    102 }
    103 
    104 static cpu_features_t
    105 detect_cpu_features (void)
    106 {
    107    uint32_t a, b, c, d;
    108    cpu_features_t features = 0;
    109 
    110    /* Get feature bits */
    111    pixman_cpuid (0x01, &a, &b, &c, &d);
    112    if (d & (1 << 15))
    113 features |= X86_CMOV;
    114    if (d & (1 << 23))
    115 features |= X86_MMX;
    116    if (d & (1 << 25))
    117 features |= X86_SSE;
    118    if (d & (1 << 26))
    119 features |= X86_SSE2;
    120    if (c & (1 << 9))
    121 features |= X86_SSSE3;
    122 
    123    /* Check for AMD specific features */
    124    if ((features & X86_MMX) && !(features & X86_SSE))
    125    {
    126 char vendor[13];
    127 
    128 /* Get vendor string */
    129 memset (vendor, 0, sizeof vendor);
    130 
    131 pixman_cpuid (0x00, &a, &b, &c, &d);
    132 memcpy (vendor + 0, &b, 4);
    133 memcpy (vendor + 4, &d, 4);
    134 memcpy (vendor + 8, &c, 4);
    135 
    136 if (strcmp (vendor, "AuthenticAMD") == 0 ||
    137     strcmp (vendor, "HygonGenuine") == 0 ||
    138     strcmp (vendor, "Geode by NSC") == 0)
    139 {
    140     pixman_cpuid (0x80000000, &a, &b, &c, &d);
    141     if (a >= 0x80000001)
    142     {
    143 	pixman_cpuid (0x80000001, &a, &b, &c, &d);
    144 
    145 	if (d & (1 << 22))
    146 	    features |= X86_MMX_EXTENSIONS;
    147     }
    148 }
    149    }
    150 
    151    return features;
    152 }
    153 
    154 #endif
    155 
    156 static pixman_bool_t
    157 have_feature (cpu_features_t feature)
    158 {
    159    static pixman_bool_t initialized;
    160    static cpu_features_t features;
    161 
    162    if (!initialized)
    163    {
    164 features = detect_cpu_features();
    165 initialized = TRUE;
    166    }
    167 
    168    return (features & feature) == feature;
    169 }
    170 
    171 #endif
    172 
    173 pixman_implementation_t *
    174 _pixman_x86_get_implementations (pixman_implementation_t *imp)
    175 {
    176 #define MMX_BITS  (X86_MMX | X86_MMX_EXTENSIONS)
    177 #define SSE2_BITS (X86_MMX | X86_MMX_EXTENSIONS | X86_SSE | X86_SSE2)
    178 #define SSSE3_BITS (X86_SSE | X86_SSE2 | X86_SSSE3)
    179 
    180 #ifdef USE_X86_MMX
    181    if (!_pixman_disabled ("mmx") && have_feature (MMX_BITS))
    182 imp = _pixman_implementation_create_mmx (imp);
    183 #endif
    184 
    185 #ifdef USE_SSE2
    186    if (!_pixman_disabled ("sse2") && have_feature (SSE2_BITS))
    187 imp = _pixman_implementation_create_sse2 (imp);
    188 #endif
    189 
    190 #ifdef USE_SSSE3
    191    if (!_pixman_disabled ("ssse3") && have_feature (SSSE3_BITS))
    192 imp = _pixman_implementation_create_ssse3 (imp);
    193 #endif
    194 
    195    return imp;
    196 }