2 * Copyright © 2000 SuSE, Inc.
3 * Copyright © 2007 Red Hat, Inc.
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.
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.
26 #include "pixman-private.h"
28 #if defined(USE_X86_MMX) || defined (USE_SSE2) || defined (USE_SSSE3)
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
39 X86_MMX_EXTENSIONS
= (1 << 1),
40 X86_SSE
= (1 << 2) | X86_MMX_EXTENSIONS
,
51 detect_cpu_features (void)
53 cpu_features_t features
= 0;
54 unsigned int result
= 0;
56 if (getisax (&result
, 1))
58 if (result
& AV_386_CMOV
)
60 if (result
& AV_386_MMX
)
62 if (result
& AV_386_AMD_MMX
)
63 features
|= X86_MMX_EXTENSIONS
;
64 if (result
& AV_386_SSE
)
66 if (result
& AV_386_SSE2
)
68 if (result
& AV_386_SSSE3
)
69 features
|= X86_SSSE3
;
77 #define _PIXMAN_X86_64 \
78 (defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64))
83 #if _PIXMAN_X86_64 || defined (_MSC_VER)
87 #elif defined (__GNUC__)
93 "mov %%eax, %%ecx" "\n\t"
94 "xor $0x00200000, %%eax" "\n\t"
99 "xor %%ecx, %%eax" "\n\t"
100 "mov %%eax, %0" "\n\t"
108 #error "Unknown compiler"
113 pixman_cpuid (uint32_t feature
,
114 uint32_t *a
, uint32_t *b
, uint32_t *c
, uint32_t *d
)
116 #if defined (__GNUC__)
121 : "=a" (*a
), "=b" (*b
), "=c" (*c
), "=d" (*d
)
124 /* On x86-32 we need to be careful about the handling of %ebx
125 * and %esp. We can't declare either one as clobbered
126 * since they are special registers (%ebx is the "PIC
127 * register" holding an offset to global data, %esp the
128 * stack pointer), so we need to make sure that %ebx is
129 * preserved, and that %esp has its original value when
130 * accessing the output operands.
133 "xchg %%ebx, %1" "\n\t"
135 "xchg %%ebx, %1" "\n\t"
136 : "=a" (*a
), "=r" (*b
), "=c" (*c
), "=d" (*d
)
140 #elif defined (_MSC_VER)
143 __cpuid (info
, feature
);
150 #error Unknown compiler
154 static cpu_features_t
155 detect_cpu_features (void)
158 cpu_features_t features
= 0;
163 /* Get feature bits */
164 pixman_cpuid (0x01, &a
, &b
, &c
, &d
);
166 features
|= X86_CMOV
;
172 features
|= X86_SSE2
;
174 features
|= X86_SSSE3
;
176 /* Check for AMD specific features */
177 if ((features
& X86_MMX
) && !(features
& X86_SSE
))
181 /* Get vendor string */
182 memset (vendor
, 0, sizeof vendor
);
184 pixman_cpuid (0x00, &a
, &b
, &c
, &d
);
185 memcpy (vendor
+ 0, &b
, 4);
186 memcpy (vendor
+ 4, &d
, 4);
187 memcpy (vendor
+ 8, &c
, 4);
189 if (strcmp (vendor
, "AuthenticAMD") == 0 ||
190 strcmp (vendor
, "Geode by NSC") == 0)
192 pixman_cpuid (0x80000000, &a
, &b
, &c
, &d
);
195 pixman_cpuid (0x80000001, &a
, &b
, &c
, &d
);
198 features
|= X86_MMX_EXTENSIONS
;
209 have_feature (cpu_features_t feature
)
211 static pixman_bool_t initialized
;
212 static cpu_features_t features
;
216 features
= detect_cpu_features();
220 return (features
& feature
) == feature
;
225 pixman_implementation_t
*
226 _pixman_x86_get_implementations (pixman_implementation_t
*imp
)
228 #define MMX_BITS (X86_MMX | X86_MMX_EXTENSIONS)
229 #define SSE2_BITS (X86_MMX | X86_MMX_EXTENSIONS | X86_SSE | X86_SSE2)
230 #define SSSE3_BITS (X86_SSE | X86_SSE2 | X86_SSSE3)
233 if (!_pixman_disabled ("mmx") && have_feature (MMX_BITS
))
234 imp
= _pixman_implementation_create_mmx (imp
);
238 if (!_pixman_disabled ("sse2") && have_feature (SSE2_BITS
))
239 imp
= _pixman_implementation_create_sse2 (imp
);
243 if (!_pixman_disabled ("ssse3") && have_feature (SSSE3_BITS
))
244 imp
= _pixman_implementation_create_ssse3 (imp
);