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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /*
michael@0 2 * Copyright © 2000 SuSE, Inc.
michael@0 3 * Copyright © 2007 Red Hat, Inc.
michael@0 4 *
michael@0 5 * Permission to use, copy, modify, distribute, and sell this software and its
michael@0 6 * documentation for any purpose is hereby granted without fee, provided that
michael@0 7 * the above copyright notice appear in all copies and that both that
michael@0 8 * copyright notice and this permission notice appear in supporting
michael@0 9 * documentation, and that the name of SuSE not be used in advertising or
michael@0 10 * publicity pertaining to distribution of the software without specific,
michael@0 11 * written prior permission. SuSE makes no representations about the
michael@0 12 * suitability of this software for any purpose. It is provided "as is"
michael@0 13 * without express or implied warranty.
michael@0 14 *
michael@0 15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
michael@0 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
michael@0 17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
michael@0 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
michael@0 19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
michael@0 20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
michael@0 21 */
michael@0 22 #ifdef HAVE_CONFIG_H
michael@0 23 #include <config.h>
michael@0 24 #endif
michael@0 25
michael@0 26 #include "pixman-private.h"
michael@0 27
michael@0 28 #if defined(USE_X86_MMX) || defined (USE_SSE2)
michael@0 29
michael@0 30 /* The CPU detection code needs to be in a file not compiled with
michael@0 31 * "-mmmx -msse", as gcc would generate CMOV instructions otherwise
michael@0 32 * that would lead to SIGILL instructions on old CPUs that don't have
michael@0 33 * it.
michael@0 34 */
michael@0 35
michael@0 36 typedef enum
michael@0 37 {
michael@0 38 X86_MMX = (1 << 0),
michael@0 39 X86_MMX_EXTENSIONS = (1 << 1),
michael@0 40 X86_SSE = (1 << 2) | X86_MMX_EXTENSIONS,
michael@0 41 X86_SSE2 = (1 << 3),
michael@0 42 X86_CMOV = (1 << 4)
michael@0 43 } cpu_features_t;
michael@0 44
michael@0 45 #ifdef HAVE_GETISAX
michael@0 46
michael@0 47 #include <sys/auxv.h>
michael@0 48
michael@0 49 static cpu_features_t
michael@0 50 detect_cpu_features (void)
michael@0 51 {
michael@0 52 cpu_features_t features = 0;
michael@0 53 unsigned int result = 0;
michael@0 54
michael@0 55 if (getisax (&result, 1))
michael@0 56 {
michael@0 57 if (result & AV_386_CMOV)
michael@0 58 features |= X86_CMOV;
michael@0 59 if (result & AV_386_MMX)
michael@0 60 features |= X86_MMX;
michael@0 61 if (result & AV_386_AMD_MMX)
michael@0 62 features |= X86_MMX_EXTENSIONS;
michael@0 63 if (result & AV_386_SSE)
michael@0 64 features |= X86_SSE;
michael@0 65 if (result & AV_386_SSE2)
michael@0 66 features |= X86_SSE2;
michael@0 67 }
michael@0 68
michael@0 69 return features;
michael@0 70 }
michael@0 71
michael@0 72 #else
michael@0 73
michael@0 74 #define _PIXMAN_X86_64 \
michael@0 75 (defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64))
michael@0 76
michael@0 77 static pixman_bool_t
michael@0 78 have_cpuid (void)
michael@0 79 {
michael@0 80 #if _PIXMAN_X86_64 || defined (_MSC_VER)
michael@0 81
michael@0 82 return TRUE;
michael@0 83
michael@0 84 #elif defined (__GNUC__)
michael@0 85 uint32_t result;
michael@0 86
michael@0 87 __asm__ volatile (
michael@0 88 "pushf" "\n\t"
michael@0 89 "pop %%eax" "\n\t"
michael@0 90 "mov %%eax, %%ecx" "\n\t"
michael@0 91 "xor $0x00200000, %%eax" "\n\t"
michael@0 92 "push %%eax" "\n\t"
michael@0 93 "popf" "\n\t"
michael@0 94 "pushf" "\n\t"
michael@0 95 "pop %%eax" "\n\t"
michael@0 96 "xor %%ecx, %%eax" "\n\t"
michael@0 97 "mov %%eax, %0" "\n\t"
michael@0 98 : "=r" (result)
michael@0 99 :
michael@0 100 : "%eax", "%ecx");
michael@0 101
michael@0 102 return !!result;
michael@0 103
michael@0 104 #else
michael@0 105 #error "Unknown compiler"
michael@0 106 #endif
michael@0 107 }
michael@0 108
michael@0 109 static void
michael@0 110 pixman_cpuid (uint32_t feature,
michael@0 111 uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
michael@0 112 {
michael@0 113 #if defined (__GNUC__)
michael@0 114
michael@0 115 #if _PIXMAN_X86_64
michael@0 116 __asm__ volatile (
michael@0 117 "cpuid" "\n\t"
michael@0 118 : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)
michael@0 119 : "a" (feature));
michael@0 120 #else
michael@0 121 /* On x86-32 we need to be careful about the handling of %ebx
michael@0 122 * and %esp. We can't declare either one as clobbered
michael@0 123 * since they are special registers (%ebx is the "PIC
michael@0 124 * register" holding an offset to global data, %esp the
michael@0 125 * stack pointer), so we need to make sure that %ebx is
michael@0 126 * preserved, and that %esp has its original value when
michael@0 127 * accessing the output operands.
michael@0 128 */
michael@0 129 __asm__ volatile (
michael@0 130 "xchg %%ebx, %1" "\n\t"
michael@0 131 "cpuid" "\n\t"
michael@0 132 "xchg %%ebx, %1" "\n\t"
michael@0 133 : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
michael@0 134 : "a" (feature));
michael@0 135 #endif
michael@0 136
michael@0 137 #elif defined (_MSC_VER)
michael@0 138 int info[4];
michael@0 139
michael@0 140 __cpuid (info, feature);
michael@0 141
michael@0 142 *a = info[0];
michael@0 143 *b = info[1];
michael@0 144 *c = info[2];
michael@0 145 *d = info[3];
michael@0 146 #else
michael@0 147 #error Unknown compiler
michael@0 148 #endif
michael@0 149 }
michael@0 150
michael@0 151 static cpu_features_t
michael@0 152 detect_cpu_features (void)
michael@0 153 {
michael@0 154 uint32_t a, b, c, d;
michael@0 155 cpu_features_t features = 0;
michael@0 156
michael@0 157 if (!have_cpuid())
michael@0 158 return features;
michael@0 159
michael@0 160 /* Get feature bits */
michael@0 161 pixman_cpuid (0x01, &a, &b, &c, &d);
michael@0 162 if (d & (1 << 15))
michael@0 163 features |= X86_CMOV;
michael@0 164 if (d & (1 << 23))
michael@0 165 features |= X86_MMX;
michael@0 166 if (d & (1 << 25))
michael@0 167 features |= X86_SSE;
michael@0 168 if (d & (1 << 26))
michael@0 169 features |= X86_SSE2;
michael@0 170
michael@0 171 /* Check for AMD specific features */
michael@0 172 if ((features & X86_MMX) && !(features & X86_SSE))
michael@0 173 {
michael@0 174 char vendor[13];
michael@0 175
michael@0 176 /* Get vendor string */
michael@0 177 memset (vendor, 0, sizeof vendor);
michael@0 178
michael@0 179 pixman_cpuid (0x00, &a, &b, &c, &d);
michael@0 180 memcpy (vendor + 0, &b, 4);
michael@0 181 memcpy (vendor + 4, &d, 4);
michael@0 182 memcpy (vendor + 8, &c, 4);
michael@0 183
michael@0 184 if (strcmp (vendor, "AuthenticAMD") == 0 ||
michael@0 185 strcmp (vendor, "Geode by NSC") == 0)
michael@0 186 {
michael@0 187 pixman_cpuid (0x80000000, &a, &b, &c, &d);
michael@0 188 if (a >= 0x80000001)
michael@0 189 {
michael@0 190 pixman_cpuid (0x80000001, &a, &b, &c, &d);
michael@0 191
michael@0 192 if (d & (1 << 22))
michael@0 193 features |= X86_MMX_EXTENSIONS;
michael@0 194 }
michael@0 195 }
michael@0 196 }
michael@0 197
michael@0 198 return features;
michael@0 199 }
michael@0 200
michael@0 201 #endif
michael@0 202
michael@0 203 static pixman_bool_t
michael@0 204 have_feature (cpu_features_t feature)
michael@0 205 {
michael@0 206 static pixman_bool_t initialized;
michael@0 207 static cpu_features_t features;
michael@0 208
michael@0 209 if (!initialized)
michael@0 210 {
michael@0 211 features = detect_cpu_features();
michael@0 212 initialized = TRUE;
michael@0 213 }
michael@0 214
michael@0 215 return (features & feature) == feature;
michael@0 216 }
michael@0 217
michael@0 218 #endif
michael@0 219
michael@0 220 pixman_implementation_t *
michael@0 221 _pixman_x86_get_implementations (pixman_implementation_t *imp)
michael@0 222 {
michael@0 223 #define MMX_BITS (X86_MMX | X86_MMX_EXTENSIONS)
michael@0 224 #define SSE2_BITS (X86_MMX | X86_MMX_EXTENSIONS | X86_SSE | X86_SSE2)
michael@0 225
michael@0 226 #ifdef USE_X86_MMX
michael@0 227 if (!_pixman_disabled ("mmx") && have_feature (MMX_BITS))
michael@0 228 imp = _pixman_implementation_create_mmx (imp);
michael@0 229 #endif
michael@0 230
michael@0 231 #ifdef USE_SSE2
michael@0 232 if (!_pixman_disabled ("sse2") && have_feature (SSE2_BITS))
michael@0 233 imp = _pixman_implementation_create_sse2 (imp);
michael@0 234 #endif
michael@0 235
michael@0 236 return imp;
michael@0 237 }

mercurial