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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/libpixman/src/pixman-x86.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,237 @@
     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 +#if defined(USE_X86_MMX) || defined (USE_SSE2)
    1.32 +
    1.33 +/* The CPU detection code needs to be in a file not compiled with
    1.34 + * "-mmmx -msse", as gcc would generate CMOV instructions otherwise
    1.35 + * that would lead to SIGILL instructions on old CPUs that don't have
    1.36 + * it.
    1.37 + */
    1.38 +
    1.39 +typedef enum
    1.40 +{
    1.41 +    X86_MMX			= (1 << 0),
    1.42 +    X86_MMX_EXTENSIONS		= (1 << 1),
    1.43 +    X86_SSE			= (1 << 2) | X86_MMX_EXTENSIONS,
    1.44 +    X86_SSE2			= (1 << 3),
    1.45 +    X86_CMOV			= (1 << 4)
    1.46 +} cpu_features_t;
    1.47 +
    1.48 +#ifdef HAVE_GETISAX
    1.49 +
    1.50 +#include <sys/auxv.h>
    1.51 +
    1.52 +static cpu_features_t
    1.53 +detect_cpu_features (void)
    1.54 +{
    1.55 +    cpu_features_t features = 0;
    1.56 +    unsigned int result = 0;
    1.57 +
    1.58 +    if (getisax (&result, 1))
    1.59 +    {
    1.60 +	if (result & AV_386_CMOV)
    1.61 +	    features |= X86_CMOV;
    1.62 +	if (result & AV_386_MMX)
    1.63 +	    features |= X86_MMX;
    1.64 +	if (result & AV_386_AMD_MMX)
    1.65 +	    features |= X86_MMX_EXTENSIONS;
    1.66 +	if (result & AV_386_SSE)
    1.67 +	    features |= X86_SSE;
    1.68 +	if (result & AV_386_SSE2)
    1.69 +	    features |= X86_SSE2;
    1.70 +    }
    1.71 +
    1.72 +    return features;
    1.73 +}
    1.74 +
    1.75 +#else
    1.76 +
    1.77 +#define _PIXMAN_X86_64							\
    1.78 +    (defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64))
    1.79 +
    1.80 +static pixman_bool_t
    1.81 +have_cpuid (void)
    1.82 +{
    1.83 +#if _PIXMAN_X86_64 || defined (_MSC_VER)
    1.84 +
    1.85 +    return TRUE;
    1.86 +
    1.87 +#elif defined (__GNUC__)
    1.88 +    uint32_t result;
    1.89 +
    1.90 +    __asm__ volatile (
    1.91 +        "pushf"				"\n\t"
    1.92 +        "pop %%eax"			"\n\t"
    1.93 +        "mov %%eax, %%ecx"		"\n\t"
    1.94 +        "xor $0x00200000, %%eax"	"\n\t"
    1.95 +        "push %%eax"			"\n\t"
    1.96 +        "popf"				"\n\t"
    1.97 +        "pushf"				"\n\t"
    1.98 +        "pop %%eax"			"\n\t"
    1.99 +        "xor %%ecx, %%eax"		"\n\t"
   1.100 +	"mov %%eax, %0"			"\n\t"
   1.101 +	: "=r" (result)
   1.102 +	:
   1.103 +	: "%eax", "%ecx");
   1.104 +
   1.105 +    return !!result;
   1.106 +
   1.107 +#else
   1.108 +#error "Unknown compiler"
   1.109 +#endif
   1.110 +}
   1.111 +
   1.112 +static void
   1.113 +pixman_cpuid (uint32_t feature,
   1.114 +	      uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
   1.115 +{
   1.116 +#if defined (__GNUC__)
   1.117 +
   1.118 +#if _PIXMAN_X86_64
   1.119 +    __asm__ volatile (
   1.120 +        "cpuid"				"\n\t"
   1.121 +	: "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)
   1.122 +	: "a" (feature));
   1.123 +#else
   1.124 +    /* On x86-32 we need to be careful about the handling of %ebx
   1.125 +     * and %esp. We can't declare either one as clobbered
   1.126 +     * since they are special registers (%ebx is the "PIC
   1.127 +     * register" holding an offset to global data, %esp the
   1.128 +     * stack pointer), so we need to make sure that %ebx is
   1.129 +     * preserved, and that %esp has its original value when
   1.130 +     * accessing the output operands.
   1.131 +     */
   1.132 +    __asm__ volatile (
   1.133 +	"xchg %%ebx, %1"		"\n\t"
   1.134 +	"cpuid"				"\n\t"
   1.135 +	"xchg %%ebx, %1"		"\n\t"
   1.136 +	: "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
   1.137 +	: "a" (feature));
   1.138 +#endif
   1.139 +
   1.140 +#elif defined (_MSC_VER)
   1.141 +    int info[4];
   1.142 +
   1.143 +    __cpuid (info, feature);
   1.144 +
   1.145 +    *a = info[0];
   1.146 +    *b = info[1];
   1.147 +    *c = info[2];
   1.148 +    *d = info[3];
   1.149 +#else
   1.150 +#error Unknown compiler
   1.151 +#endif
   1.152 +}
   1.153 +
   1.154 +static cpu_features_t
   1.155 +detect_cpu_features (void)
   1.156 +{
   1.157 +    uint32_t a, b, c, d;
   1.158 +    cpu_features_t features = 0;
   1.159 +
   1.160 +    if (!have_cpuid())
   1.161 +	return features;
   1.162 +
   1.163 +    /* Get feature bits */
   1.164 +    pixman_cpuid (0x01, &a, &b, &c, &d);
   1.165 +    if (d & (1 << 15))
   1.166 +	features |= X86_CMOV;
   1.167 +    if (d & (1 << 23))
   1.168 +	features |= X86_MMX;
   1.169 +    if (d & (1 << 25))
   1.170 +	features |= X86_SSE;
   1.171 +    if (d & (1 << 26))
   1.172 +	features |= X86_SSE2;
   1.173 +
   1.174 +    /* Check for AMD specific features */
   1.175 +    if ((features & X86_MMX) && !(features & X86_SSE))
   1.176 +    {
   1.177 +	char vendor[13];
   1.178 +
   1.179 +	/* Get vendor string */
   1.180 +	memset (vendor, 0, sizeof vendor);
   1.181 +
   1.182 +	pixman_cpuid (0x00, &a, &b, &c, &d);
   1.183 +	memcpy (vendor + 0, &b, 4);
   1.184 +	memcpy (vendor + 4, &d, 4);
   1.185 +	memcpy (vendor + 8, &c, 4);
   1.186 +
   1.187 +	if (strcmp (vendor, "AuthenticAMD") == 0 ||
   1.188 +	    strcmp (vendor, "Geode by NSC") == 0)
   1.189 +	{
   1.190 +	    pixman_cpuid (0x80000000, &a, &b, &c, &d);
   1.191 +	    if (a >= 0x80000001)
   1.192 +	    {
   1.193 +		pixman_cpuid (0x80000001, &a, &b, &c, &d);
   1.194 +
   1.195 +		if (d & (1 << 22))
   1.196 +		    features |= X86_MMX_EXTENSIONS;
   1.197 +	    }
   1.198 +	}
   1.199 +    }
   1.200 +
   1.201 +    return features;
   1.202 +}
   1.203 +
   1.204 +#endif
   1.205 +
   1.206 +static pixman_bool_t
   1.207 +have_feature (cpu_features_t feature)
   1.208 +{
   1.209 +    static pixman_bool_t initialized;
   1.210 +    static cpu_features_t features;
   1.211 +
   1.212 +    if (!initialized)
   1.213 +    {
   1.214 +	features = detect_cpu_features();
   1.215 +	initialized = TRUE;
   1.216 +    }
   1.217 +
   1.218 +    return (features & feature) == feature;
   1.219 +}
   1.220 +
   1.221 +#endif
   1.222 +
   1.223 +pixman_implementation_t *
   1.224 +_pixman_x86_get_implementations (pixman_implementation_t *imp)
   1.225 +{
   1.226 +#define MMX_BITS  (X86_MMX | X86_MMX_EXTENSIONS)
   1.227 +#define SSE2_BITS (X86_MMX | X86_MMX_EXTENSIONS | X86_SSE | X86_SSE2)
   1.228 +
   1.229 +#ifdef USE_X86_MMX
   1.230 +    if (!_pixman_disabled ("mmx") && have_feature (MMX_BITS))
   1.231 +	imp = _pixman_implementation_create_mmx (imp);
   1.232 +#endif
   1.233 +
   1.234 +#ifdef USE_SSE2
   1.235 +    if (!_pixman_disabled ("sse2") && have_feature (SSE2_BITS))
   1.236 +	imp = _pixman_implementation_create_sse2 (imp);
   1.237 +#endif
   1.238 +
   1.239 +    return imp;
   1.240 +}

mercurial