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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/libpixman/src/pixman-cpu.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,799 @@
     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 <string.h>
    1.30 +#include <stdlib.h>
    1.31 +
    1.32 +#if defined(USE_ARM_SIMD) && defined(_MSC_VER)
    1.33 +/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */
    1.34 +#include <windows.h>
    1.35 +#endif
    1.36 +
    1.37 +#if defined(__APPLE__)
    1.38 +#include "TargetConditionals.h"
    1.39 +#endif
    1.40 +
    1.41 +#include "pixman-private.h"
    1.42 +
    1.43 +#ifdef USE_VMX
    1.44 +
    1.45 +/* The CPU detection code needs to be in a file not compiled with
    1.46 + * "-maltivec -mabi=altivec", as gcc would try to save vector register
    1.47 + * across function calls causing SIGILL on cpus without Altivec/vmx.
    1.48 + */
    1.49 +static pixman_bool_t initialized = FALSE;
    1.50 +static volatile pixman_bool_t have_vmx = TRUE;
    1.51 +
    1.52 +#ifdef __APPLE__
    1.53 +#include <sys/sysctl.h>
    1.54 +
    1.55 +static pixman_bool_t
    1.56 +pixman_have_vmx (void)
    1.57 +{
    1.58 +    if (!initialized)
    1.59 +    {
    1.60 +	size_t length = sizeof(have_vmx);
    1.61 +	int error =
    1.62 +	    sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0);
    1.63 +
    1.64 +	if (error)
    1.65 +	    have_vmx = FALSE;
    1.66 +
    1.67 +	initialized = TRUE;
    1.68 +    }
    1.69 +    return have_vmx;
    1.70 +}
    1.71 +
    1.72 +#elif defined (__OpenBSD__)
    1.73 +#include <sys/param.h>
    1.74 +#include <sys/sysctl.h>
    1.75 +#include <machine/cpu.h>
    1.76 +
    1.77 +static pixman_bool_t
    1.78 +pixman_have_vmx (void)
    1.79 +{
    1.80 +    if (!initialized)
    1.81 +    {
    1.82 +	int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC };
    1.83 +	size_t length = sizeof(have_vmx);
    1.84 +	int error =
    1.85 +	    sysctl (mib, 2, &have_vmx, &length, NULL, 0);
    1.86 +
    1.87 +	if (error != 0)
    1.88 +	    have_vmx = FALSE;
    1.89 +
    1.90 +	initialized = TRUE;
    1.91 +    }
    1.92 +    return have_vmx;
    1.93 +}
    1.94 +
    1.95 +#elif defined (__linux__)
    1.96 +#include <sys/types.h>
    1.97 +#include <sys/stat.h>
    1.98 +#include <fcntl.h>
    1.99 +#include <unistd.h>
   1.100 +#include <stdio.h>
   1.101 +#include <linux/auxvec.h>
   1.102 +#include <asm/cputable.h>
   1.103 +
   1.104 +static pixman_bool_t
   1.105 +pixman_have_vmx (void)
   1.106 +{
   1.107 +    if (!initialized)
   1.108 +    {
   1.109 +	char fname[64];
   1.110 +	unsigned long buf[64];
   1.111 +	ssize_t count = 0;
   1.112 +	pid_t pid;
   1.113 +	int fd, i;
   1.114 +
   1.115 +	pid = getpid ();
   1.116 +	snprintf (fname, sizeof(fname) - 1, "/proc/%d/auxv", pid);
   1.117 +
   1.118 +	fd = open (fname, O_RDONLY);
   1.119 +	if (fd >= 0)
   1.120 +	{
   1.121 +	    for (i = 0; i <= (count / sizeof(unsigned long)); i += 2)
   1.122 +	    {
   1.123 +		/* Read more if buf is empty... */
   1.124 +		if (i == (count / sizeof(unsigned long)))
   1.125 +		{
   1.126 +		    count = read (fd, buf, sizeof(buf));
   1.127 +		    if (count <= 0)
   1.128 +			break;
   1.129 +		    i = 0;
   1.130 +		}
   1.131 +
   1.132 +		if (buf[i] == AT_HWCAP)
   1.133 +		{
   1.134 +		    have_vmx = !!(buf[i + 1] & PPC_FEATURE_HAS_ALTIVEC);
   1.135 +		    initialized = TRUE;
   1.136 +		    break;
   1.137 +		}
   1.138 +		else if (buf[i] == AT_NULL)
   1.139 +		{
   1.140 +		    break;
   1.141 +		}
   1.142 +	    }
   1.143 +	    close (fd);
   1.144 +	}
   1.145 +    }
   1.146 +    if (!initialized)
   1.147 +    {
   1.148 +	/* Something went wrong. Assume 'no' rather than playing
   1.149 +	   fragile tricks with catching SIGILL. */
   1.150 +	have_vmx = FALSE;
   1.151 +	initialized = TRUE;
   1.152 +    }
   1.153 +
   1.154 +    return have_vmx;
   1.155 +}
   1.156 +
   1.157 +#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */
   1.158 +#include <signal.h>
   1.159 +#include <setjmp.h>
   1.160 +
   1.161 +static jmp_buf jump_env;
   1.162 +
   1.163 +static void
   1.164 +vmx_test (int        sig,
   1.165 +	  siginfo_t *si,
   1.166 +	  void *     unused)
   1.167 +{
   1.168 +    longjmp (jump_env, 1);
   1.169 +}
   1.170 +
   1.171 +static pixman_bool_t
   1.172 +pixman_have_vmx (void)
   1.173 +{
   1.174 +    struct sigaction sa, osa;
   1.175 +    int jmp_result;
   1.176 +
   1.177 +    if (!initialized)
   1.178 +    {
   1.179 +	sa.sa_flags = SA_SIGINFO;
   1.180 +	sigemptyset (&sa.sa_mask);
   1.181 +	sa.sa_sigaction = vmx_test;
   1.182 +	sigaction (SIGILL, &sa, &osa);
   1.183 +	jmp_result = setjmp (jump_env);
   1.184 +	if (jmp_result == 0)
   1.185 +	{
   1.186 +	    asm volatile ( "vor 0, 0, 0" );
   1.187 +	}
   1.188 +	sigaction (SIGILL, &osa, NULL);
   1.189 +	have_vmx = (jmp_result == 0);
   1.190 +	initialized = TRUE;
   1.191 +    }
   1.192 +    return have_vmx;
   1.193 +}
   1.194 +
   1.195 +#endif /* __APPLE__ */
   1.196 +#endif /* USE_VMX */
   1.197 +
   1.198 +#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT)
   1.199 +
   1.200 +#if defined(_MSC_VER)
   1.201 +
   1.202 +#if defined(USE_ARM_SIMD)
   1.203 +extern int pixman_msvc_try_arm_simd_op ();
   1.204 +
   1.205 +pixman_bool_t
   1.206 +pixman_have_arm_simd (void)
   1.207 +{
   1.208 +    static pixman_bool_t initialized = FALSE;
   1.209 +    static pixman_bool_t have_arm_simd = FALSE;
   1.210 +
   1.211 +    if (!initialized)
   1.212 +    {
   1.213 +	__try {
   1.214 +	    pixman_msvc_try_arm_simd_op ();
   1.215 +	    have_arm_simd = TRUE;
   1.216 +	} __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) {
   1.217 +	    have_arm_simd = FALSE;
   1.218 +	}
   1.219 +	initialized = TRUE;
   1.220 +    }
   1.221 +
   1.222 +    return have_arm_simd;
   1.223 +}
   1.224 +
   1.225 +#endif /* USE_ARM_SIMD */
   1.226 +
   1.227 +#if defined(USE_ARM_NEON)
   1.228 +extern int pixman_msvc_try_arm_neon_op ();
   1.229 +
   1.230 +pixman_bool_t
   1.231 +pixman_have_arm_neon (void)
   1.232 +{
   1.233 +    static pixman_bool_t initialized = FALSE;
   1.234 +    static pixman_bool_t have_arm_neon = FALSE;
   1.235 +
   1.236 +    if (!initialized)
   1.237 +    {
   1.238 +	__try
   1.239 +	{
   1.240 +	    pixman_msvc_try_arm_neon_op ();
   1.241 +	    have_arm_neon = TRUE;
   1.242 +	}
   1.243 +	__except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION)
   1.244 +	{
   1.245 +	    have_arm_neon = FALSE;
   1.246 +	}
   1.247 +	initialized = TRUE;
   1.248 +    }
   1.249 +
   1.250 +    return have_arm_neon;
   1.251 +}
   1.252 +
   1.253 +#endif /* USE_ARM_NEON */
   1.254 +
   1.255 +#elif (defined (__APPLE__) && defined(TARGET_OS_IPHONE)) /* iOS (iPhone/iPad/iPod touch) */
   1.256 +
   1.257 +/* Detection of ARM NEON on iOS is fairly simple because iOS binaries
   1.258 + * contain separate executable images for each processor architecture.
   1.259 + * So all we have to do is detect the armv7 architecture build. The
   1.260 + * operating system automatically runs the armv7 binary for armv7 devices
   1.261 + * and the armv6 binary for armv6 devices.
   1.262 + */
   1.263 +
   1.264 +pixman_bool_t
   1.265 +pixman_have_arm_simd (void)
   1.266 +{
   1.267 +#if defined(USE_ARM_SIMD)
   1.268 +    return TRUE;
   1.269 +#else
   1.270 +    return FALSE;
   1.271 +#endif
   1.272 +}
   1.273 +
   1.274 +pixman_bool_t
   1.275 +pixman_have_arm_neon (void)
   1.276 +{
   1.277 +#if defined(USE_ARM_NEON) && defined(__ARM_NEON__)
   1.278 +    /* This is an armv7 cpu build */
   1.279 +    return TRUE;
   1.280 +#else
   1.281 +    /* This is an armv6 cpu build */
   1.282 +    return FALSE;
   1.283 +#endif
   1.284 +}
   1.285 +
   1.286 +pixman_bool_t
   1.287 +pixman_have_arm_iwmmxt (void)
   1.288 +{
   1.289 +#if defined(USE_ARM_IWMMXT)
   1.290 +    return FALSE;
   1.291 +#else
   1.292 +    return FALSE;
   1.293 +#endif
   1.294 +}
   1.295 +
   1.296 +#elif defined (__linux__) || defined(__ANDROID__) || defined(ANDROID) /* linux ELF or ANDROID */
   1.297 +
   1.298 +static pixman_bool_t arm_has_v7 = FALSE;
   1.299 +static pixman_bool_t arm_has_v6 = FALSE;
   1.300 +static pixman_bool_t arm_has_vfp = FALSE;
   1.301 +static pixman_bool_t arm_has_neon = FALSE;
   1.302 +static pixman_bool_t arm_has_iwmmxt = FALSE;
   1.303 +static pixman_bool_t arm_tests_initialized = FALSE;
   1.304 +
   1.305 +#if defined(__ANDROID__) || defined(ANDROID) /* Android device support */
   1.306 +
   1.307 +static void
   1.308 +pixman_arm_read_auxv_or_cpu_features ()
   1.309 +{
   1.310 +    char buf[1024];
   1.311 +    char* pos;
   1.312 +    const char* ver_token = "CPU architecture: ";
   1.313 +    FILE* f = fopen("/proc/cpuinfo", "r");
   1.314 +    if (!f) {
   1.315 +	arm_tests_initialized = TRUE;
   1.316 +	return;
   1.317 +    }
   1.318 +
   1.319 +    fread(buf, sizeof(char), sizeof(buf), f);
   1.320 +    fclose(f);
   1.321 +    pos = strstr(buf, ver_token);
   1.322 +    if (pos) {
   1.323 +	char vchar = *(pos + strlen(ver_token));
   1.324 +	if (vchar >= '0' && vchar <= '9') {
   1.325 +	    int ver = vchar - '0';
   1.326 +	    arm_has_v7 = ver >= 7;
   1.327 +	    arm_has_v6 = ver >= 6;
   1.328 +	}
   1.329 +    }
   1.330 +    arm_has_neon = strstr(buf, "neon") != NULL;
   1.331 +    arm_has_vfp = strstr(buf, "vfp") != NULL;
   1.332 +    arm_has_iwmmxt = strstr(buf, "iwmmxt") != NULL;
   1.333 +    arm_tests_initialized = TRUE;
   1.334 +}
   1.335 +
   1.336 +#elif defined (__linux__) /* linux ELF */
   1.337 +
   1.338 +#include <unistd.h>
   1.339 +#include <sys/types.h>
   1.340 +#include <sys/stat.h>
   1.341 +#include <sys/mman.h>
   1.342 +#include <fcntl.h>
   1.343 +#include <string.h>
   1.344 +#include <elf.h>
   1.345 +
   1.346 +static void
   1.347 +pixman_arm_read_auxv_or_cpu_features ()
   1.348 +{
   1.349 +    int fd;
   1.350 +    Elf32_auxv_t aux;
   1.351 +
   1.352 +    fd = open ("/proc/self/auxv", O_RDONLY);
   1.353 +    if (fd >= 0)
   1.354 +    {
   1.355 +	while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
   1.356 +	{
   1.357 +	    if (aux.a_type == AT_HWCAP)
   1.358 +	    {
   1.359 +		uint32_t hwcap = aux.a_un.a_val;
   1.360 +		/* hardcode these values to avoid depending on specific
   1.361 +		 * versions of the hwcap header, e.g. HWCAP_NEON
   1.362 +		 */
   1.363 +		arm_has_vfp = (hwcap & 64) != 0;
   1.364 +		arm_has_iwmmxt = (hwcap & 512) != 0;
   1.365 +		/* this flag is only present on kernel 2.6.29 */
   1.366 +		arm_has_neon = (hwcap & 4096) != 0;
   1.367 +	    }
   1.368 +	    else if (aux.a_type == AT_PLATFORM)
   1.369 +	    {
   1.370 +		const char *plat = (const char*) aux.a_un.a_val;
   1.371 +		if (strncmp (plat, "v7l", 3) == 0)
   1.372 +		{
   1.373 +		    arm_has_v7 = TRUE;
   1.374 +		    arm_has_v6 = TRUE;
   1.375 +		}
   1.376 +		else if (strncmp (plat, "v6l", 3) == 0)
   1.377 +		{
   1.378 +		    arm_has_v6 = TRUE;
   1.379 +		}
   1.380 +	    }
   1.381 +	}
   1.382 +	close (fd);
   1.383 +    }
   1.384 +
   1.385 +    arm_tests_initialized = TRUE;
   1.386 +}
   1.387 +
   1.388 +#endif /* Linux elf */
   1.389 +
   1.390 +#if defined(USE_ARM_SIMD)
   1.391 +pixman_bool_t
   1.392 +pixman_have_arm_simd (void)
   1.393 +{
   1.394 +    if (!arm_tests_initialized)
   1.395 +	pixman_arm_read_auxv_or_cpu_features ();
   1.396 +
   1.397 +    return arm_has_v6;
   1.398 +}
   1.399 +
   1.400 +#endif /* USE_ARM_SIMD */
   1.401 +
   1.402 +#if defined(USE_ARM_NEON)
   1.403 +pixman_bool_t
   1.404 +pixman_have_arm_neon (void)
   1.405 +{
   1.406 +    if (!arm_tests_initialized)
   1.407 +	pixman_arm_read_auxv_or_cpu_features ();
   1.408 +
   1.409 +    return arm_has_neon;
   1.410 +}
   1.411 +
   1.412 +#endif /* USE_ARM_NEON */
   1.413 +
   1.414 +#if defined(USE_ARM_IWMMXT)
   1.415 +pixman_bool_t
   1.416 +pixman_have_arm_iwmmxt (void)
   1.417 +{
   1.418 +    if (!arm_tests_initialized)
   1.419 +	pixman_arm_read_auxv_or_cpu_features ();
   1.420 +
   1.421 +    return arm_has_iwmmxt;
   1.422 +}
   1.423 +
   1.424 +#endif /* USE_ARM_IWMMXT */
   1.425 +
   1.426 +#else /* !_MSC_VER && !Linux elf && !Android */
   1.427 +
   1.428 +#define pixman_have_arm_simd() FALSE
   1.429 +#define pixman_have_arm_neon() FALSE
   1.430 +#define pixman_have_arm_iwmmxt() FALSE
   1.431 +
   1.432 +#endif
   1.433 +
   1.434 +#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */
   1.435 +
   1.436 +#if defined(USE_MIPS_DSPR2)
   1.437 +
   1.438 +#if defined (__linux__) /* linux ELF */
   1.439 +
   1.440 +pixman_bool_t
   1.441 +pixman_have_mips_dspr2 (void)
   1.442 +{
   1.443 +    const char *search_string = "MIPS 74K";
   1.444 +    const char *file_name = "/proc/cpuinfo";
   1.445 +    /* Simple detection of MIPS DSP ASE (revision 2) at runtime for Linux.
   1.446 +     * It is based on /proc/cpuinfo, which reveals hardware configuration
   1.447 +     * to user-space applications.  According to MIPS (early 2010), no similar
   1.448 +     * facility is universally available on the MIPS architectures, so it's up
   1.449 +     * to individual OSes to provide such.
   1.450 +     *
   1.451 +     * Only currently available MIPS core that supports DSPr2 is 74K.
   1.452 +     */
   1.453 +
   1.454 +    char cpuinfo_line[256];
   1.455 +
   1.456 +    FILE *f = NULL;
   1.457 +
   1.458 +    if ((f = fopen (file_name, "r")) == NULL)
   1.459 +        return FALSE;
   1.460 +
   1.461 +    while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL)
   1.462 +    {
   1.463 +        if (strstr (cpuinfo_line, search_string) != NULL)
   1.464 +        {
   1.465 +            fclose (f);
   1.466 +            return TRUE;
   1.467 +        }
   1.468 +    }
   1.469 +
   1.470 +    fclose (f);
   1.471 +
   1.472 +    /* Did not find string in the proc file. */
   1.473 +    return FALSE;
   1.474 +}
   1.475 +
   1.476 +#else /* linux ELF */
   1.477 +
   1.478 +#define pixman_have_mips_dspr2() FALSE
   1.479 +
   1.480 +#endif /* linux ELF */
   1.481 +
   1.482 +#endif /* USE_MIPS_DSPR2 */
   1.483 +
   1.484 +#if defined(USE_X86_MMX) || defined(USE_SSE2)
   1.485 +/* The CPU detection code needs to be in a file not compiled with
   1.486 + * "-mmmx -msse", as gcc would generate CMOV instructions otherwise
   1.487 + * that would lead to SIGILL instructions on old CPUs that don't have
   1.488 + * it.
   1.489 + */
   1.490 +#if !defined(__amd64__) && !defined(__x86_64__) && !defined(_M_AMD64)
   1.491 +
   1.492 +#ifdef HAVE_GETISAX
   1.493 +#include <sys/auxv.h>
   1.494 +#endif
   1.495 +
   1.496 +typedef enum
   1.497 +{
   1.498 +    NO_FEATURES = 0,
   1.499 +    MMX = 0x1,
   1.500 +    MMX_EXTENSIONS = 0x2,
   1.501 +    SSE = 0x6,
   1.502 +    SSE2 = 0x8,
   1.503 +    CMOV = 0x10
   1.504 +} cpu_features_t;
   1.505 +
   1.506 +
   1.507 +static unsigned int
   1.508 +detect_cpu_features (void)
   1.509 +{
   1.510 +    unsigned int features = 0;
   1.511 +    unsigned int result = 0;
   1.512 +
   1.513 +#ifdef HAVE_GETISAX
   1.514 +    if (getisax (&result, 1))
   1.515 +    {
   1.516 +	if (result & AV_386_CMOV)
   1.517 +	    features |= CMOV;
   1.518 +	if (result & AV_386_MMX)
   1.519 +	    features |= MMX;
   1.520 +	if (result & AV_386_AMD_MMX)
   1.521 +	    features |= MMX_EXTENSIONS;
   1.522 +	if (result & AV_386_SSE)
   1.523 +	    features |= SSE;
   1.524 +	if (result & AV_386_SSE2)
   1.525 +	    features |= SSE2;
   1.526 +    }
   1.527 +#else
   1.528 +    char vendor[13];
   1.529 +#ifdef _MSC_VER
   1.530 +    int vendor0 = 0, vendor1, vendor2;
   1.531 +#endif
   1.532 +    vendor[0] = 0;
   1.533 +    vendor[12] = 0;
   1.534 +
   1.535 +#ifdef __GNUC__
   1.536 +    /* see p. 118 of amd64 instruction set manual Vol3 */
   1.537 +    /* We need to be careful about the handling of %ebx and
   1.538 +     * %esp here. We can't declare either one as clobbered
   1.539 +     * since they are special registers (%ebx is the "PIC
   1.540 +     * register" holding an offset to global data, %esp the
   1.541 +     * stack pointer), so we need to make sure they have their
   1.542 +     * original values when we access the output operands.
   1.543 +     */
   1.544 +    __asm__ (
   1.545 +        "pushf\n"
   1.546 +        "pop %%eax\n"
   1.547 +        "mov %%eax, %%ecx\n"
   1.548 +        "xor $0x00200000, %%eax\n"
   1.549 +        "push %%eax\n"
   1.550 +        "popf\n"
   1.551 +        "pushf\n"
   1.552 +        "pop %%eax\n"
   1.553 +        "mov $0x0, %%edx\n"
   1.554 +        "xor %%ecx, %%eax\n"
   1.555 +        "jz 1f\n"
   1.556 +
   1.557 +        "mov $0x00000000, %%eax\n"
   1.558 +        "push %%ebx\n"
   1.559 +        "cpuid\n"
   1.560 +        "mov %%ebx, %%eax\n"
   1.561 +        "pop %%ebx\n"
   1.562 +        "mov %%eax, %1\n"
   1.563 +        "mov %%edx, %2\n"
   1.564 +        "mov %%ecx, %3\n"
   1.565 +        "mov $0x00000001, %%eax\n"
   1.566 +        "push %%ebx\n"
   1.567 +        "cpuid\n"
   1.568 +        "pop %%ebx\n"
   1.569 +        "1:\n"
   1.570 +        "mov %%edx, %0\n"
   1.571 +	: "=r" (result),
   1.572 +        "=m" (vendor[0]),
   1.573 +        "=m" (vendor[4]),
   1.574 +        "=m" (vendor[8])
   1.575 +	:
   1.576 +	: "%eax", "%ecx", "%edx"
   1.577 +        );
   1.578 +
   1.579 +#elif defined (_MSC_VER)
   1.580 +
   1.581 +    _asm {
   1.582 +	pushfd
   1.583 +	pop eax
   1.584 +	mov ecx, eax
   1.585 +	xor eax, 00200000h
   1.586 +	push eax
   1.587 +	popfd
   1.588 +	pushfd
   1.589 +	pop eax
   1.590 +	mov edx, 0
   1.591 +	xor eax, ecx
   1.592 +	jz nocpuid
   1.593 +
   1.594 +	mov eax, 0
   1.595 +	push ebx
   1.596 +	cpuid
   1.597 +	mov eax, ebx
   1.598 +	pop ebx
   1.599 +	mov vendor0, eax
   1.600 +	mov vendor1, edx
   1.601 +	mov vendor2, ecx
   1.602 +	mov eax, 1
   1.603 +	push ebx
   1.604 +	cpuid
   1.605 +	pop ebx
   1.606 +    nocpuid:
   1.607 +	mov result, edx
   1.608 +    }
   1.609 +    memmove (vendor + 0, &vendor0, 4);
   1.610 +    memmove (vendor + 4, &vendor1, 4);
   1.611 +    memmove (vendor + 8, &vendor2, 4);
   1.612 +
   1.613 +#else
   1.614 +#   error unsupported compiler
   1.615 +#endif
   1.616 +
   1.617 +    features = 0;
   1.618 +    if (result)
   1.619 +    {
   1.620 +	/* result now contains the standard feature bits */
   1.621 +	if (result & (1 << 15))
   1.622 +	    features |= CMOV;
   1.623 +	if (result & (1 << 23))
   1.624 +	    features |= MMX;
   1.625 +	if (result & (1 << 25))
   1.626 +	    features |= SSE;
   1.627 +	if (result & (1 << 26))
   1.628 +	    features |= SSE2;
   1.629 +	if ((features & MMX) && !(features & SSE) &&
   1.630 +	    (strcmp (vendor, "AuthenticAMD") == 0 ||
   1.631 +	     strcmp (vendor, "Geode by NSC") == 0))
   1.632 +	{
   1.633 +	    /* check for AMD MMX extensions */
   1.634 +#ifdef __GNUC__
   1.635 +	    __asm__ (
   1.636 +	        "	push %%ebx\n"
   1.637 +	        "	mov $0x80000000, %%eax\n"
   1.638 +	        "	cpuid\n"
   1.639 +	        "	xor %%edx, %%edx\n"
   1.640 +	        "	cmp $0x1, %%eax\n"
   1.641 +	        "	jge 2f\n"
   1.642 +	        "	mov $0x80000001, %%eax\n"
   1.643 +	        "	cpuid\n"
   1.644 +	        "2:\n"
   1.645 +	        "	pop %%ebx\n"
   1.646 +	        "	mov %%edx, %0\n"
   1.647 +		: "=r" (result)
   1.648 +		:
   1.649 +		: "%eax", "%ecx", "%edx"
   1.650 +	        );
   1.651 +#elif defined _MSC_VER
   1.652 +	    _asm {
   1.653 +		push ebx
   1.654 +		mov eax, 80000000h
   1.655 +		cpuid
   1.656 +		xor edx, edx
   1.657 +		cmp eax, 1
   1.658 +		jge notamd
   1.659 +		mov eax, 80000001h
   1.660 +		cpuid
   1.661 +	    notamd:
   1.662 +		pop ebx
   1.663 +		mov result, edx
   1.664 +	    }
   1.665 +#endif
   1.666 +	    if (result & (1 << 22))
   1.667 +		features |= MMX_EXTENSIONS;
   1.668 +	}
   1.669 +    }
   1.670 +#endif /* HAVE_GETISAX */
   1.671 +
   1.672 +    return features;
   1.673 +}
   1.674 +
   1.675 +#ifdef USE_X86_MMX
   1.676 +static pixman_bool_t
   1.677 +pixman_have_mmx (void)
   1.678 +{
   1.679 +    static pixman_bool_t initialized = FALSE;
   1.680 +    static pixman_bool_t mmx_present;
   1.681 +
   1.682 +    if (!initialized)
   1.683 +    {
   1.684 +	unsigned int features = detect_cpu_features ();
   1.685 +	mmx_present = (features & (MMX | MMX_EXTENSIONS)) == (MMX | MMX_EXTENSIONS);
   1.686 +	initialized = TRUE;
   1.687 +    }
   1.688 +
   1.689 +    return mmx_present;
   1.690 +}
   1.691 +#endif
   1.692 +
   1.693 +#ifdef USE_SSE2
   1.694 +static pixman_bool_t
   1.695 +pixman_have_sse2 (void)
   1.696 +{
   1.697 +    static pixman_bool_t initialized = FALSE;
   1.698 +    static pixman_bool_t sse2_present;
   1.699 +
   1.700 +    if (!initialized)
   1.701 +    {
   1.702 +	unsigned int features = detect_cpu_features ();
   1.703 +	sse2_present = (features & (MMX | MMX_EXTENSIONS | SSE | SSE2)) == (MMX | MMX_EXTENSIONS | SSE | SSE2);
   1.704 +	initialized = TRUE;
   1.705 +    }
   1.706 +
   1.707 +    return sse2_present;
   1.708 +}
   1.709 +
   1.710 +#endif
   1.711 +
   1.712 +#else /* __amd64__ */
   1.713 +#ifdef USE_X86_MMX
   1.714 +#define pixman_have_mmx() TRUE
   1.715 +#endif
   1.716 +#ifdef USE_SSE2
   1.717 +#define pixman_have_sse2() TRUE
   1.718 +#endif
   1.719 +#endif /* __amd64__ */
   1.720 +#endif
   1.721 +
   1.722 +static pixman_bool_t
   1.723 +disabled (const char *name)
   1.724 +{
   1.725 +    const char *env;
   1.726 +
   1.727 +    if ((env = getenv ("PIXMAN_DISABLE")))
   1.728 +    {
   1.729 +	do
   1.730 +	{
   1.731 +	    const char *end;
   1.732 +	    int len;
   1.733 +
   1.734 +	    if ((end = strchr (env, ' ')))
   1.735 +		len = end - env;
   1.736 +	    else
   1.737 +		len = strlen (env);
   1.738 +
   1.739 +	    if (strlen (name) == len && strncmp (name, env, len) == 0)
   1.740 +	    {
   1.741 +		printf ("pixman: Disabled %s implementation\n", name);
   1.742 +		return TRUE;
   1.743 +	    }
   1.744 +
   1.745 +	    env += len;
   1.746 +	}
   1.747 +	while (*env++);
   1.748 +    }
   1.749 +
   1.750 +    return FALSE;
   1.751 +}
   1.752 +
   1.753 +pixman_implementation_t *
   1.754 +_pixman_choose_implementation (void)
   1.755 +{
   1.756 +    pixman_implementation_t *imp;
   1.757 +
   1.758 +    imp = _pixman_implementation_create_general();
   1.759 +
   1.760 +    if (!disabled ("fast"))
   1.761 +	imp = _pixman_implementation_create_fast_path (imp);
   1.762 +
   1.763 +#ifdef USE_X86_MMX
   1.764 +    if (!disabled ("mmx") && pixman_have_mmx ())
   1.765 +	imp = _pixman_implementation_create_mmx (imp);
   1.766 +#endif
   1.767 +
   1.768 +#ifdef USE_SSE2
   1.769 +    if (!disabled ("sse2") && pixman_have_sse2 ())
   1.770 +	imp = _pixman_implementation_create_sse2 (imp);
   1.771 +#endif
   1.772 +
   1.773 +#ifdef USE_ARM_SIMD
   1.774 +    if (!disabled ("arm-simd") && pixman_have_arm_simd ())
   1.775 +	imp = _pixman_implementation_create_arm_simd (imp);
   1.776 +#endif
   1.777 +
   1.778 +#ifdef USE_ARM_IWMMXT
   1.779 +    if (!disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ())
   1.780 +	imp = _pixman_implementation_create_mmx (imp);
   1.781 +#endif
   1.782 +
   1.783 +#ifdef USE_ARM_NEON
   1.784 +    if (!disabled ("arm-neon") && pixman_have_arm_neon ())
   1.785 +	imp = _pixman_implementation_create_arm_neon (imp);
   1.786 +#endif
   1.787 +
   1.788 +#ifdef USE_MIPS_DSPR2
   1.789 +    if (!disabled ("mips-dspr2") && pixman_have_mips_dspr2 ())
   1.790 +	imp = _pixman_implementation_create_mips_dspr2 (imp);
   1.791 +#endif
   1.792 +
   1.793 +#ifdef USE_VMX
   1.794 +    if (!disabled ("vmx") && pixman_have_vmx ())
   1.795 +	imp = _pixman_implementation_create_vmx (imp);
   1.796 +#endif
   1.797 +
   1.798 +    imp = _pixman_implementation_create_noop (imp);
   1.799 +
   1.800 +    return imp;
   1.801 +}
   1.802 +

mercurial