Add qemu 2.4.0
[kvmfornfv.git] / qemu / pixman / pixman / pixman-mmx.c
1 /*
2  * Copyright © 2004, 2005 Red Hat, Inc.
3  * Copyright © 2004 Nicholas Miell
4  * Copyright © 2005 Trolltech AS
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of Red Hat not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  Red Hat makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23  * SOFTWARE.
24  *
25  * Author:  Søren Sandmann (sandmann@redhat.com)
26  * Minor Improvements: Nicholas Miell (nmiell@gmail.com)
27  * MMX code paths for fbcompose.c by Lars Knoll (lars@trolltech.com)
28  *
29  * Based on work by Owen Taylor
30  */
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #if defined USE_X86_MMX || defined USE_ARM_IWMMXT || defined USE_LOONGSON_MMI
37
38 #ifdef USE_LOONGSON_MMI
39 #include <loongson-mmintrin.h>
40 #else
41 #include <mmintrin.h>
42 #endif
43 #include "pixman-private.h"
44 #include "pixman-combine32.h"
45 #include "pixman-inlines.h"
46
47 #ifdef VERBOSE
48 #define CHECKPOINT() error_f ("at %s %d\n", __FUNCTION__, __LINE__)
49 #else
50 #define CHECKPOINT()
51 #endif
52
53 #if defined USE_ARM_IWMMXT && __GNUC__ == 4 && __GNUC_MINOR__ < 8
54 /* Empty the multimedia state. For some reason, ARM's mmintrin.h doesn't provide this.  */
55 extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
56 _mm_empty (void)
57 {
58
59 }
60 #endif
61
62 #ifdef USE_X86_MMX
63 # if (defined(__SUNPRO_C) || defined(_MSC_VER) || defined(_WIN64))
64 #  include <xmmintrin.h>
65 # else
66 /* We have to compile with -msse to use xmmintrin.h, but that causes SSE
67  * instructions to be generated that we don't want. Just duplicate the
68  * functions we want to use.  */
69 extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
70 _mm_movemask_pi8 (__m64 __A)
71 {
72     int ret;
73
74     asm ("pmovmskb %1, %0\n\t"
75         : "=r" (ret)
76         : "y" (__A)
77     );
78
79     return ret;
80 }
81
82 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
83 _mm_mulhi_pu16 (__m64 __A, __m64 __B)
84 {
85     asm ("pmulhuw %1, %0\n\t"
86         : "+y" (__A)
87         : "y" (__B)
88     );
89     return __A;
90 }
91
92 #  ifdef __OPTIMIZE__
93 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
94 _mm_shuffle_pi16 (__m64 __A, int8_t const __N)
95 {
96     __m64 ret;
97
98     asm ("pshufw %2, %1, %0\n\t"
99         : "=y" (ret)
100         : "y" (__A), "K" (__N)
101     );
102
103     return ret;
104 }
105 #  else
106 #   define _mm_shuffle_pi16(A, N)                                       \
107     ({                                                                  \
108         __m64 ret;                                                      \
109                                                                         \
110         asm ("pshufw %2, %1, %0\n\t"                                    \
111              : "=y" (ret)                                               \
112              : "y" (A), "K" ((const int8_t)N)                           \
113         );                                                              \
114                                                                         \
115         ret;                                                            \
116     })
117 #  endif
118 # endif
119 #endif
120
121 #ifndef _MSC_VER
122 #define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \
123  (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | (fp0))
124 #endif
125
126 /* Notes about writing mmx code
127  *
128  * give memory operands as the second operand. If you give it as the
129  * first, gcc will first load it into a register, then use that
130  * register
131  *
132  *   ie. use
133  *
134  *         _mm_mullo_pi16 (x, mmx_constant);
135  *
136  *   not
137  *
138  *         _mm_mullo_pi16 (mmx_constant, x);
139  *
140  * Also try to minimize dependencies. i.e. when you need a value, try
141  * to calculate it from a value that was calculated as early as
142  * possible.
143  */
144
145 /* --------------- MMX primitives ------------------------------------- */
146
147 /* If __m64 is defined as a struct or union, then define M64_MEMBER to be
148  * the name of the member used to access the data.
149  * If __m64 requires using mm_cvt* intrinsics functions to convert between
150  * uint64_t and __m64 values, then define USE_CVT_INTRINSICS.
151  * If __m64 and uint64_t values can just be cast to each other directly,
152  * then define USE_M64_CASTS.
153  * If __m64 is a double datatype, then define USE_M64_DOUBLE.
154  */
155 #ifdef _MSC_VER
156 # define M64_MEMBER m64_u64
157 #elif defined(__ICC)
158 # define USE_CVT_INTRINSICS
159 #elif defined(USE_LOONGSON_MMI)
160 # define USE_M64_DOUBLE
161 #elif defined(__GNUC__)
162 # define USE_M64_CASTS
163 #elif defined(__SUNPRO_C)
164 # if (__SUNPRO_C >= 0x5120) && !defined(__NOVECTORSIZE__)
165 /* Solaris Studio 12.3 (Sun C 5.12) introduces __attribute__(__vector_size__)
166  * support, and defaults to using it to define __m64, unless __NOVECTORSIZE__
167  * is defined.   If it is used, then the mm_cvt* intrinsics must be used.
168  */
169 #  define USE_CVT_INTRINSICS
170 # else
171 /* For Studio 12.2 or older, or when __attribute__(__vector_size__) is
172  * disabled, __m64 is defined as a struct containing "unsigned long long l_".
173  */
174 #  define M64_MEMBER l_
175 # endif
176 #endif
177
178 #if defined(USE_M64_CASTS) || defined(USE_CVT_INTRINSICS) || defined(USE_M64_DOUBLE)
179 typedef uint64_t mmxdatafield;
180 #else
181 typedef __m64 mmxdatafield;
182 #endif
183
184 typedef struct
185 {
186     mmxdatafield mmx_4x00ff;
187     mmxdatafield mmx_4x0080;
188     mmxdatafield mmx_565_rgb;
189     mmxdatafield mmx_565_unpack_multiplier;
190     mmxdatafield mmx_565_pack_multiplier;
191     mmxdatafield mmx_565_r;
192     mmxdatafield mmx_565_g;
193     mmxdatafield mmx_565_b;
194     mmxdatafield mmx_packed_565_rb;
195     mmxdatafield mmx_packed_565_g;
196     mmxdatafield mmx_expand_565_g;
197     mmxdatafield mmx_expand_565_b;
198     mmxdatafield mmx_expand_565_r;
199 #ifndef USE_LOONGSON_MMI
200     mmxdatafield mmx_mask_0;
201     mmxdatafield mmx_mask_1;
202     mmxdatafield mmx_mask_2;
203     mmxdatafield mmx_mask_3;
204 #endif
205     mmxdatafield mmx_full_alpha;
206     mmxdatafield mmx_4x0101;
207     mmxdatafield mmx_ff000000;
208 } mmx_data_t;
209
210 #if defined(_MSC_VER)
211 # define MMXDATA_INIT(field, val) { val ## UI64 }
212 #elif defined(M64_MEMBER)       /* __m64 is a struct, not an integral type */
213 # define MMXDATA_INIT(field, val) field =   { val ## ULL }
214 #else                           /* mmxdatafield is an integral type */
215 # define MMXDATA_INIT(field, val) field =   val ## ULL
216 #endif
217
218 static const mmx_data_t c =
219 {
220     MMXDATA_INIT (.mmx_4x00ff,                   0x00ff00ff00ff00ff),
221     MMXDATA_INIT (.mmx_4x0080,                   0x0080008000800080),
222     MMXDATA_INIT (.mmx_565_rgb,                  0x000001f0003f001f),
223     MMXDATA_INIT (.mmx_565_unpack_multiplier,    0x0000008404100840),
224     MMXDATA_INIT (.mmx_565_pack_multiplier,      0x2000000420000004),
225     MMXDATA_INIT (.mmx_565_r,                    0x000000f800000000),
226     MMXDATA_INIT (.mmx_565_g,                    0x0000000000fc0000),
227     MMXDATA_INIT (.mmx_565_b,                    0x00000000000000f8),
228     MMXDATA_INIT (.mmx_packed_565_rb,            0x00f800f800f800f8),
229     MMXDATA_INIT (.mmx_packed_565_g,             0x0000fc000000fc00),
230     MMXDATA_INIT (.mmx_expand_565_g,             0x07e007e007e007e0),
231     MMXDATA_INIT (.mmx_expand_565_b,             0x001f001f001f001f),
232     MMXDATA_INIT (.mmx_expand_565_r,             0xf800f800f800f800),
233 #ifndef USE_LOONGSON_MMI
234     MMXDATA_INIT (.mmx_mask_0,                   0xffffffffffff0000),
235     MMXDATA_INIT (.mmx_mask_1,                   0xffffffff0000ffff),
236     MMXDATA_INIT (.mmx_mask_2,                   0xffff0000ffffffff),
237     MMXDATA_INIT (.mmx_mask_3,                   0x0000ffffffffffff),
238 #endif
239     MMXDATA_INIT (.mmx_full_alpha,               0x00ff000000000000),
240     MMXDATA_INIT (.mmx_4x0101,                   0x0101010101010101),
241     MMXDATA_INIT (.mmx_ff000000,                 0xff000000ff000000),
242 };
243
244 #ifdef USE_CVT_INTRINSICS
245 #    define MC(x) to_m64 (c.mmx_ ## x)
246 #elif defined(USE_M64_CASTS)
247 #    define MC(x) ((__m64)c.mmx_ ## x)
248 #elif defined(USE_M64_DOUBLE)
249 #    define MC(x) (*(__m64 *)&c.mmx_ ## x)
250 #else
251 #    define MC(x) c.mmx_ ## x
252 #endif
253
254 static force_inline __m64
255 to_m64 (uint64_t x)
256 {
257 #ifdef USE_CVT_INTRINSICS
258     return _mm_cvtsi64_m64 (x);
259 #elif defined M64_MEMBER        /* __m64 is a struct, not an integral type */
260     __m64 res;
261
262     res.M64_MEMBER = x;
263     return res;
264 #elif defined USE_M64_DOUBLE
265     return *(__m64 *)&x;
266 #else /* USE_M64_CASTS */
267     return (__m64)x;
268 #endif
269 }
270
271 static force_inline uint64_t
272 to_uint64 (__m64 x)
273 {
274 #ifdef USE_CVT_INTRINSICS
275     return _mm_cvtm64_si64 (x);
276 #elif defined M64_MEMBER        /* __m64 is a struct, not an integral type */
277     uint64_t res = x.M64_MEMBER;
278     return res;
279 #elif defined USE_M64_DOUBLE
280     return *(uint64_t *)&x;
281 #else /* USE_M64_CASTS */
282     return (uint64_t)x;
283 #endif
284 }
285
286 static force_inline __m64
287 shift (__m64 v,
288        int   s)
289 {
290     if (s > 0)
291         return _mm_slli_si64 (v, s);
292     else if (s < 0)
293         return _mm_srli_si64 (v, -s);
294     else
295         return v;
296 }
297
298 static force_inline __m64
299 negate (__m64 mask)
300 {
301     return _mm_xor_si64 (mask, MC (4x00ff));
302 }
303
304 /* Computes the product of two unsigned fixed-point 8-bit values from 0 to 1
305  * and maps its result to the same range.
306  *
307  * Jim Blinn gives multiple ways to compute this in "Jim Blinn's Corner:
308  * Notation, Notation, Notation", the first of which is
309  *
310  *   prod(a, b) = (a * b + 128) / 255.
311  *
312  * By approximating the division by 255 as 257/65536 it can be replaced by a
313  * multiply and a right shift. This is the implementation that we use in
314  * pix_multiply(), but we _mm_mulhi_pu16() by 257 (part of SSE1 or Extended
315  * 3DNow!, and unavailable at the time of the book's publication) to perform
316  * the multiplication and right shift in a single operation.
317  *
318  *   prod(a, b) = ((a * b + 128) * 257) >> 16.
319  *
320  * A third way (how pix_multiply() was implemented prior to 14208344) exists
321  * also that performs the multiplication by 257 with adds and shifts.
322  *
323  * Where temp = a * b + 128
324  *
325  *   prod(a, b) = (temp + (temp >> 8)) >> 8.
326  */
327 static force_inline __m64
328 pix_multiply (__m64 a, __m64 b)
329 {
330     __m64 res;
331
332     res = _mm_mullo_pi16 (a, b);
333     res = _mm_adds_pu16 (res, MC (4x0080));
334     res = _mm_mulhi_pu16 (res, MC (4x0101));
335
336     return res;
337 }
338
339 static force_inline __m64
340 pix_add (__m64 a, __m64 b)
341 {
342     return _mm_adds_pu8 (a, b);
343 }
344
345 static force_inline __m64
346 expand_alpha (__m64 pixel)
347 {
348     return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE (3, 3, 3, 3));
349 }
350
351 static force_inline __m64
352 expand_alpha_rev (__m64 pixel)
353 {
354     return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE (0, 0, 0, 0));
355 }
356
357 static force_inline __m64
358 invert_colors (__m64 pixel)
359 {
360     return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE (3, 0, 1, 2));
361 }
362
363 static force_inline __m64
364 over (__m64 src,
365       __m64 srca,
366       __m64 dest)
367 {
368     return _mm_adds_pu8 (src, pix_multiply (dest, negate (srca)));
369 }
370
371 static force_inline __m64
372 over_rev_non_pre (__m64 src, __m64 dest)
373 {
374     __m64 srca = expand_alpha (src);
375     __m64 srcfaaa = _mm_or_si64 (srca, MC (full_alpha));
376
377     return over (pix_multiply (invert_colors (src), srcfaaa), srca, dest);
378 }
379
380 static force_inline __m64
381 in (__m64 src, __m64 mask)
382 {
383     return pix_multiply (src, mask);
384 }
385
386 #ifndef _MSC_VER
387 static force_inline __m64
388 in_over (__m64 src, __m64 srca, __m64 mask, __m64 dest)
389 {
390     return over (in (src, mask), pix_multiply (srca, mask), dest);
391 }
392
393 #else
394
395 #define in_over(src, srca, mask, dest)                                  \
396     over (in (src, mask), pix_multiply (srca, mask), dest)
397
398 #endif
399
400 /* Elemental unaligned loads */
401
402 static force_inline __m64 ldq_u(__m64 *p)
403 {
404 #ifdef USE_X86_MMX
405     /* x86's alignment restrictions are very relaxed. */
406     return *(__m64 *)p;
407 #elif defined USE_ARM_IWMMXT
408     int align = (uintptr_t)p & 7;
409     __m64 *aligned_p;
410     if (align == 0)
411         return *p;
412     aligned_p = (__m64 *)((uintptr_t)p & ~7);
413     return (__m64) _mm_align_si64 (aligned_p[0], aligned_p[1], align);
414 #else
415     struct __una_u64 { __m64 x __attribute__((packed)); };
416     const struct __una_u64 *ptr = (const struct __una_u64 *) p;
417     return (__m64) ptr->x;
418 #endif
419 }
420
421 static force_inline uint32_t ldl_u(const uint32_t *p)
422 {
423 #ifdef USE_X86_MMX
424     /* x86's alignment restrictions are very relaxed. */
425     return *p;
426 #else
427     struct __una_u32 { uint32_t x __attribute__((packed)); };
428     const struct __una_u32 *ptr = (const struct __una_u32 *) p;
429     return ptr->x;
430 #endif
431 }
432
433 static force_inline __m64
434 load (const uint32_t *v)
435 {
436 #ifdef USE_LOONGSON_MMI
437     __m64 ret;
438     asm ("lwc1 %0, %1\n\t"
439         : "=f" (ret)
440         : "m" (*v)
441     );
442     return ret;
443 #else
444     return _mm_cvtsi32_si64 (*v);
445 #endif
446 }
447
448 static force_inline __m64
449 load8888 (const uint32_t *v)
450 {
451 #ifdef USE_LOONGSON_MMI
452     return _mm_unpacklo_pi8_f (*(__m32 *)v, _mm_setzero_si64 ());
453 #else
454     return _mm_unpacklo_pi8 (load (v), _mm_setzero_si64 ());
455 #endif
456 }
457
458 static force_inline __m64
459 load8888u (const uint32_t *v)
460 {
461     uint32_t l = ldl_u (v);
462     return load8888 (&l);
463 }
464
465 static force_inline __m64
466 pack8888 (__m64 lo, __m64 hi)
467 {
468     return _mm_packs_pu16 (lo, hi);
469 }
470
471 static force_inline void
472 store (uint32_t *dest, __m64 v)
473 {
474 #ifdef USE_LOONGSON_MMI
475     asm ("swc1 %1, %0\n\t"
476         : "=m" (*dest)
477         : "f" (v)
478         : "memory"
479     );
480 #else
481     *dest = _mm_cvtsi64_si32 (v);
482 #endif
483 }
484
485 static force_inline void
486 store8888 (uint32_t *dest, __m64 v)
487 {
488     v = pack8888 (v, _mm_setzero_si64 ());
489     store (dest, v);
490 }
491
492 static force_inline pixman_bool_t
493 is_equal (__m64 a, __m64 b)
494 {
495 #ifdef USE_LOONGSON_MMI
496     /* __m64 is double, we can compare directly. */
497     return a == b;
498 #else
499     return _mm_movemask_pi8 (_mm_cmpeq_pi8 (a, b)) == 0xff;
500 #endif
501 }
502
503 static force_inline pixman_bool_t
504 is_opaque (__m64 v)
505 {
506 #ifdef USE_LOONGSON_MMI
507     return is_equal (_mm_and_si64 (v, MC (full_alpha)), MC (full_alpha));
508 #else
509     __m64 ffs = _mm_cmpeq_pi8 (v, v);
510     return (_mm_movemask_pi8 (_mm_cmpeq_pi8 (v, ffs)) & 0x40);
511 #endif
512 }
513
514 static force_inline pixman_bool_t
515 is_zero (__m64 v)
516 {
517     return is_equal (v, _mm_setzero_si64 ());
518 }
519
520 /* Expand 16 bits positioned at @pos (0-3) of a mmx register into
521  *
522  *    00RR00GG00BB
523  *
524  * --- Expanding 565 in the low word ---
525  *
526  * m = (m << (32 - 3)) | (m << (16 - 5)) | m;
527  * m = m & (01f0003f001f);
528  * m = m * (008404100840);
529  * m = m >> 8;
530  *
531  * Note the trick here - the top word is shifted by another nibble to
532  * avoid it bumping into the middle word
533  */
534 static force_inline __m64
535 expand565 (__m64 pixel, int pos)
536 {
537     __m64 p = pixel;
538     __m64 t1, t2;
539
540     /* move pixel to low 16 bit and zero the rest */
541 #ifdef USE_LOONGSON_MMI
542     p = loongson_extract_pi16 (p, pos);
543 #else
544     p = shift (shift (p, (3 - pos) * 16), -48);
545 #endif
546
547     t1 = shift (p, 36 - 11);
548     t2 = shift (p, 16 - 5);
549
550     p = _mm_or_si64 (t1, p);
551     p = _mm_or_si64 (t2, p);
552     p = _mm_and_si64 (p, MC (565_rgb));
553
554     pixel = _mm_mullo_pi16 (p, MC (565_unpack_multiplier));
555     return _mm_srli_pi16 (pixel, 8);
556 }
557
558 /* Expand 4 16 bit pixels in an mmx register into two mmx registers of
559  *
560  *    AARRGGBBRRGGBB
561  */
562 static force_inline void
563 expand_4xpacked565 (__m64 vin, __m64 *vout0, __m64 *vout1, int full_alpha)
564 {
565     __m64 t0, t1, alpha = _mm_setzero_si64 ();
566     __m64 r = _mm_and_si64 (vin, MC (expand_565_r));
567     __m64 g = _mm_and_si64 (vin, MC (expand_565_g));
568     __m64 b = _mm_and_si64 (vin, MC (expand_565_b));
569     if (full_alpha)
570         alpha = _mm_cmpeq_pi32 (alpha, alpha);
571
572     /* Replicate high bits into empty low bits. */
573     r = _mm_or_si64 (_mm_srli_pi16 (r, 8), _mm_srli_pi16 (r, 13));
574     g = _mm_or_si64 (_mm_srli_pi16 (g, 3), _mm_srli_pi16 (g, 9));
575     b = _mm_or_si64 (_mm_slli_pi16 (b, 3), _mm_srli_pi16 (b, 2));
576
577     r = _mm_packs_pu16 (r, _mm_setzero_si64 ());        /* 00 00 00 00 R3 R2 R1 R0 */
578     g = _mm_packs_pu16 (g, _mm_setzero_si64 ());        /* 00 00 00 00 G3 G2 G1 G0 */
579     b = _mm_packs_pu16 (b, _mm_setzero_si64 ());        /* 00 00 00 00 B3 B2 B1 B0 */
580
581     t1 = _mm_unpacklo_pi8 (r, alpha);                   /* A3 R3 A2 R2 A1 R1 A0 R0 */
582     t0 = _mm_unpacklo_pi8 (b, g);                       /* G3 B3 G2 B2 G1 B1 G0 B0 */
583
584     *vout0 = _mm_unpacklo_pi16 (t0, t1);                /* A1 R1 G1 B1 A0 R0 G0 B0 */
585     *vout1 = _mm_unpackhi_pi16 (t0, t1);                /* A3 R3 G3 B3 A2 R2 G2 B2 */
586 }
587
588 static force_inline __m64
589 expand8888 (__m64 in, int pos)
590 {
591     if (pos == 0)
592         return _mm_unpacklo_pi8 (in, _mm_setzero_si64 ());
593     else
594         return _mm_unpackhi_pi8 (in, _mm_setzero_si64 ());
595 }
596
597 static force_inline __m64
598 expandx888 (__m64 in, int pos)
599 {
600     return _mm_or_si64 (expand8888 (in, pos), MC (full_alpha));
601 }
602
603 static force_inline void
604 expand_4x565 (__m64 vin, __m64 *vout0, __m64 *vout1, __m64 *vout2, __m64 *vout3, int full_alpha)
605 {
606     __m64 v0, v1;
607     expand_4xpacked565 (vin, &v0, &v1, full_alpha);
608     *vout0 = expand8888 (v0, 0);
609     *vout1 = expand8888 (v0, 1);
610     *vout2 = expand8888 (v1, 0);
611     *vout3 = expand8888 (v1, 1);
612 }
613
614 static force_inline __m64
615 pack_565 (__m64 pixel, __m64 target, int pos)
616 {
617     __m64 p = pixel;
618     __m64 t = target;
619     __m64 r, g, b;
620
621     r = _mm_and_si64 (p, MC (565_r));
622     g = _mm_and_si64 (p, MC (565_g));
623     b = _mm_and_si64 (p, MC (565_b));
624
625 #ifdef USE_LOONGSON_MMI
626     r = shift (r, -(32 - 8));
627     g = shift (g, -(16 - 3));
628     b = shift (b, -(0  + 3));
629
630     p = _mm_or_si64 (r, g);
631     p = _mm_or_si64 (p, b);
632     return loongson_insert_pi16 (t, p, pos);
633 #else
634     r = shift (r, -(32 - 8) + pos * 16);
635     g = shift (g, -(16 - 3) + pos * 16);
636     b = shift (b, -(0  + 3) + pos * 16);
637
638     if (pos == 0)
639         t = _mm_and_si64 (t, MC (mask_0));
640     else if (pos == 1)
641         t = _mm_and_si64 (t, MC (mask_1));
642     else if (pos == 2)
643         t = _mm_and_si64 (t, MC (mask_2));
644     else if (pos == 3)
645         t = _mm_and_si64 (t, MC (mask_3));
646
647     p = _mm_or_si64 (r, t);
648     p = _mm_or_si64 (g, p);
649
650     return _mm_or_si64 (b, p);
651 #endif
652 }
653
654 static force_inline __m64
655 pack_4xpacked565 (__m64 a, __m64 b)
656 {
657     __m64 rb0 = _mm_and_si64 (a, MC (packed_565_rb));
658     __m64 rb1 = _mm_and_si64 (b, MC (packed_565_rb));
659
660     __m64 t0 = _mm_madd_pi16 (rb0, MC (565_pack_multiplier));
661     __m64 t1 = _mm_madd_pi16 (rb1, MC (565_pack_multiplier));
662
663     __m64 g0 = _mm_and_si64 (a, MC (packed_565_g));
664     __m64 g1 = _mm_and_si64 (b, MC (packed_565_g));
665
666     t0 = _mm_or_si64 (t0, g0);
667     t1 = _mm_or_si64 (t1, g1);
668
669     t0 = shift(t0, -5);
670 #ifdef USE_ARM_IWMMXT
671     t1 = shift(t1, -5);
672     return _mm_packs_pu32 (t0, t1);
673 #else
674     t1 = shift(t1, -5 + 16);
675     return _mm_shuffle_pi16 (_mm_or_si64 (t0, t1), _MM_SHUFFLE (3, 1, 2, 0));
676 #endif
677 }
678
679 #ifndef _MSC_VER
680
681 static force_inline __m64
682 pack_4x565 (__m64 v0, __m64 v1, __m64 v2, __m64 v3)
683 {
684     return pack_4xpacked565 (pack8888 (v0, v1), pack8888 (v2, v3));
685 }
686
687 static force_inline __m64
688 pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b)
689 {
690     x = pix_multiply (x, a);
691     y = pix_multiply (y, b);
692
693     return pix_add (x, y);
694 }
695
696 #else
697
698 /* MSVC only handles a "pass by register" of up to three SSE intrinsics */
699
700 #define pack_4x565(v0, v1, v2, v3) \
701     pack_4xpacked565 (pack8888 (v0, v1), pack8888 (v2, v3))
702
703 #define pix_add_mul(x, a, y, b)  \
704     ( x = pix_multiply (x, a),   \
705       y = pix_multiply (y, b),   \
706       pix_add (x, y) )
707
708 #endif
709
710 /* --------------- MMX code patch for fbcompose.c --------------------- */
711
712 static force_inline __m64
713 combine (const uint32_t *src, const uint32_t *mask)
714 {
715     __m64 vsrc = load8888 (src);
716
717     if (mask)
718     {
719         __m64 m = load8888 (mask);
720
721         m = expand_alpha (m);
722         vsrc = pix_multiply (vsrc, m);
723     }
724
725     return vsrc;
726 }
727
728 static force_inline __m64
729 core_combine_over_u_pixel_mmx (__m64 vsrc, __m64 vdst)
730 {
731     vsrc = _mm_unpacklo_pi8 (vsrc, _mm_setzero_si64 ());
732
733     if (is_opaque (vsrc))
734     {
735         return vsrc;
736     }
737     else if (!is_zero (vsrc))
738     {
739         return over (vsrc, expand_alpha (vsrc),
740                      _mm_unpacklo_pi8 (vdst, _mm_setzero_si64 ()));
741     }
742
743     return _mm_unpacklo_pi8 (vdst, _mm_setzero_si64 ());
744 }
745
746 static void
747 mmx_combine_over_u (pixman_implementation_t *imp,
748                     pixman_op_t              op,
749                     uint32_t *               dest,
750                     const uint32_t *         src,
751                     const uint32_t *         mask,
752                     int                      width)
753 {
754     const uint32_t *end = dest + width;
755
756     while (dest < end)
757     {
758         __m64 vsrc = combine (src, mask);
759
760         if (is_opaque (vsrc))
761         {
762             store8888 (dest, vsrc);
763         }
764         else if (!is_zero (vsrc))
765         {
766             __m64 sa = expand_alpha (vsrc);
767             store8888 (dest, over (vsrc, sa, load8888 (dest)));
768         }
769
770         ++dest;
771         ++src;
772         if (mask)
773             ++mask;
774     }
775     _mm_empty ();
776 }
777
778 static void
779 mmx_combine_over_reverse_u (pixman_implementation_t *imp,
780                             pixman_op_t              op,
781                             uint32_t *               dest,
782                             const uint32_t *         src,
783                             const uint32_t *         mask,
784                             int                      width)
785 {
786     const uint32_t *end = dest + width;
787
788     while (dest < end)
789     {
790         __m64 d, da;
791         __m64 s = combine (src, mask);
792
793         d = load8888 (dest);
794         da = expand_alpha (d);
795         store8888 (dest, over (d, da, s));
796
797         ++dest;
798         ++src;
799         if (mask)
800             mask++;
801     }
802     _mm_empty ();
803 }
804
805 static void
806 mmx_combine_in_u (pixman_implementation_t *imp,
807                   pixman_op_t              op,
808                   uint32_t *               dest,
809                   const uint32_t *         src,
810                   const uint32_t *         mask,
811                   int                      width)
812 {
813     const uint32_t *end = dest + width;
814
815     while (dest < end)
816     {
817         __m64 a;
818         __m64 x = combine (src, mask);
819
820         a = load8888 (dest);
821         a = expand_alpha (a);
822         x = pix_multiply (x, a);
823
824         store8888 (dest, x);
825
826         ++dest;
827         ++src;
828         if (mask)
829             mask++;
830     }
831     _mm_empty ();
832 }
833
834 static void
835 mmx_combine_in_reverse_u (pixman_implementation_t *imp,
836                           pixman_op_t              op,
837                           uint32_t *               dest,
838                           const uint32_t *         src,
839                           const uint32_t *         mask,
840                           int                      width)
841 {
842     const uint32_t *end = dest + width;
843
844     while (dest < end)
845     {
846         __m64 a = combine (src, mask);
847         __m64 x;
848
849         x = load8888 (dest);
850         a = expand_alpha (a);
851         x = pix_multiply (x, a);
852         store8888 (dest, x);
853
854         ++dest;
855         ++src;
856         if (mask)
857             mask++;
858     }
859     _mm_empty ();
860 }
861
862 static void
863 mmx_combine_out_u (pixman_implementation_t *imp,
864                    pixman_op_t              op,
865                    uint32_t *               dest,
866                    const uint32_t *         src,
867                    const uint32_t *         mask,
868                    int                      width)
869 {
870     const uint32_t *end = dest + width;
871
872     while (dest < end)
873     {
874         __m64 a;
875         __m64 x = combine (src, mask);
876
877         a = load8888 (dest);
878         a = expand_alpha (a);
879         a = negate (a);
880         x = pix_multiply (x, a);
881         store8888 (dest, x);
882
883         ++dest;
884         ++src;
885         if (mask)
886             mask++;
887     }
888     _mm_empty ();
889 }
890
891 static void
892 mmx_combine_out_reverse_u (pixman_implementation_t *imp,
893                            pixman_op_t              op,
894                            uint32_t *               dest,
895                            const uint32_t *         src,
896                            const uint32_t *         mask,
897                            int                      width)
898 {
899     const uint32_t *end = dest + width;
900
901     while (dest < end)
902     {
903         __m64 a = combine (src, mask);
904         __m64 x;
905
906         x = load8888 (dest);
907         a = expand_alpha (a);
908         a = negate (a);
909         x = pix_multiply (x, a);
910
911         store8888 (dest, x);
912
913         ++dest;
914         ++src;
915         if (mask)
916             mask++;
917     }
918     _mm_empty ();
919 }
920
921 static void
922 mmx_combine_atop_u (pixman_implementation_t *imp,
923                     pixman_op_t              op,
924                     uint32_t *               dest,
925                     const uint32_t *         src,
926                     const uint32_t *         mask,
927                     int                      width)
928 {
929     const uint32_t *end = dest + width;
930
931     while (dest < end)
932     {
933         __m64 da, d, sia;
934         __m64 s = combine (src, mask);
935
936         d = load8888 (dest);
937         sia = expand_alpha (s);
938         sia = negate (sia);
939         da = expand_alpha (d);
940         s = pix_add_mul (s, da, d, sia);
941         store8888 (dest, s);
942
943         ++dest;
944         ++src;
945         if (mask)
946             mask++;
947     }
948     _mm_empty ();
949 }
950
951 static void
952 mmx_combine_atop_reverse_u (pixman_implementation_t *imp,
953                             pixman_op_t              op,
954                             uint32_t *               dest,
955                             const uint32_t *         src,
956                             const uint32_t *         mask,
957                             int                      width)
958 {
959     const uint32_t *end;
960
961     end = dest + width;
962
963     while (dest < end)
964     {
965         __m64 dia, d, sa;
966         __m64 s = combine (src, mask);
967
968         d = load8888 (dest);
969         sa = expand_alpha (s);
970         dia = expand_alpha (d);
971         dia = negate (dia);
972         s = pix_add_mul (s, dia, d, sa);
973         store8888 (dest, s);
974
975         ++dest;
976         ++src;
977         if (mask)
978             mask++;
979     }
980     _mm_empty ();
981 }
982
983 static void
984 mmx_combine_xor_u (pixman_implementation_t *imp,
985                    pixman_op_t              op,
986                    uint32_t *               dest,
987                    const uint32_t *         src,
988                    const uint32_t *         mask,
989                    int                      width)
990 {
991     const uint32_t *end = dest + width;
992
993     while (dest < end)
994     {
995         __m64 dia, d, sia;
996         __m64 s = combine (src, mask);
997
998         d = load8888 (dest);
999         sia = expand_alpha (s);
1000         dia = expand_alpha (d);
1001         sia = negate (sia);
1002         dia = negate (dia);
1003         s = pix_add_mul (s, dia, d, sia);
1004         store8888 (dest, s);
1005
1006         ++dest;
1007         ++src;
1008         if (mask)
1009             mask++;
1010     }
1011     _mm_empty ();
1012 }
1013
1014 static void
1015 mmx_combine_add_u (pixman_implementation_t *imp,
1016                    pixman_op_t              op,
1017                    uint32_t *               dest,
1018                    const uint32_t *         src,
1019                    const uint32_t *         mask,
1020                    int                      width)
1021 {
1022     const uint32_t *end = dest + width;
1023
1024     while (dest < end)
1025     {
1026         __m64 d;
1027         __m64 s = combine (src, mask);
1028
1029         d = load8888 (dest);
1030         s = pix_add (s, d);
1031         store8888 (dest, s);
1032
1033         ++dest;
1034         ++src;
1035         if (mask)
1036             mask++;
1037     }
1038     _mm_empty ();
1039 }
1040
1041 static void
1042 mmx_combine_saturate_u (pixman_implementation_t *imp,
1043                         pixman_op_t              op,
1044                         uint32_t *               dest,
1045                         const uint32_t *         src,
1046                         const uint32_t *         mask,
1047                         int                      width)
1048 {
1049     const uint32_t *end = dest + width;
1050
1051     while (dest < end)
1052     {
1053         uint32_t s, sa, da;
1054         uint32_t d = *dest;
1055         __m64 ms = combine (src, mask);
1056         __m64 md = load8888 (dest);
1057
1058         store8888(&s, ms);
1059         da = ~d >> 24;
1060         sa = s >> 24;
1061
1062         if (sa > da)
1063         {
1064             uint32_t quot = DIV_UN8 (da, sa) << 24;
1065             __m64 msa = load8888 (&quot);
1066             msa = expand_alpha (msa);
1067             ms = pix_multiply (ms, msa);
1068         }
1069
1070         md = pix_add (md, ms);
1071         store8888 (dest, md);
1072
1073         ++src;
1074         ++dest;
1075         if (mask)
1076             mask++;
1077     }
1078     _mm_empty ();
1079 }
1080
1081 static void
1082 mmx_combine_src_ca (pixman_implementation_t *imp,
1083                     pixman_op_t              op,
1084                     uint32_t *               dest,
1085                     const uint32_t *         src,
1086                     const uint32_t *         mask,
1087                     int                      width)
1088 {
1089     const uint32_t *end = src + width;
1090
1091     while (src < end)
1092     {
1093         __m64 a = load8888 (mask);
1094         __m64 s = load8888 (src);
1095
1096         s = pix_multiply (s, a);
1097         store8888 (dest, s);
1098
1099         ++src;
1100         ++mask;
1101         ++dest;
1102     }
1103     _mm_empty ();
1104 }
1105
1106 static void
1107 mmx_combine_over_ca (pixman_implementation_t *imp,
1108                      pixman_op_t              op,
1109                      uint32_t *               dest,
1110                      const uint32_t *         src,
1111                      const uint32_t *         mask,
1112                      int                      width)
1113 {
1114     const uint32_t *end = src + width;
1115
1116     while (src < end)
1117     {
1118         __m64 a = load8888 (mask);
1119         __m64 s = load8888 (src);
1120         __m64 d = load8888 (dest);
1121         __m64 sa = expand_alpha (s);
1122
1123         store8888 (dest, in_over (s, sa, a, d));
1124
1125         ++src;
1126         ++dest;
1127         ++mask;
1128     }
1129     _mm_empty ();
1130 }
1131
1132 static void
1133 mmx_combine_over_reverse_ca (pixman_implementation_t *imp,
1134                              pixman_op_t              op,
1135                              uint32_t *               dest,
1136                              const uint32_t *         src,
1137                              const uint32_t *         mask,
1138                              int                      width)
1139 {
1140     const uint32_t *end = src + width;
1141
1142     while (src < end)
1143     {
1144         __m64 a = load8888 (mask);
1145         __m64 s = load8888 (src);
1146         __m64 d = load8888 (dest);
1147         __m64 da = expand_alpha (d);
1148
1149         store8888 (dest, over (d, da, in (s, a)));
1150
1151         ++src;
1152         ++dest;
1153         ++mask;
1154     }
1155     _mm_empty ();
1156 }
1157
1158 static void
1159 mmx_combine_in_ca (pixman_implementation_t *imp,
1160                    pixman_op_t              op,
1161                    uint32_t *               dest,
1162                    const uint32_t *         src,
1163                    const uint32_t *         mask,
1164                    int                      width)
1165 {
1166     const uint32_t *end = src + width;
1167
1168     while (src < end)
1169     {
1170         __m64 a = load8888 (mask);
1171         __m64 s = load8888 (src);
1172         __m64 d = load8888 (dest);
1173         __m64 da = expand_alpha (d);
1174
1175         s = pix_multiply (s, a);
1176         s = pix_multiply (s, da);
1177         store8888 (dest, s);
1178
1179         ++src;
1180         ++dest;
1181         ++mask;
1182     }
1183     _mm_empty ();
1184 }
1185
1186 static void
1187 mmx_combine_in_reverse_ca (pixman_implementation_t *imp,
1188                            pixman_op_t              op,
1189                            uint32_t *               dest,
1190                            const uint32_t *         src,
1191                            const uint32_t *         mask,
1192                            int                      width)
1193 {
1194     const uint32_t *end = src + width;
1195
1196     while (src < end)
1197     {
1198         __m64 a = load8888 (mask);
1199         __m64 s = load8888 (src);
1200         __m64 d = load8888 (dest);
1201         __m64 sa = expand_alpha (s);
1202
1203         a = pix_multiply (a, sa);
1204         d = pix_multiply (d, a);
1205         store8888 (dest, d);
1206
1207         ++src;
1208         ++dest;
1209         ++mask;
1210     }
1211     _mm_empty ();
1212 }
1213
1214 static void
1215 mmx_combine_out_ca (pixman_implementation_t *imp,
1216                     pixman_op_t              op,
1217                     uint32_t *               dest,
1218                     const uint32_t *         src,
1219                     const uint32_t *         mask,
1220                     int                      width)
1221 {
1222     const uint32_t *end = src + width;
1223
1224     while (src < end)
1225     {
1226         __m64 a = load8888 (mask);
1227         __m64 s = load8888 (src);
1228         __m64 d = load8888 (dest);
1229         __m64 da = expand_alpha (d);
1230
1231         da = negate (da);
1232         s = pix_multiply (s, a);
1233         s = pix_multiply (s, da);
1234         store8888 (dest, s);
1235
1236         ++src;
1237         ++dest;
1238         ++mask;
1239     }
1240     _mm_empty ();
1241 }
1242
1243 static void
1244 mmx_combine_out_reverse_ca (pixman_implementation_t *imp,
1245                             pixman_op_t              op,
1246                             uint32_t *               dest,
1247                             const uint32_t *         src,
1248                             const uint32_t *         mask,
1249                             int                      width)
1250 {
1251     const uint32_t *end = src + width;
1252
1253     while (src < end)
1254     {
1255         __m64 a = load8888 (mask);
1256         __m64 s = load8888 (src);
1257         __m64 d = load8888 (dest);
1258         __m64 sa = expand_alpha (s);
1259
1260         a = pix_multiply (a, sa);
1261         a = negate (a);
1262         d = pix_multiply (d, a);
1263         store8888 (dest, d);
1264
1265         ++src;
1266         ++dest;
1267         ++mask;
1268     }
1269     _mm_empty ();
1270 }
1271
1272 static void
1273 mmx_combine_atop_ca (pixman_implementation_t *imp,
1274                      pixman_op_t              op,
1275                      uint32_t *               dest,
1276                      const uint32_t *         src,
1277                      const uint32_t *         mask,
1278                      int                      width)
1279 {
1280     const uint32_t *end = src + width;
1281
1282     while (src < end)
1283     {
1284         __m64 a = load8888 (mask);
1285         __m64 s = load8888 (src);
1286         __m64 d = load8888 (dest);
1287         __m64 da = expand_alpha (d);
1288         __m64 sa = expand_alpha (s);
1289
1290         s = pix_multiply (s, a);
1291         a = pix_multiply (a, sa);
1292         a = negate (a);
1293         d = pix_add_mul (d, a, s, da);
1294         store8888 (dest, d);
1295
1296         ++src;
1297         ++dest;
1298         ++mask;
1299     }
1300     _mm_empty ();
1301 }
1302
1303 static void
1304 mmx_combine_atop_reverse_ca (pixman_implementation_t *imp,
1305                              pixman_op_t              op,
1306                              uint32_t *               dest,
1307                              const uint32_t *         src,
1308                              const uint32_t *         mask,
1309                              int                      width)
1310 {
1311     const uint32_t *end = src + width;
1312
1313     while (src < end)
1314     {
1315         __m64 a = load8888 (mask);
1316         __m64 s = load8888 (src);
1317         __m64 d = load8888 (dest);
1318         __m64 da = expand_alpha (d);
1319         __m64 sa = expand_alpha (s);
1320
1321         s = pix_multiply (s, a);
1322         a = pix_multiply (a, sa);
1323         da = negate (da);
1324         d = pix_add_mul (d, a, s, da);
1325         store8888 (dest, d);
1326
1327         ++src;
1328         ++dest;
1329         ++mask;
1330     }
1331     _mm_empty ();
1332 }
1333
1334 static void
1335 mmx_combine_xor_ca (pixman_implementation_t *imp,
1336                     pixman_op_t              op,
1337                     uint32_t *               dest,
1338                     const uint32_t *         src,
1339                     const uint32_t *         mask,
1340                     int                      width)
1341 {
1342     const uint32_t *end = src + width;
1343
1344     while (src < end)
1345     {
1346         __m64 a = load8888 (mask);
1347         __m64 s = load8888 (src);
1348         __m64 d = load8888 (dest);
1349         __m64 da = expand_alpha (d);
1350         __m64 sa = expand_alpha (s);
1351
1352         s = pix_multiply (s, a);
1353         a = pix_multiply (a, sa);
1354         da = negate (da);
1355         a = negate (a);
1356         d = pix_add_mul (d, a, s, da);
1357         store8888 (dest, d);
1358
1359         ++src;
1360         ++dest;
1361         ++mask;
1362     }
1363     _mm_empty ();
1364 }
1365
1366 static void
1367 mmx_combine_add_ca (pixman_implementation_t *imp,
1368                     pixman_op_t              op,
1369                     uint32_t *               dest,
1370                     const uint32_t *         src,
1371                     const uint32_t *         mask,
1372                     int                      width)
1373 {
1374     const uint32_t *end = src + width;
1375
1376     while (src < end)
1377     {
1378         __m64 a = load8888 (mask);
1379         __m64 s = load8888 (src);
1380         __m64 d = load8888 (dest);
1381
1382         s = pix_multiply (s, a);
1383         d = pix_add (s, d);
1384         store8888 (dest, d);
1385
1386         ++src;
1387         ++dest;
1388         ++mask;
1389     }
1390     _mm_empty ();
1391 }
1392
1393 /* ------------- MMX code paths called from fbpict.c -------------------- */
1394
1395 static void
1396 mmx_composite_over_n_8888 (pixman_implementation_t *imp,
1397                            pixman_composite_info_t *info)
1398 {
1399     PIXMAN_COMPOSITE_ARGS (info);
1400     uint32_t src;
1401     uint32_t    *dst_line, *dst;
1402     int32_t w;
1403     int dst_stride;
1404     __m64 vsrc, vsrca;
1405
1406     CHECKPOINT ();
1407
1408     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1409
1410     if (src == 0)
1411         return;
1412
1413     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1414
1415     vsrc = load8888 (&src);
1416     vsrca = expand_alpha (vsrc);
1417
1418     while (height--)
1419     {
1420         dst = dst_line;
1421         dst_line += dst_stride;
1422         w = width;
1423
1424         CHECKPOINT ();
1425
1426         while (w && (uintptr_t)dst & 7)
1427         {
1428             store8888 (dst, over (vsrc, vsrca, load8888 (dst)));
1429
1430             w--;
1431             dst++;
1432         }
1433
1434         while (w >= 2)
1435         {
1436             __m64 vdest;
1437             __m64 dest0, dest1;
1438
1439             vdest = *(__m64 *)dst;
1440
1441             dest0 = over (vsrc, vsrca, expand8888 (vdest, 0));
1442             dest1 = over (vsrc, vsrca, expand8888 (vdest, 1));
1443
1444             *(__m64 *)dst = pack8888 (dest0, dest1);
1445
1446             dst += 2;
1447             w -= 2;
1448         }
1449
1450         CHECKPOINT ();
1451
1452         if (w)
1453         {
1454             store8888 (dst, over (vsrc, vsrca, load8888 (dst)));
1455         }
1456     }
1457
1458     _mm_empty ();
1459 }
1460
1461 static void
1462 mmx_composite_over_n_0565 (pixman_implementation_t *imp,
1463                            pixman_composite_info_t *info)
1464 {
1465     PIXMAN_COMPOSITE_ARGS (info);
1466     uint32_t src;
1467     uint16_t    *dst_line, *dst;
1468     int32_t w;
1469     int dst_stride;
1470     __m64 vsrc, vsrca;
1471
1472     CHECKPOINT ();
1473
1474     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1475
1476     if (src == 0)
1477         return;
1478
1479     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1480
1481     vsrc = load8888 (&src);
1482     vsrca = expand_alpha (vsrc);
1483
1484     while (height--)
1485     {
1486         dst = dst_line;
1487         dst_line += dst_stride;
1488         w = width;
1489
1490         CHECKPOINT ();
1491
1492         while (w && (uintptr_t)dst & 7)
1493         {
1494             uint64_t d = *dst;
1495             __m64 vdest = expand565 (to_m64 (d), 0);
1496
1497             vdest = pack_565 (over (vsrc, vsrca, vdest), vdest, 0);
1498             *dst = to_uint64 (vdest);
1499
1500             w--;
1501             dst++;
1502         }
1503
1504         while (w >= 4)
1505         {
1506             __m64 vdest = *(__m64 *)dst;
1507             __m64 v0, v1, v2, v3;
1508
1509             expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0);
1510
1511             v0 = over (vsrc, vsrca, v0);
1512             v1 = over (vsrc, vsrca, v1);
1513             v2 = over (vsrc, vsrca, v2);
1514             v3 = over (vsrc, vsrca, v3);
1515
1516             *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3);
1517
1518             dst += 4;
1519             w -= 4;
1520         }
1521
1522         CHECKPOINT ();
1523
1524         while (w)
1525         {
1526             uint64_t d = *dst;
1527             __m64 vdest = expand565 (to_m64 (d), 0);
1528
1529             vdest = pack_565 (over (vsrc, vsrca, vdest), vdest, 0);
1530             *dst = to_uint64 (vdest);
1531
1532             w--;
1533             dst++;
1534         }
1535     }
1536
1537     _mm_empty ();
1538 }
1539
1540 static void
1541 mmx_composite_over_n_8888_8888_ca (pixman_implementation_t *imp,
1542                                    pixman_composite_info_t *info)
1543 {
1544     PIXMAN_COMPOSITE_ARGS (info);
1545     uint32_t src;
1546     uint32_t    *dst_line;
1547     uint32_t    *mask_line;
1548     int dst_stride, mask_stride;
1549     __m64 vsrc, vsrca;
1550
1551     CHECKPOINT ();
1552
1553     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1554
1555     if (src == 0)
1556         return;
1557
1558     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1559     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
1560
1561     vsrc = load8888 (&src);
1562     vsrca = expand_alpha (vsrc);
1563
1564     while (height--)
1565     {
1566         int twidth = width;
1567         uint32_t *p = (uint32_t *)mask_line;
1568         uint32_t *q = (uint32_t *)dst_line;
1569
1570         while (twidth && (uintptr_t)q & 7)
1571         {
1572             uint32_t m = *(uint32_t *)p;
1573
1574             if (m)
1575             {
1576                 __m64 vdest = load8888 (q);
1577                 vdest = in_over (vsrc, vsrca, load8888 (&m), vdest);
1578                 store8888 (q, vdest);
1579             }
1580
1581             twidth--;
1582             p++;
1583             q++;
1584         }
1585
1586         while (twidth >= 2)
1587         {
1588             uint32_t m0, m1;
1589             m0 = *p;
1590             m1 = *(p + 1);
1591
1592             if (m0 | m1)
1593             {
1594                 __m64 dest0, dest1;
1595                 __m64 vdest = *(__m64 *)q;
1596
1597                 dest0 = in_over (vsrc, vsrca, load8888 (&m0),
1598                                  expand8888 (vdest, 0));
1599                 dest1 = in_over (vsrc, vsrca, load8888 (&m1),
1600                                  expand8888 (vdest, 1));
1601
1602                 *(__m64 *)q = pack8888 (dest0, dest1);
1603             }
1604
1605             p += 2;
1606             q += 2;
1607             twidth -= 2;
1608         }
1609
1610         if (twidth)
1611         {
1612             uint32_t m = *(uint32_t *)p;
1613
1614             if (m)
1615             {
1616                 __m64 vdest = load8888 (q);
1617                 vdest = in_over (vsrc, vsrca, load8888 (&m), vdest);
1618                 store8888 (q, vdest);
1619             }
1620
1621             twidth--;
1622             p++;
1623             q++;
1624         }
1625
1626         dst_line += dst_stride;
1627         mask_line += mask_stride;
1628     }
1629
1630     _mm_empty ();
1631 }
1632
1633 static void
1634 mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp,
1635                                 pixman_composite_info_t *info)
1636 {
1637     PIXMAN_COMPOSITE_ARGS (info);
1638     uint32_t    *dst_line, *dst;
1639     uint32_t    *src_line, *src;
1640     uint32_t mask;
1641     __m64 vmask;
1642     int dst_stride, src_stride;
1643     int32_t w;
1644
1645     CHECKPOINT ();
1646
1647     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1648     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1649
1650     mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format);
1651     vmask = expand_alpha (load8888 (&mask));
1652
1653     while (height--)
1654     {
1655         dst = dst_line;
1656         dst_line += dst_stride;
1657         src = src_line;
1658         src_line += src_stride;
1659         w = width;
1660
1661         while (w && (uintptr_t)dst & 7)
1662         {
1663             __m64 s = load8888 (src);
1664             __m64 d = load8888 (dst);
1665
1666             store8888 (dst, in_over (s, expand_alpha (s), vmask, d));
1667
1668             w--;
1669             dst++;
1670             src++;
1671         }
1672
1673         while (w >= 2)
1674         {
1675             __m64 vs = ldq_u ((__m64 *)src);
1676             __m64 vd = *(__m64 *)dst;
1677             __m64 vsrc0 = expand8888 (vs, 0);
1678             __m64 vsrc1 = expand8888 (vs, 1);
1679
1680             *(__m64 *)dst = pack8888 (
1681                 in_over (vsrc0, expand_alpha (vsrc0), vmask, expand8888 (vd, 0)),
1682                 in_over (vsrc1, expand_alpha (vsrc1), vmask, expand8888 (vd, 1)));
1683
1684             w -= 2;
1685             dst += 2;
1686             src += 2;
1687         }
1688
1689         if (w)
1690         {
1691             __m64 s = load8888 (src);
1692             __m64 d = load8888 (dst);
1693
1694             store8888 (dst, in_over (s, expand_alpha (s), vmask, d));
1695         }
1696     }
1697
1698     _mm_empty ();
1699 }
1700
1701 static void
1702 mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp,
1703                                 pixman_composite_info_t *info)
1704 {
1705     PIXMAN_COMPOSITE_ARGS (info);
1706     uint32_t *dst_line, *dst;
1707     uint32_t *src_line, *src;
1708     uint32_t mask;
1709     __m64 vmask;
1710     int dst_stride, src_stride;
1711     int32_t w;
1712     __m64 srca;
1713
1714     CHECKPOINT ();
1715
1716     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1717     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1718     mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format);
1719
1720     vmask = expand_alpha (load8888 (&mask));
1721     srca = MC (4x00ff);
1722
1723     while (height--)
1724     {
1725         dst = dst_line;
1726         dst_line += dst_stride;
1727         src = src_line;
1728         src_line += src_stride;
1729         w = width;
1730
1731         while (w && (uintptr_t)dst & 7)
1732         {
1733             uint32_t ssrc = *src | 0xff000000;
1734             __m64 s = load8888 (&ssrc);
1735             __m64 d = load8888 (dst);
1736
1737             store8888 (dst, in_over (s, srca, vmask, d));
1738
1739             w--;
1740             dst++;
1741             src++;
1742         }
1743
1744         while (w >= 16)
1745         {
1746             __m64 vd0 = *(__m64 *)(dst + 0);
1747             __m64 vd1 = *(__m64 *)(dst + 2);
1748             __m64 vd2 = *(__m64 *)(dst + 4);
1749             __m64 vd3 = *(__m64 *)(dst + 6);
1750             __m64 vd4 = *(__m64 *)(dst + 8);
1751             __m64 vd5 = *(__m64 *)(dst + 10);
1752             __m64 vd6 = *(__m64 *)(dst + 12);
1753             __m64 vd7 = *(__m64 *)(dst + 14);
1754
1755             __m64 vs0 = ldq_u ((__m64 *)(src + 0));
1756             __m64 vs1 = ldq_u ((__m64 *)(src + 2));
1757             __m64 vs2 = ldq_u ((__m64 *)(src + 4));
1758             __m64 vs3 = ldq_u ((__m64 *)(src + 6));
1759             __m64 vs4 = ldq_u ((__m64 *)(src + 8));
1760             __m64 vs5 = ldq_u ((__m64 *)(src + 10));
1761             __m64 vs6 = ldq_u ((__m64 *)(src + 12));
1762             __m64 vs7 = ldq_u ((__m64 *)(src + 14));
1763
1764             vd0 = pack8888 (
1765                 in_over (expandx888 (vs0, 0), srca, vmask, expand8888 (vd0, 0)),
1766                 in_over (expandx888 (vs0, 1), srca, vmask, expand8888 (vd0, 1)));
1767
1768             vd1 = pack8888 (
1769                 in_over (expandx888 (vs1, 0), srca, vmask, expand8888 (vd1, 0)),
1770                 in_over (expandx888 (vs1, 1), srca, vmask, expand8888 (vd1, 1)));
1771
1772             vd2 = pack8888 (
1773                 in_over (expandx888 (vs2, 0), srca, vmask, expand8888 (vd2, 0)),
1774                 in_over (expandx888 (vs2, 1), srca, vmask, expand8888 (vd2, 1)));
1775
1776             vd3 = pack8888 (
1777                 in_over (expandx888 (vs3, 0), srca, vmask, expand8888 (vd3, 0)),
1778                 in_over (expandx888 (vs3, 1), srca, vmask, expand8888 (vd3, 1)));
1779
1780             vd4 = pack8888 (
1781                 in_over (expandx888 (vs4, 0), srca, vmask, expand8888 (vd4, 0)),
1782                 in_over (expandx888 (vs4, 1), srca, vmask, expand8888 (vd4, 1)));
1783
1784             vd5 = pack8888 (
1785                 in_over (expandx888 (vs5, 0), srca, vmask, expand8888 (vd5, 0)),
1786                 in_over (expandx888 (vs5, 1), srca, vmask, expand8888 (vd5, 1)));
1787
1788             vd6 = pack8888 (
1789                 in_over (expandx888 (vs6, 0), srca, vmask, expand8888 (vd6, 0)),
1790                 in_over (expandx888 (vs6, 1), srca, vmask, expand8888 (vd6, 1)));
1791
1792             vd7 = pack8888 (
1793                 in_over (expandx888 (vs7, 0), srca, vmask, expand8888 (vd7, 0)),
1794                 in_over (expandx888 (vs7, 1), srca, vmask, expand8888 (vd7, 1)));
1795
1796             *(__m64 *)(dst + 0) = vd0;
1797             *(__m64 *)(dst + 2) = vd1;
1798             *(__m64 *)(dst + 4) = vd2;
1799             *(__m64 *)(dst + 6) = vd3;
1800             *(__m64 *)(dst + 8) = vd4;
1801             *(__m64 *)(dst + 10) = vd5;
1802             *(__m64 *)(dst + 12) = vd6;
1803             *(__m64 *)(dst + 14) = vd7;
1804
1805             w -= 16;
1806             dst += 16;
1807             src += 16;
1808         }
1809
1810         while (w)
1811         {
1812             uint32_t ssrc = *src | 0xff000000;
1813             __m64 s = load8888 (&ssrc);
1814             __m64 d = load8888 (dst);
1815
1816             store8888 (dst, in_over (s, srca, vmask, d));
1817
1818             w--;
1819             dst++;
1820             src++;
1821         }
1822     }
1823
1824     _mm_empty ();
1825 }
1826
1827 static void
1828 mmx_composite_over_8888_8888 (pixman_implementation_t *imp,
1829                               pixman_composite_info_t *info)
1830 {
1831     PIXMAN_COMPOSITE_ARGS (info);
1832     uint32_t *dst_line, *dst;
1833     uint32_t *src_line, *src;
1834     uint32_t s;
1835     int dst_stride, src_stride;
1836     uint8_t a;
1837     int32_t w;
1838
1839     CHECKPOINT ();
1840
1841     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1842     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1843
1844     while (height--)
1845     {
1846         dst = dst_line;
1847         dst_line += dst_stride;
1848         src = src_line;
1849         src_line += src_stride;
1850         w = width;
1851
1852         while (w--)
1853         {
1854             s = *src++;
1855             a = s >> 24;
1856
1857             if (a == 0xff)
1858             {
1859                 *dst = s;
1860             }
1861             else if (s)
1862             {
1863                 __m64 ms, sa;
1864                 ms = load8888 (&s);
1865                 sa = expand_alpha (ms);
1866                 store8888 (dst, over (ms, sa, load8888 (dst)));
1867             }
1868
1869             dst++;
1870         }
1871     }
1872     _mm_empty ();
1873 }
1874
1875 static void
1876 mmx_composite_over_8888_0565 (pixman_implementation_t *imp,
1877                               pixman_composite_info_t *info)
1878 {
1879     PIXMAN_COMPOSITE_ARGS (info);
1880     uint16_t    *dst_line, *dst;
1881     uint32_t    *src_line, *src;
1882     int dst_stride, src_stride;
1883     int32_t w;
1884
1885     CHECKPOINT ();
1886
1887     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1888     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1889
1890 #if 0
1891     /* FIXME */
1892     assert (src_image->drawable == mask_image->drawable);
1893 #endif
1894
1895     while (height--)
1896     {
1897         dst = dst_line;
1898         dst_line += dst_stride;
1899         src = src_line;
1900         src_line += src_stride;
1901         w = width;
1902
1903         CHECKPOINT ();
1904
1905         while (w && (uintptr_t)dst & 7)
1906         {
1907             __m64 vsrc = load8888 (src);
1908             uint64_t d = *dst;
1909             __m64 vdest = expand565 (to_m64 (d), 0);
1910
1911             vdest = pack_565 (
1912                 over (vsrc, expand_alpha (vsrc), vdest), vdest, 0);
1913
1914             *dst = to_uint64 (vdest);
1915
1916             w--;
1917             dst++;
1918             src++;
1919         }
1920
1921         CHECKPOINT ();
1922
1923         while (w >= 4)
1924         {
1925             __m64 vdest = *(__m64 *)dst;
1926             __m64 v0, v1, v2, v3;
1927             __m64 vsrc0, vsrc1, vsrc2, vsrc3;
1928
1929             expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0);
1930
1931             vsrc0 = load8888 ((src + 0));
1932             vsrc1 = load8888 ((src + 1));
1933             vsrc2 = load8888 ((src + 2));
1934             vsrc3 = load8888 ((src + 3));
1935
1936             v0 = over (vsrc0, expand_alpha (vsrc0), v0);
1937             v1 = over (vsrc1, expand_alpha (vsrc1), v1);
1938             v2 = over (vsrc2, expand_alpha (vsrc2), v2);
1939             v3 = over (vsrc3, expand_alpha (vsrc3), v3);
1940
1941             *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3);
1942
1943             w -= 4;
1944             dst += 4;
1945             src += 4;
1946         }
1947
1948         CHECKPOINT ();
1949
1950         while (w)
1951         {
1952             __m64 vsrc = load8888 (src);
1953             uint64_t d = *dst;
1954             __m64 vdest = expand565 (to_m64 (d), 0);
1955
1956             vdest = pack_565 (over (vsrc, expand_alpha (vsrc), vdest), vdest, 0);
1957
1958             *dst = to_uint64 (vdest);
1959
1960             w--;
1961             dst++;
1962             src++;
1963         }
1964     }
1965
1966     _mm_empty ();
1967 }
1968
1969 static void
1970 mmx_composite_over_n_8_8888 (pixman_implementation_t *imp,
1971                              pixman_composite_info_t *info)
1972 {
1973     PIXMAN_COMPOSITE_ARGS (info);
1974     uint32_t src, srca;
1975     uint32_t *dst_line, *dst;
1976     uint8_t *mask_line, *mask;
1977     int dst_stride, mask_stride;
1978     int32_t w;
1979     __m64 vsrc, vsrca;
1980     uint64_t srcsrc;
1981
1982     CHECKPOINT ();
1983
1984     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1985
1986     srca = src >> 24;
1987     if (src == 0)
1988         return;
1989
1990     srcsrc = (uint64_t)src << 32 | src;
1991
1992     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1993     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
1994
1995     vsrc = load8888 (&src);
1996     vsrca = expand_alpha (vsrc);
1997
1998     while (height--)
1999     {
2000         dst = dst_line;
2001         dst_line += dst_stride;
2002         mask = mask_line;
2003         mask_line += mask_stride;
2004         w = width;
2005
2006         CHECKPOINT ();
2007
2008         while (w && (uintptr_t)dst & 7)
2009         {
2010             uint64_t m = *mask;
2011
2012             if (m)
2013             {
2014                 __m64 vdest = in_over (vsrc, vsrca,
2015                                        expand_alpha_rev (to_m64 (m)),
2016                                        load8888 (dst));
2017
2018                 store8888 (dst, vdest);
2019             }
2020
2021             w--;
2022             mask++;
2023             dst++;
2024         }
2025
2026         CHECKPOINT ();
2027
2028         while (w >= 2)
2029         {
2030             uint64_t m0, m1;
2031
2032             m0 = *mask;
2033             m1 = *(mask + 1);
2034
2035             if (srca == 0xff && (m0 & m1) == 0xff)
2036             {
2037                 *(uint64_t *)dst = srcsrc;
2038             }
2039             else if (m0 | m1)
2040             {
2041                 __m64 vdest;
2042                 __m64 dest0, dest1;
2043
2044                 vdest = *(__m64 *)dst;
2045
2046                 dest0 = in_over (vsrc, vsrca, expand_alpha_rev (to_m64 (m0)),
2047                                  expand8888 (vdest, 0));
2048                 dest1 = in_over (vsrc, vsrca, expand_alpha_rev (to_m64 (m1)),
2049                                  expand8888 (vdest, 1));
2050
2051                 *(__m64 *)dst = pack8888 (dest0, dest1);
2052             }
2053
2054             mask += 2;
2055             dst += 2;
2056             w -= 2;
2057         }
2058
2059         CHECKPOINT ();
2060
2061         if (w)
2062         {
2063             uint64_t m = *mask;
2064
2065             if (m)
2066             {
2067                 __m64 vdest = load8888 (dst);
2068
2069                 vdest = in_over (
2070                     vsrc, vsrca, expand_alpha_rev (to_m64 (m)), vdest);
2071                 store8888 (dst, vdest);
2072             }
2073         }
2074     }
2075
2076     _mm_empty ();
2077 }
2078
2079 static pixman_bool_t
2080 mmx_fill (pixman_implementation_t *imp,
2081           uint32_t *               bits,
2082           int                      stride,
2083           int                      bpp,
2084           int                      x,
2085           int                      y,
2086           int                      width,
2087           int                      height,
2088           uint32_t                 filler)
2089 {
2090     uint64_t fill;
2091     __m64 vfill;
2092     uint32_t byte_width;
2093     uint8_t     *byte_line;
2094
2095 #if defined __GNUC__ && defined USE_X86_MMX
2096     __m64 v1, v2, v3, v4, v5, v6, v7;
2097 #endif
2098
2099     if (bpp != 16 && bpp != 32 && bpp != 8)
2100         return FALSE;
2101
2102     if (bpp == 8)
2103     {
2104         stride = stride * (int) sizeof (uint32_t) / 1;
2105         byte_line = (uint8_t *)(((uint8_t *)bits) + stride * y + x);
2106         byte_width = width;
2107         stride *= 1;
2108         filler = (filler & 0xff) * 0x01010101;
2109     }
2110     else if (bpp == 16)
2111     {
2112         stride = stride * (int) sizeof (uint32_t) / 2;
2113         byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x);
2114         byte_width = 2 * width;
2115         stride *= 2;
2116         filler = (filler & 0xffff) * 0x00010001;
2117     }
2118     else
2119     {
2120         stride = stride * (int) sizeof (uint32_t) / 4;
2121         byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x);
2122         byte_width = 4 * width;
2123         stride *= 4;
2124     }
2125
2126     fill = ((uint64_t)filler << 32) | filler;
2127     vfill = to_m64 (fill);
2128
2129 #if defined __GNUC__ && defined USE_X86_MMX
2130     __asm__ (
2131         "movq           %7,     %0\n"
2132         "movq           %7,     %1\n"
2133         "movq           %7,     %2\n"
2134         "movq           %7,     %3\n"
2135         "movq           %7,     %4\n"
2136         "movq           %7,     %5\n"
2137         "movq           %7,     %6\n"
2138         : "=&y" (v1), "=&y" (v2), "=&y" (v3),
2139           "=&y" (v4), "=&y" (v5), "=&y" (v6), "=y" (v7)
2140         : "y" (vfill));
2141 #endif
2142
2143     while (height--)
2144     {
2145         int w;
2146         uint8_t *d = byte_line;
2147
2148         byte_line += stride;
2149         w = byte_width;
2150
2151         if (w >= 1 && ((uintptr_t)d & 1))
2152         {
2153             *(uint8_t *)d = (filler & 0xff);
2154             w--;
2155             d++;
2156         }
2157
2158         if (w >= 2 && ((uintptr_t)d & 3))
2159         {
2160             *(uint16_t *)d = filler;
2161             w -= 2;
2162             d += 2;
2163         }
2164
2165         while (w >= 4 && ((uintptr_t)d & 7))
2166         {
2167             *(uint32_t *)d = filler;
2168
2169             w -= 4;
2170             d += 4;
2171         }
2172
2173         while (w >= 64)
2174         {
2175 #if defined __GNUC__ && defined USE_X86_MMX
2176             __asm__ (
2177                 "movq   %1,       (%0)\n"
2178                 "movq   %2,      8(%0)\n"
2179                 "movq   %3,     16(%0)\n"
2180                 "movq   %4,     24(%0)\n"
2181                 "movq   %5,     32(%0)\n"
2182                 "movq   %6,     40(%0)\n"
2183                 "movq   %7,     48(%0)\n"
2184                 "movq   %8,     56(%0)\n"
2185                 :
2186                 : "r" (d),
2187                   "y" (vfill), "y" (v1), "y" (v2), "y" (v3),
2188                   "y" (v4), "y" (v5), "y" (v6), "y" (v7)
2189                 : "memory");
2190 #else
2191             *(__m64*) (d +  0) = vfill;
2192             *(__m64*) (d +  8) = vfill;
2193             *(__m64*) (d + 16) = vfill;
2194             *(__m64*) (d + 24) = vfill;
2195             *(__m64*) (d + 32) = vfill;
2196             *(__m64*) (d + 40) = vfill;
2197             *(__m64*) (d + 48) = vfill;
2198             *(__m64*) (d + 56) = vfill;
2199 #endif
2200             w -= 64;
2201             d += 64;
2202         }
2203
2204         while (w >= 4)
2205         {
2206             *(uint32_t *)d = filler;
2207
2208             w -= 4;
2209             d += 4;
2210         }
2211         if (w >= 2)
2212         {
2213             *(uint16_t *)d = filler;
2214             w -= 2;
2215             d += 2;
2216         }
2217         if (w >= 1)
2218         {
2219             *(uint8_t *)d = (filler & 0xff);
2220             w--;
2221             d++;
2222         }
2223
2224     }
2225
2226     _mm_empty ();
2227     return TRUE;
2228 }
2229
2230 static void
2231 mmx_composite_src_x888_0565 (pixman_implementation_t *imp,
2232                              pixman_composite_info_t *info)
2233 {
2234     PIXMAN_COMPOSITE_ARGS (info);
2235     uint16_t    *dst_line, *dst;
2236     uint32_t    *src_line, *src, s;
2237     int dst_stride, src_stride;
2238     int32_t w;
2239
2240     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2241     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2242
2243     while (height--)
2244     {
2245         dst = dst_line;
2246         dst_line += dst_stride;
2247         src = src_line;
2248         src_line += src_stride;
2249         w = width;
2250
2251         while (w && (uintptr_t)dst & 7)
2252         {
2253             s = *src++;
2254             *dst = convert_8888_to_0565 (s);
2255             dst++;
2256             w--;
2257         }
2258
2259         while (w >= 4)
2260         {
2261             __m64 vdest;
2262             __m64 vsrc0 = ldq_u ((__m64 *)(src + 0));
2263             __m64 vsrc1 = ldq_u ((__m64 *)(src + 2));
2264
2265             vdest = pack_4xpacked565 (vsrc0, vsrc1);
2266
2267             *(__m64 *)dst = vdest;
2268
2269             w -= 4;
2270             src += 4;
2271             dst += 4;
2272         }
2273
2274         while (w)
2275         {
2276             s = *src++;
2277             *dst = convert_8888_to_0565 (s);
2278             dst++;
2279             w--;
2280         }
2281     }
2282
2283     _mm_empty ();
2284 }
2285
2286 static void
2287 mmx_composite_src_n_8_8888 (pixman_implementation_t *imp,
2288                             pixman_composite_info_t *info)
2289 {
2290     PIXMAN_COMPOSITE_ARGS (info);
2291     uint32_t src, srca;
2292     uint32_t    *dst_line, *dst;
2293     uint8_t     *mask_line, *mask;
2294     int dst_stride, mask_stride;
2295     int32_t w;
2296     __m64 vsrc;
2297     uint64_t srcsrc;
2298
2299     CHECKPOINT ();
2300
2301     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2302
2303     srca = src >> 24;
2304     if (src == 0)
2305     {
2306         mmx_fill (imp, dest_image->bits.bits, dest_image->bits.rowstride,
2307                   PIXMAN_FORMAT_BPP (dest_image->bits.format),
2308                   dest_x, dest_y, width, height, 0);
2309         return;
2310     }
2311
2312     srcsrc = (uint64_t)src << 32 | src;
2313
2314     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
2315     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2316
2317     vsrc = load8888 (&src);
2318
2319     while (height--)
2320     {
2321         dst = dst_line;
2322         dst_line += dst_stride;
2323         mask = mask_line;
2324         mask_line += mask_stride;
2325         w = width;
2326
2327         CHECKPOINT ();
2328
2329         while (w && (uintptr_t)dst & 7)
2330         {
2331             uint64_t m = *mask;
2332
2333             if (m)
2334             {
2335                 __m64 vdest = in (vsrc, expand_alpha_rev (to_m64 (m)));
2336
2337                 store8888 (dst, vdest);
2338             }
2339             else
2340             {
2341                 *dst = 0;
2342             }
2343
2344             w--;
2345             mask++;
2346             dst++;
2347         }
2348
2349         CHECKPOINT ();
2350
2351         while (w >= 2)
2352         {
2353             uint64_t m0, m1;
2354             m0 = *mask;
2355             m1 = *(mask + 1);
2356
2357             if (srca == 0xff && (m0 & m1) == 0xff)
2358             {
2359                 *(uint64_t *)dst = srcsrc;
2360             }
2361             else if (m0 | m1)
2362             {
2363                 __m64 dest0, dest1;
2364
2365                 dest0 = in (vsrc, expand_alpha_rev (to_m64 (m0)));
2366                 dest1 = in (vsrc, expand_alpha_rev (to_m64 (m1)));
2367
2368                 *(__m64 *)dst = pack8888 (dest0, dest1);
2369             }
2370             else
2371             {
2372                 *(uint64_t *)dst = 0;
2373             }
2374
2375             mask += 2;
2376             dst += 2;
2377             w -= 2;
2378         }
2379
2380         CHECKPOINT ();
2381
2382         if (w)
2383         {
2384             uint64_t m = *mask;
2385
2386             if (m)
2387             {
2388                 __m64 vdest = load8888 (dst);
2389
2390                 vdest = in (vsrc, expand_alpha_rev (to_m64 (m)));
2391                 store8888 (dst, vdest);
2392             }
2393             else
2394             {
2395                 *dst = 0;
2396             }
2397         }
2398     }
2399
2400     _mm_empty ();
2401 }
2402
2403 static void
2404 mmx_composite_over_n_8_0565 (pixman_implementation_t *imp,
2405                              pixman_composite_info_t *info)
2406 {
2407     PIXMAN_COMPOSITE_ARGS (info);
2408     uint32_t src, srca;
2409     uint16_t *dst_line, *dst;
2410     uint8_t *mask_line, *mask;
2411     int dst_stride, mask_stride;
2412     int32_t w;
2413     __m64 vsrc, vsrca, tmp;
2414     __m64 srcsrcsrcsrc;
2415
2416     CHECKPOINT ();
2417
2418     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2419
2420     srca = src >> 24;
2421     if (src == 0)
2422         return;
2423
2424     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2425     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2426
2427     vsrc = load8888 (&src);
2428     vsrca = expand_alpha (vsrc);
2429
2430     tmp = pack_565 (vsrc, _mm_setzero_si64 (), 0);
2431     srcsrcsrcsrc = expand_alpha_rev (tmp);
2432
2433     while (height--)
2434     {
2435         dst = dst_line;
2436         dst_line += dst_stride;
2437         mask = mask_line;
2438         mask_line += mask_stride;
2439         w = width;
2440
2441         CHECKPOINT ();
2442
2443         while (w && (uintptr_t)dst & 7)
2444         {
2445             uint64_t m = *mask;
2446
2447             if (m)
2448             {
2449                 uint64_t d = *dst;
2450                 __m64 vd = to_m64 (d);
2451                 __m64 vdest = in_over (
2452                     vsrc, vsrca, expand_alpha_rev (to_m64 (m)), expand565 (vd, 0));
2453
2454                 vd = pack_565 (vdest, _mm_setzero_si64 (), 0);
2455                 *dst = to_uint64 (vd);
2456             }
2457
2458             w--;
2459             mask++;
2460             dst++;
2461         }
2462
2463         CHECKPOINT ();
2464
2465         while (w >= 4)
2466         {
2467             uint64_t m0, m1, m2, m3;
2468             m0 = *mask;
2469             m1 = *(mask + 1);
2470             m2 = *(mask + 2);
2471             m3 = *(mask + 3);
2472
2473             if (srca == 0xff && (m0 & m1 & m2 & m3) == 0xff)
2474             {
2475                 *(__m64 *)dst = srcsrcsrcsrc;
2476             }
2477             else if (m0 | m1 | m2 | m3)
2478             {
2479                 __m64 vdest = *(__m64 *)dst;
2480                 __m64 v0, v1, v2, v3;
2481                 __m64 vm0, vm1, vm2, vm3;
2482
2483                 expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0);
2484
2485                 vm0 = to_m64 (m0);
2486                 v0 = in_over (vsrc, vsrca, expand_alpha_rev (vm0), v0);
2487
2488                 vm1 = to_m64 (m1);
2489                 v1 = in_over (vsrc, vsrca, expand_alpha_rev (vm1), v1);
2490
2491                 vm2 = to_m64 (m2);
2492                 v2 = in_over (vsrc, vsrca, expand_alpha_rev (vm2), v2);
2493
2494                 vm3 = to_m64 (m3);
2495                 v3 = in_over (vsrc, vsrca, expand_alpha_rev (vm3), v3);
2496
2497                 *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3);;
2498             }
2499
2500             w -= 4;
2501             mask += 4;
2502             dst += 4;
2503         }
2504
2505         CHECKPOINT ();
2506
2507         while (w)
2508         {
2509             uint64_t m = *mask;
2510
2511             if (m)
2512             {
2513                 uint64_t d = *dst;
2514                 __m64 vd = to_m64 (d);
2515                 __m64 vdest = in_over (vsrc, vsrca, expand_alpha_rev (to_m64 (m)),
2516                                        expand565 (vd, 0));
2517                 vd = pack_565 (vdest, _mm_setzero_si64 (), 0);
2518                 *dst = to_uint64 (vd);
2519             }
2520
2521             w--;
2522             mask++;
2523             dst++;
2524         }
2525     }
2526
2527     _mm_empty ();
2528 }
2529
2530 static void
2531 mmx_composite_over_pixbuf_0565 (pixman_implementation_t *imp,
2532                                 pixman_composite_info_t *info)
2533 {
2534     PIXMAN_COMPOSITE_ARGS (info);
2535     uint16_t    *dst_line, *dst;
2536     uint32_t    *src_line, *src;
2537     int dst_stride, src_stride;
2538     int32_t w;
2539
2540     CHECKPOINT ();
2541
2542     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2543     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2544
2545 #if 0
2546     /* FIXME */
2547     assert (src_image->drawable == mask_image->drawable);
2548 #endif
2549
2550     while (height--)
2551     {
2552         dst = dst_line;
2553         dst_line += dst_stride;
2554         src = src_line;
2555         src_line += src_stride;
2556         w = width;
2557
2558         CHECKPOINT ();
2559
2560         while (w && (uintptr_t)dst & 7)
2561         {
2562             __m64 vsrc = load8888 (src);
2563             uint64_t d = *dst;
2564             __m64 vdest = expand565 (to_m64 (d), 0);
2565
2566             vdest = pack_565 (over_rev_non_pre (vsrc, vdest), vdest, 0);
2567
2568             *dst = to_uint64 (vdest);
2569
2570             w--;
2571             dst++;
2572             src++;
2573         }
2574
2575         CHECKPOINT ();
2576
2577         while (w >= 4)
2578         {
2579             uint32_t s0, s1, s2, s3;
2580             unsigned char a0, a1, a2, a3;
2581
2582             s0 = *src;
2583             s1 = *(src + 1);
2584             s2 = *(src + 2);
2585             s3 = *(src + 3);
2586
2587             a0 = (s0 >> 24);
2588             a1 = (s1 >> 24);
2589             a2 = (s2 >> 24);
2590             a3 = (s3 >> 24);
2591
2592             if ((a0 & a1 & a2 & a3) == 0xFF)
2593             {
2594                 __m64 v0 = invert_colors (load8888 (&s0));
2595                 __m64 v1 = invert_colors (load8888 (&s1));
2596                 __m64 v2 = invert_colors (load8888 (&s2));
2597                 __m64 v3 = invert_colors (load8888 (&s3));
2598
2599                 *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3);
2600             }
2601             else if (s0 | s1 | s2 | s3)
2602             {
2603                 __m64 vdest = *(__m64 *)dst;
2604                 __m64 v0, v1, v2, v3;
2605
2606                 __m64 vsrc0 = load8888 (&s0);
2607                 __m64 vsrc1 = load8888 (&s1);
2608                 __m64 vsrc2 = load8888 (&s2);
2609                 __m64 vsrc3 = load8888 (&s3);
2610
2611                 expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0);
2612
2613                 v0 = over_rev_non_pre (vsrc0, v0);
2614                 v1 = over_rev_non_pre (vsrc1, v1);
2615                 v2 = over_rev_non_pre (vsrc2, v2);
2616                 v3 = over_rev_non_pre (vsrc3, v3);
2617
2618                 *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3);
2619             }
2620
2621             w -= 4;
2622             dst += 4;
2623             src += 4;
2624         }
2625
2626         CHECKPOINT ();
2627
2628         while (w)
2629         {
2630             __m64 vsrc = load8888 (src);
2631             uint64_t d = *dst;
2632             __m64 vdest = expand565 (to_m64 (d), 0);
2633
2634             vdest = pack_565 (over_rev_non_pre (vsrc, vdest), vdest, 0);
2635
2636             *dst = to_uint64 (vdest);
2637
2638             w--;
2639             dst++;
2640             src++;
2641         }
2642     }
2643
2644     _mm_empty ();
2645 }
2646
2647 static void
2648 mmx_composite_over_pixbuf_8888 (pixman_implementation_t *imp,
2649                                 pixman_composite_info_t *info)
2650 {
2651     PIXMAN_COMPOSITE_ARGS (info);
2652     uint32_t    *dst_line, *dst;
2653     uint32_t    *src_line, *src;
2654     int dst_stride, src_stride;
2655     int32_t w;
2656
2657     CHECKPOINT ();
2658
2659     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
2660     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2661
2662 #if 0
2663     /* FIXME */
2664     assert (src_image->drawable == mask_image->drawable);
2665 #endif
2666
2667     while (height--)
2668     {
2669         dst = dst_line;
2670         dst_line += dst_stride;
2671         src = src_line;
2672         src_line += src_stride;
2673         w = width;
2674
2675         while (w && (uintptr_t)dst & 7)
2676         {
2677             __m64 s = load8888 (src);
2678             __m64 d = load8888 (dst);
2679
2680             store8888 (dst, over_rev_non_pre (s, d));
2681
2682             w--;
2683             dst++;
2684             src++;
2685         }
2686
2687         while (w >= 2)
2688         {
2689             uint32_t s0, s1;
2690             unsigned char a0, a1;
2691             __m64 d0, d1;
2692
2693             s0 = *src;
2694             s1 = *(src + 1);
2695
2696             a0 = (s0 >> 24);
2697             a1 = (s1 >> 24);
2698
2699             if ((a0 & a1) == 0xFF)
2700             {
2701                 d0 = invert_colors (load8888 (&s0));
2702                 d1 = invert_colors (load8888 (&s1));
2703
2704                 *(__m64 *)dst = pack8888 (d0, d1);
2705             }
2706             else if (s0 | s1)
2707             {
2708                 __m64 vdest = *(__m64 *)dst;
2709
2710                 d0 = over_rev_non_pre (load8888 (&s0), expand8888 (vdest, 0));
2711                 d1 = over_rev_non_pre (load8888 (&s1), expand8888 (vdest, 1));
2712
2713                 *(__m64 *)dst = pack8888 (d0, d1);
2714             }
2715
2716             w -= 2;
2717             dst += 2;
2718             src += 2;
2719         }
2720
2721         if (w)
2722         {
2723             __m64 s = load8888 (src);
2724             __m64 d = load8888 (dst);
2725
2726             store8888 (dst, over_rev_non_pre (s, d));
2727         }
2728     }
2729
2730     _mm_empty ();
2731 }
2732
2733 static void
2734 mmx_composite_over_n_8888_0565_ca (pixman_implementation_t *imp,
2735                                    pixman_composite_info_t *info)
2736 {
2737     PIXMAN_COMPOSITE_ARGS (info);
2738     uint32_t src;
2739     uint16_t    *dst_line;
2740     uint32_t    *mask_line;
2741     int dst_stride, mask_stride;
2742     __m64 vsrc, vsrca;
2743
2744     CHECKPOINT ();
2745
2746     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2747
2748     if (src == 0)
2749         return;
2750
2751     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2752     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
2753
2754     vsrc = load8888 (&src);
2755     vsrca = expand_alpha (vsrc);
2756
2757     while (height--)
2758     {
2759         int twidth = width;
2760         uint32_t *p = (uint32_t *)mask_line;
2761         uint16_t *q = (uint16_t *)dst_line;
2762
2763         while (twidth && ((uintptr_t)q & 7))
2764         {
2765             uint32_t m = *(uint32_t *)p;
2766
2767             if (m)
2768             {
2769                 uint64_t d = *q;
2770                 __m64 vdest = expand565 (to_m64 (d), 0);
2771                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m), vdest), vdest, 0);
2772                 *q = to_uint64 (vdest);
2773             }
2774
2775             twidth--;
2776             p++;
2777             q++;
2778         }
2779
2780         while (twidth >= 4)
2781         {
2782             uint32_t m0, m1, m2, m3;
2783
2784             m0 = *p;
2785             m1 = *(p + 1);
2786             m2 = *(p + 2);
2787             m3 = *(p + 3);
2788
2789             if ((m0 | m1 | m2 | m3))
2790             {
2791                 __m64 vdest = *(__m64 *)q;
2792                 __m64 v0, v1, v2, v3;
2793
2794                 expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0);
2795
2796                 v0 = in_over (vsrc, vsrca, load8888 (&m0), v0);
2797                 v1 = in_over (vsrc, vsrca, load8888 (&m1), v1);
2798                 v2 = in_over (vsrc, vsrca, load8888 (&m2), v2);
2799                 v3 = in_over (vsrc, vsrca, load8888 (&m3), v3);
2800
2801                 *(__m64 *)q = pack_4x565 (v0, v1, v2, v3);
2802             }
2803             twidth -= 4;
2804             p += 4;
2805             q += 4;
2806         }
2807
2808         while (twidth)
2809         {
2810             uint32_t m;
2811
2812             m = *(uint32_t *)p;
2813             if (m)
2814             {
2815                 uint64_t d = *q;
2816                 __m64 vdest = expand565 (to_m64 (d), 0);
2817                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m), vdest), vdest, 0);
2818                 *q = to_uint64 (vdest);
2819             }
2820
2821             twidth--;
2822             p++;
2823             q++;
2824         }
2825
2826         mask_line += mask_stride;
2827         dst_line += dst_stride;
2828     }
2829
2830     _mm_empty ();
2831 }
2832
2833 static void
2834 mmx_composite_in_n_8_8 (pixman_implementation_t *imp,
2835                         pixman_composite_info_t *info)
2836 {
2837     PIXMAN_COMPOSITE_ARGS (info);
2838     uint8_t *dst_line, *dst;
2839     uint8_t *mask_line, *mask;
2840     int dst_stride, mask_stride;
2841     int32_t w;
2842     uint32_t src;
2843     uint8_t sa;
2844     __m64 vsrc, vsrca;
2845
2846     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2847     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2848
2849     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2850
2851     sa = src >> 24;
2852
2853     vsrc = load8888 (&src);
2854     vsrca = expand_alpha (vsrc);
2855
2856     while (height--)
2857     {
2858         dst = dst_line;
2859         dst_line += dst_stride;
2860         mask = mask_line;
2861         mask_line += mask_stride;
2862         w = width;
2863
2864         while (w && (uintptr_t)dst & 7)
2865         {
2866             uint16_t tmp;
2867             uint8_t a;
2868             uint32_t m, d;
2869
2870             a = *mask++;
2871             d = *dst;
2872
2873             m = MUL_UN8 (sa, a, tmp);
2874             d = MUL_UN8 (m, d, tmp);
2875
2876             *dst++ = d;
2877             w--;
2878         }
2879
2880         while (w >= 4)
2881         {
2882             __m64 vmask;
2883             __m64 vdest;
2884
2885             vmask = load8888u ((uint32_t *)mask);
2886             vdest = load8888 ((uint32_t *)dst);
2887
2888             store8888 ((uint32_t *)dst, in (in (vsrca, vmask), vdest));
2889
2890             dst += 4;
2891             mask += 4;
2892             w -= 4;
2893         }
2894
2895         while (w--)
2896         {
2897             uint16_t tmp;
2898             uint8_t a;
2899             uint32_t m, d;
2900
2901             a = *mask++;
2902             d = *dst;
2903
2904             m = MUL_UN8 (sa, a, tmp);
2905             d = MUL_UN8 (m, d, tmp);
2906
2907             *dst++ = d;
2908         }
2909     }
2910
2911     _mm_empty ();
2912 }
2913
2914 static void
2915 mmx_composite_in_8_8 (pixman_implementation_t *imp,
2916                       pixman_composite_info_t *info)
2917 {
2918     PIXMAN_COMPOSITE_ARGS (info);
2919     uint8_t     *dst_line, *dst;
2920     uint8_t     *src_line, *src;
2921     int src_stride, dst_stride;
2922     int32_t w;
2923
2924     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2925     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
2926
2927     while (height--)
2928     {
2929         dst = dst_line;
2930         dst_line += dst_stride;
2931         src = src_line;
2932         src_line += src_stride;
2933         w = width;
2934
2935         while (w && (uintptr_t)dst & 3)
2936         {
2937             uint8_t s, d;
2938             uint16_t tmp;
2939
2940             s = *src;
2941             d = *dst;
2942
2943             *dst = MUL_UN8 (s, d, tmp);
2944
2945             src++;
2946             dst++;
2947             w--;
2948         }
2949
2950         while (w >= 4)
2951         {
2952             uint32_t *s = (uint32_t *)src;
2953             uint32_t *d = (uint32_t *)dst;
2954
2955             store8888 (d, in (load8888u (s), load8888 (d)));
2956
2957             w -= 4;
2958             dst += 4;
2959             src += 4;
2960         }
2961
2962         while (w--)
2963         {
2964             uint8_t s, d;
2965             uint16_t tmp;
2966
2967             s = *src;
2968             d = *dst;
2969
2970             *dst = MUL_UN8 (s, d, tmp);
2971
2972             src++;
2973             dst++;
2974         }
2975     }
2976
2977     _mm_empty ();
2978 }
2979
2980 static void
2981 mmx_composite_add_n_8_8 (pixman_implementation_t *imp,
2982                          pixman_composite_info_t *info)
2983 {
2984     PIXMAN_COMPOSITE_ARGS (info);
2985     uint8_t     *dst_line, *dst;
2986     uint8_t     *mask_line, *mask;
2987     int dst_stride, mask_stride;
2988     int32_t w;
2989     uint32_t src;
2990     uint8_t sa;
2991     __m64 vsrc, vsrca;
2992
2993     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2994     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2995
2996     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2997
2998     sa = src >> 24;
2999
3000     if (src == 0)
3001         return;
3002
3003     vsrc = load8888 (&src);
3004     vsrca = expand_alpha (vsrc);
3005
3006     while (height--)
3007     {
3008         dst = dst_line;
3009         dst_line += dst_stride;
3010         mask = mask_line;
3011         mask_line += mask_stride;
3012         w = width;
3013
3014         while (w && (uintptr_t)dst & 3)
3015         {
3016             uint16_t tmp;
3017             uint16_t a;
3018             uint32_t m, d;
3019             uint32_t r;
3020
3021             a = *mask++;
3022             d = *dst;
3023
3024             m = MUL_UN8 (sa, a, tmp);
3025             r = ADD_UN8 (m, d, tmp);
3026
3027             *dst++ = r;
3028             w--;
3029         }
3030
3031         while (w >= 4)
3032         {
3033             __m64 vmask;
3034             __m64 vdest;
3035
3036             vmask = load8888u ((uint32_t *)mask);
3037             vdest = load8888 ((uint32_t *)dst);
3038
3039             store8888 ((uint32_t *)dst, _mm_adds_pu8 (in (vsrca, vmask), vdest));
3040
3041             dst += 4;
3042             mask += 4;
3043             w -= 4;
3044         }
3045
3046         while (w--)
3047         {
3048             uint16_t tmp;
3049             uint16_t a;
3050             uint32_t m, d;
3051             uint32_t r;
3052
3053             a = *mask++;
3054             d = *dst;
3055
3056             m = MUL_UN8 (sa, a, tmp);
3057             r = ADD_UN8 (m, d, tmp);
3058
3059             *dst++ = r;
3060         }
3061     }
3062
3063     _mm_empty ();
3064 }
3065
3066 static void
3067 mmx_composite_add_8_8 (pixman_implementation_t *imp,
3068                        pixman_composite_info_t *info)
3069 {
3070     PIXMAN_COMPOSITE_ARGS (info);
3071     uint8_t *dst_line, *dst;
3072     uint8_t *src_line, *src;
3073     int dst_stride, src_stride;
3074     int32_t w;
3075     uint8_t s, d;
3076     uint16_t t;
3077
3078     CHECKPOINT ();
3079
3080     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
3081     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
3082
3083     while (height--)
3084     {
3085         dst = dst_line;
3086         dst_line += dst_stride;
3087         src = src_line;
3088         src_line += src_stride;
3089         w = width;
3090
3091         while (w && (uintptr_t)dst & 7)
3092         {
3093             s = *src;
3094             d = *dst;
3095             t = d + s;
3096             s = t | (0 - (t >> 8));
3097             *dst = s;
3098
3099             dst++;
3100             src++;
3101             w--;
3102         }
3103
3104         while (w >= 8)
3105         {
3106             *(__m64*)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst);
3107             dst += 8;
3108             src += 8;
3109             w -= 8;
3110         }
3111
3112         while (w)
3113         {
3114             s = *src;
3115             d = *dst;
3116             t = d + s;
3117             s = t | (0 - (t >> 8));
3118             *dst = s;
3119
3120             dst++;
3121             src++;
3122             w--;
3123         }
3124     }
3125
3126     _mm_empty ();
3127 }
3128
3129 static void
3130 mmx_composite_add_0565_0565 (pixman_implementation_t *imp,
3131                              pixman_composite_info_t *info)
3132 {
3133     PIXMAN_COMPOSITE_ARGS (info);
3134     uint16_t    *dst_line, *dst;
3135     uint32_t    d;
3136     uint16_t    *src_line, *src;
3137     uint32_t    s;
3138     int dst_stride, src_stride;
3139     int32_t w;
3140
3141     CHECKPOINT ();
3142
3143     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint16_t, src_stride, src_line, 1);
3144     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
3145
3146     while (height--)
3147     {
3148         dst = dst_line;
3149         dst_line += dst_stride;
3150         src = src_line;
3151         src_line += src_stride;
3152         w = width;
3153
3154         while (w && (uintptr_t)dst & 7)
3155         {
3156             s = *src++;
3157             if (s)
3158             {
3159                 d = *dst;
3160                 s = convert_0565_to_8888 (s);
3161                 if (d)
3162                 {
3163                     d = convert_0565_to_8888 (d);
3164                     UN8x4_ADD_UN8x4 (s, d);
3165                 }
3166                 *dst = convert_8888_to_0565 (s);
3167             }
3168             dst++;
3169             w--;
3170         }
3171
3172         while (w >= 4)
3173         {
3174             __m64 vdest = *(__m64 *)dst;
3175             __m64 vsrc = ldq_u ((__m64 *)src);
3176             __m64 vd0, vd1;
3177             __m64 vs0, vs1;
3178
3179             expand_4xpacked565 (vdest, &vd0, &vd1, 0);
3180             expand_4xpacked565 (vsrc, &vs0, &vs1, 0);
3181
3182             vd0 = _mm_adds_pu8 (vd0, vs0);
3183             vd1 = _mm_adds_pu8 (vd1, vs1);
3184
3185             *(__m64 *)dst = pack_4xpacked565 (vd0, vd1);
3186
3187             dst += 4;
3188             src += 4;
3189             w -= 4;
3190         }
3191
3192         while (w--)
3193         {
3194             s = *src++;
3195             if (s)
3196             {
3197                 d = *dst;
3198                 s = convert_0565_to_8888 (s);
3199                 if (d)
3200                 {
3201                     d = convert_0565_to_8888 (d);
3202                     UN8x4_ADD_UN8x4 (s, d);
3203                 }
3204                 *dst = convert_8888_to_0565 (s);
3205             }
3206             dst++;
3207         }
3208     }
3209
3210     _mm_empty ();
3211 }
3212
3213 static void
3214 mmx_composite_add_8888_8888 (pixman_implementation_t *imp,
3215                              pixman_composite_info_t *info)
3216 {
3217     PIXMAN_COMPOSITE_ARGS (info);
3218     uint32_t    *dst_line, *dst;
3219     uint32_t    *src_line, *src;
3220     int dst_stride, src_stride;
3221     int32_t w;
3222
3223     CHECKPOINT ();
3224
3225     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
3226     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
3227
3228     while (height--)
3229     {
3230         dst = dst_line;
3231         dst_line += dst_stride;
3232         src = src_line;
3233         src_line += src_stride;
3234         w = width;
3235
3236         while (w && (uintptr_t)dst & 7)
3237         {
3238             store (dst, _mm_adds_pu8 (load ((const uint32_t *)src),
3239                                       load ((const uint32_t *)dst)));
3240             dst++;
3241             src++;
3242             w--;
3243         }
3244
3245         while (w >= 2)
3246         {
3247             *(__m64 *)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst);
3248             dst += 2;
3249             src += 2;
3250             w -= 2;
3251         }
3252
3253         if (w)
3254         {
3255             store (dst, _mm_adds_pu8 (load ((const uint32_t *)src),
3256                                       load ((const uint32_t *)dst)));
3257
3258         }
3259     }
3260
3261     _mm_empty ();
3262 }
3263
3264 static pixman_bool_t
3265 mmx_blt (pixman_implementation_t *imp,
3266          uint32_t *               src_bits,
3267          uint32_t *               dst_bits,
3268          int                      src_stride,
3269          int                      dst_stride,
3270          int                      src_bpp,
3271          int                      dst_bpp,
3272          int                      src_x,
3273          int                      src_y,
3274          int                      dest_x,
3275          int                      dest_y,
3276          int                      width,
3277          int                      height)
3278 {
3279     uint8_t *   src_bytes;
3280     uint8_t *   dst_bytes;
3281     int byte_width;
3282
3283     if (src_bpp != dst_bpp)
3284         return FALSE;
3285
3286     if (src_bpp == 16)
3287     {
3288         src_stride = src_stride * (int) sizeof (uint32_t) / 2;
3289         dst_stride = dst_stride * (int) sizeof (uint32_t) / 2;
3290         src_bytes = (uint8_t *)(((uint16_t *)src_bits) + src_stride * (src_y) + (src_x));
3291         dst_bytes = (uint8_t *)(((uint16_t *)dst_bits) + dst_stride * (dest_y) + (dest_x));
3292         byte_width = 2 * width;
3293         src_stride *= 2;
3294         dst_stride *= 2;
3295     }
3296     else if (src_bpp == 32)
3297     {
3298         src_stride = src_stride * (int) sizeof (uint32_t) / 4;
3299         dst_stride = dst_stride * (int) sizeof (uint32_t) / 4;
3300         src_bytes = (uint8_t *)(((uint32_t *)src_bits) + src_stride * (src_y) + (src_x));
3301         dst_bytes = (uint8_t *)(((uint32_t *)dst_bits) + dst_stride * (dest_y) + (dest_x));
3302         byte_width = 4 * width;
3303         src_stride *= 4;
3304         dst_stride *= 4;
3305     }
3306     else
3307     {
3308         return FALSE;
3309     }
3310
3311     while (height--)
3312     {
3313         int w;
3314         uint8_t *s = src_bytes;
3315         uint8_t *d = dst_bytes;
3316         src_bytes += src_stride;
3317         dst_bytes += dst_stride;
3318         w = byte_width;
3319
3320         if (w >= 1 && ((uintptr_t)d & 1))
3321         {
3322             *(uint8_t *)d = *(uint8_t *)s;
3323             w -= 1;
3324             s += 1;
3325             d += 1;
3326         }
3327
3328         if (w >= 2 && ((uintptr_t)d & 3))
3329         {
3330             *(uint16_t *)d = *(uint16_t *)s;
3331             w -= 2;
3332             s += 2;
3333             d += 2;
3334         }
3335
3336         while (w >= 4 && ((uintptr_t)d & 7))
3337         {
3338             *(uint32_t *)d = ldl_u ((uint32_t *)s);
3339
3340             w -= 4;
3341             s += 4;
3342             d += 4;
3343         }
3344
3345         while (w >= 64)
3346         {
3347 #if (defined (__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))) && defined USE_X86_MMX
3348             __asm__ (
3349                 "movq     (%1),   %%mm0\n"
3350                 "movq    8(%1),   %%mm1\n"
3351                 "movq   16(%1),   %%mm2\n"
3352                 "movq   24(%1),   %%mm3\n"
3353                 "movq   32(%1),   %%mm4\n"
3354                 "movq   40(%1),   %%mm5\n"
3355                 "movq   48(%1),   %%mm6\n"
3356                 "movq   56(%1),   %%mm7\n"
3357
3358                 "movq   %%mm0,    (%0)\n"
3359                 "movq   %%mm1,   8(%0)\n"
3360                 "movq   %%mm2,  16(%0)\n"
3361                 "movq   %%mm3,  24(%0)\n"
3362                 "movq   %%mm4,  32(%0)\n"
3363                 "movq   %%mm5,  40(%0)\n"
3364                 "movq   %%mm6,  48(%0)\n"
3365                 "movq   %%mm7,  56(%0)\n"
3366                 :
3367                 : "r" (d), "r" (s)
3368                 : "memory",
3369                   "%mm0", "%mm1", "%mm2", "%mm3",
3370                   "%mm4", "%mm5", "%mm6", "%mm7");
3371 #else
3372             __m64 v0 = ldq_u ((__m64 *)(s + 0));
3373             __m64 v1 = ldq_u ((__m64 *)(s + 8));
3374             __m64 v2 = ldq_u ((__m64 *)(s + 16));
3375             __m64 v3 = ldq_u ((__m64 *)(s + 24));
3376             __m64 v4 = ldq_u ((__m64 *)(s + 32));
3377             __m64 v5 = ldq_u ((__m64 *)(s + 40));
3378             __m64 v6 = ldq_u ((__m64 *)(s + 48));
3379             __m64 v7 = ldq_u ((__m64 *)(s + 56));
3380             *(__m64 *)(d + 0)  = v0;
3381             *(__m64 *)(d + 8)  = v1;
3382             *(__m64 *)(d + 16) = v2;
3383             *(__m64 *)(d + 24) = v3;
3384             *(__m64 *)(d + 32) = v4;
3385             *(__m64 *)(d + 40) = v5;
3386             *(__m64 *)(d + 48) = v6;
3387             *(__m64 *)(d + 56) = v7;
3388 #endif
3389
3390             w -= 64;
3391             s += 64;
3392             d += 64;
3393         }
3394         while (w >= 4)
3395         {
3396             *(uint32_t *)d = ldl_u ((uint32_t *)s);
3397
3398             w -= 4;
3399             s += 4;
3400             d += 4;
3401         }
3402         if (w >= 2)
3403         {
3404             *(uint16_t *)d = *(uint16_t *)s;
3405             w -= 2;
3406             s += 2;
3407             d += 2;
3408         }
3409     }
3410
3411     _mm_empty ();
3412
3413     return TRUE;
3414 }
3415
3416 static void
3417 mmx_composite_copy_area (pixman_implementation_t *imp,
3418                          pixman_composite_info_t *info)
3419 {
3420     PIXMAN_COMPOSITE_ARGS (info);
3421
3422     mmx_blt (imp, src_image->bits.bits,
3423              dest_image->bits.bits,
3424              src_image->bits.rowstride,
3425              dest_image->bits.rowstride,
3426              PIXMAN_FORMAT_BPP (src_image->bits.format),
3427              PIXMAN_FORMAT_BPP (dest_image->bits.format),
3428              src_x, src_y, dest_x, dest_y, width, height);
3429 }
3430
3431 static void
3432 mmx_composite_over_x888_8_8888 (pixman_implementation_t *imp,
3433                                 pixman_composite_info_t *info)
3434 {
3435     PIXMAN_COMPOSITE_ARGS (info);
3436     uint32_t  *src, *src_line;
3437     uint32_t  *dst, *dst_line;
3438     uint8_t  *mask, *mask_line;
3439     int src_stride, mask_stride, dst_stride;
3440     int32_t w;
3441
3442     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
3443     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
3444     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
3445
3446     while (height--)
3447     {
3448         src = src_line;
3449         src_line += src_stride;
3450         dst = dst_line;
3451         dst_line += dst_stride;
3452         mask = mask_line;
3453         mask_line += mask_stride;
3454
3455         w = width;
3456
3457         while (w--)
3458         {
3459             uint64_t m = *mask;
3460
3461             if (m)
3462             {
3463                 uint32_t ssrc = *src | 0xff000000;
3464                 __m64 s = load8888 (&ssrc);
3465
3466                 if (m == 0xff)
3467                 {
3468                     store8888 (dst, s);
3469                 }
3470                 else
3471                 {
3472                     __m64 sa = expand_alpha (s);
3473                     __m64 vm = expand_alpha_rev (to_m64 (m));
3474                     __m64 vdest = in_over (s, sa, vm, load8888 (dst));
3475
3476                     store8888 (dst, vdest);
3477                 }
3478             }
3479
3480             mask++;
3481             dst++;
3482             src++;
3483         }
3484     }
3485
3486     _mm_empty ();
3487 }
3488
3489 static void
3490 mmx_composite_over_reverse_n_8888 (pixman_implementation_t *imp,
3491                                    pixman_composite_info_t *info)
3492 {
3493     PIXMAN_COMPOSITE_ARGS (info);
3494     uint32_t src;
3495     uint32_t    *dst_line, *dst;
3496     int32_t w;
3497     int dst_stride;
3498     __m64 vsrc;
3499
3500     CHECKPOINT ();
3501
3502     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
3503
3504     if (src == 0)
3505         return;
3506
3507     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
3508
3509     vsrc = load8888 (&src);
3510
3511     while (height--)
3512     {
3513         dst = dst_line;
3514         dst_line += dst_stride;
3515         w = width;
3516
3517         CHECKPOINT ();
3518
3519         while (w && (uintptr_t)dst & 7)
3520         {
3521             __m64 vdest = load8888 (dst);
3522
3523             store8888 (dst, over (vdest, expand_alpha (vdest), vsrc));
3524
3525             w--;
3526             dst++;
3527         }
3528
3529         while (w >= 2)
3530         {
3531             __m64 vdest = *(__m64 *)dst;
3532             __m64 dest0 = expand8888 (vdest, 0);
3533             __m64 dest1 = expand8888 (vdest, 1);
3534
3535
3536             dest0 = over (dest0, expand_alpha (dest0), vsrc);
3537             dest1 = over (dest1, expand_alpha (dest1), vsrc);
3538
3539             *(__m64 *)dst = pack8888 (dest0, dest1);
3540
3541             dst += 2;
3542             w -= 2;
3543         }
3544
3545         CHECKPOINT ();
3546
3547         if (w)
3548         {
3549             __m64 vdest = load8888 (dst);
3550
3551             store8888 (dst, over (vdest, expand_alpha (vdest), vsrc));
3552         }
3553     }
3554
3555     _mm_empty ();
3556 }
3557
3558 #define BSHIFT ((1 << BILINEAR_INTERPOLATION_BITS))
3559 #define BMSK (BSHIFT - 1)
3560
3561 #define BILINEAR_DECLARE_VARIABLES                                              \
3562     const __m64 mm_wt = _mm_set_pi16 (wt, wt, wt, wt);                          \
3563     const __m64 mm_wb = _mm_set_pi16 (wb, wb, wb, wb);                          \
3564     const __m64 mm_addc7 = _mm_set_pi16 (0, 1, 0, 1);                           \
3565     const __m64 mm_xorc7 = _mm_set_pi16 (0, BMSK, 0, BMSK);                     \
3566     const __m64 mm_ux = _mm_set_pi16 (unit_x, unit_x, unit_x, unit_x);          \
3567     const __m64 mm_zero = _mm_setzero_si64 ();                                  \
3568     __m64 mm_x = _mm_set_pi16 (vx, vx, vx, vx)
3569
3570 #define BILINEAR_INTERPOLATE_ONE_PIXEL(pix)                                     \
3571 do {                                                                            \
3572     /* fetch 2x2 pixel block into 2 mmx registers */                            \
3573     __m64 t = ldq_u ((__m64 *)&src_top [pixman_fixed_to_int (vx)]);             \
3574     __m64 b = ldq_u ((__m64 *)&src_bottom [pixman_fixed_to_int (vx)]);          \
3575     /* vertical interpolation */                                                \
3576     __m64 t_hi = _mm_mullo_pi16 (_mm_unpackhi_pi8 (t, mm_zero), mm_wt);         \
3577     __m64 t_lo = _mm_mullo_pi16 (_mm_unpacklo_pi8 (t, mm_zero), mm_wt);         \
3578     __m64 b_hi = _mm_mullo_pi16 (_mm_unpackhi_pi8 (b, mm_zero), mm_wb);         \
3579     __m64 b_lo = _mm_mullo_pi16 (_mm_unpacklo_pi8 (b, mm_zero), mm_wb);         \
3580     __m64 hi = _mm_add_pi16 (t_hi, b_hi);                                       \
3581     __m64 lo = _mm_add_pi16 (t_lo, b_lo);                                       \
3582     /* calculate horizontal weights */                                          \
3583     __m64 mm_wh = _mm_add_pi16 (mm_addc7, _mm_xor_si64 (mm_xorc7,               \
3584                           _mm_srli_pi16 (mm_x,                                  \
3585                                          16 - BILINEAR_INTERPOLATION_BITS)));   \
3586     /* horizontal interpolation */                                              \
3587     __m64 p = _mm_unpacklo_pi16 (lo, hi);                                       \
3588     __m64 q = _mm_unpackhi_pi16 (lo, hi);                                       \
3589     vx += unit_x;                                                               \
3590     lo = _mm_madd_pi16 (p, mm_wh);                                              \
3591     hi = _mm_madd_pi16 (q, mm_wh);                                              \
3592     mm_x = _mm_add_pi16 (mm_x, mm_ux);                                          \
3593     /* shift and pack the result */                                             \
3594     hi = _mm_srli_pi32 (hi, BILINEAR_INTERPOLATION_BITS * 2);                   \
3595     lo = _mm_srli_pi32 (lo, BILINEAR_INTERPOLATION_BITS * 2);                   \
3596     lo = _mm_packs_pi32 (lo, hi);                                               \
3597     lo = _mm_packs_pu16 (lo, lo);                                               \
3598     pix = lo;                                                                   \
3599 } while (0)
3600
3601 #define BILINEAR_SKIP_ONE_PIXEL()                                               \
3602 do {                                                                            \
3603     vx += unit_x;                                                               \
3604     mm_x = _mm_add_pi16 (mm_x, mm_ux);                                          \
3605 } while(0)
3606
3607 static force_inline void
3608 scaled_bilinear_scanline_mmx_8888_8888_SRC (uint32_t *       dst,
3609                                             const uint32_t * mask,
3610                                             const uint32_t * src_top,
3611                                             const uint32_t * src_bottom,
3612                                             int32_t          w,
3613                                             int              wt,
3614                                             int              wb,
3615                                             pixman_fixed_t   vx,
3616                                             pixman_fixed_t   unit_x,
3617                                             pixman_fixed_t   max_vx,
3618                                             pixman_bool_t    zero_src)
3619 {
3620     BILINEAR_DECLARE_VARIABLES;
3621     __m64 pix;
3622
3623     while (w--)
3624     {
3625         BILINEAR_INTERPOLATE_ONE_PIXEL (pix);
3626         store (dst, pix);
3627         dst++;
3628     }
3629
3630     _mm_empty ();
3631 }
3632
3633 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_cover_SRC,
3634                                scaled_bilinear_scanline_mmx_8888_8888_SRC,
3635                                uint32_t, uint32_t, uint32_t,
3636                                COVER, FLAG_NONE)
3637 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_pad_SRC,
3638                                scaled_bilinear_scanline_mmx_8888_8888_SRC,
3639                                uint32_t, uint32_t, uint32_t,
3640                                PAD, FLAG_NONE)
3641 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_none_SRC,
3642                                scaled_bilinear_scanline_mmx_8888_8888_SRC,
3643                                uint32_t, uint32_t, uint32_t,
3644                                NONE, FLAG_NONE)
3645 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_normal_SRC,
3646                                scaled_bilinear_scanline_mmx_8888_8888_SRC,
3647                                uint32_t, uint32_t, uint32_t,
3648                                NORMAL, FLAG_NONE)
3649
3650 static force_inline void
3651 scaled_bilinear_scanline_mmx_8888_8888_OVER (uint32_t *       dst,
3652                                              const uint32_t * mask,
3653                                              const uint32_t * src_top,
3654                                              const uint32_t * src_bottom,
3655                                              int32_t          w,
3656                                              int              wt,
3657                                              int              wb,
3658                                              pixman_fixed_t   vx,
3659                                              pixman_fixed_t   unit_x,
3660                                              pixman_fixed_t   max_vx,
3661                                              pixman_bool_t    zero_src)
3662 {
3663     BILINEAR_DECLARE_VARIABLES;
3664     __m64 pix1, pix2;
3665
3666     while (w)
3667     {
3668         BILINEAR_INTERPOLATE_ONE_PIXEL (pix1);
3669
3670         if (!is_zero (pix1))
3671         {
3672             pix2 = load (dst);
3673             store8888 (dst, core_combine_over_u_pixel_mmx (pix1, pix2));
3674         }
3675
3676         w--;
3677         dst++;
3678     }
3679
3680     _mm_empty ();
3681 }
3682
3683 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_cover_OVER,
3684                                scaled_bilinear_scanline_mmx_8888_8888_OVER,
3685                                uint32_t, uint32_t, uint32_t,
3686                                COVER, FLAG_NONE)
3687 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_pad_OVER,
3688                                scaled_bilinear_scanline_mmx_8888_8888_OVER,
3689                                uint32_t, uint32_t, uint32_t,
3690                                PAD, FLAG_NONE)
3691 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_none_OVER,
3692                                scaled_bilinear_scanline_mmx_8888_8888_OVER,
3693                                uint32_t, uint32_t, uint32_t,
3694                                NONE, FLAG_NONE)
3695 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_normal_OVER,
3696                                scaled_bilinear_scanline_mmx_8888_8888_OVER,
3697                                uint32_t, uint32_t, uint32_t,
3698                                NORMAL, FLAG_NONE)
3699
3700 static force_inline void
3701 scaled_bilinear_scanline_mmx_8888_8_8888_OVER (uint32_t *       dst,
3702                                                const uint8_t  * mask,
3703                                                const uint32_t * src_top,
3704                                                const uint32_t * src_bottom,
3705                                                int32_t          w,
3706                                                int              wt,
3707                                                int              wb,
3708                                                pixman_fixed_t   vx,
3709                                                pixman_fixed_t   unit_x,
3710                                                pixman_fixed_t   max_vx,
3711                                                pixman_bool_t    zero_src)
3712 {
3713     BILINEAR_DECLARE_VARIABLES;
3714     __m64 pix1, pix2;
3715     uint32_t m;
3716
3717     while (w)
3718     {
3719         m = (uint32_t) *mask++;
3720
3721         if (m)
3722         {
3723             BILINEAR_INTERPOLATE_ONE_PIXEL (pix1);
3724
3725             if (m == 0xff && is_opaque (pix1))
3726             {
3727                 store (dst, pix1);
3728             }
3729             else
3730             {
3731                 __m64 ms, md, ma, msa;
3732
3733                 pix2 = load (dst);
3734                 ma = expand_alpha_rev (to_m64 (m));
3735                 ms = _mm_unpacklo_pi8 (pix1, _mm_setzero_si64 ());
3736                 md = _mm_unpacklo_pi8 (pix2, _mm_setzero_si64 ());
3737
3738                 msa = expand_alpha (ms);
3739
3740                 store8888 (dst, (in_over (ms, msa, ma, md)));
3741             }
3742         }
3743         else
3744         {
3745             BILINEAR_SKIP_ONE_PIXEL ();
3746         }
3747
3748         w--;
3749         dst++;
3750     }
3751
3752     _mm_empty ();
3753 }
3754
3755 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_cover_OVER,
3756                                scaled_bilinear_scanline_mmx_8888_8_8888_OVER,
3757                                uint32_t, uint8_t, uint32_t,
3758                                COVER, FLAG_HAVE_NON_SOLID_MASK)
3759 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_pad_OVER,
3760                                scaled_bilinear_scanline_mmx_8888_8_8888_OVER,
3761                                uint32_t, uint8_t, uint32_t,
3762                                PAD, FLAG_HAVE_NON_SOLID_MASK)
3763 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_none_OVER,
3764                                scaled_bilinear_scanline_mmx_8888_8_8888_OVER,
3765                                uint32_t, uint8_t, uint32_t,
3766                                NONE, FLAG_HAVE_NON_SOLID_MASK)
3767 FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_normal_OVER,
3768                                scaled_bilinear_scanline_mmx_8888_8_8888_OVER,
3769                                uint32_t, uint8_t, uint32_t,
3770                                NORMAL, FLAG_HAVE_NON_SOLID_MASK)
3771
3772 static uint32_t *
3773 mmx_fetch_x8r8g8b8 (pixman_iter_t *iter, const uint32_t *mask)
3774 {
3775     int w = iter->width;
3776     uint32_t *dst = iter->buffer;
3777     uint32_t *src = (uint32_t *)iter->bits;
3778
3779     iter->bits += iter->stride;
3780
3781     while (w && ((uintptr_t)dst) & 7)
3782     {
3783         *dst++ = (*src++) | 0xff000000;
3784         w--;
3785     }
3786
3787     while (w >= 8)
3788     {
3789         __m64 vsrc1 = ldq_u ((__m64 *)(src + 0));
3790         __m64 vsrc2 = ldq_u ((__m64 *)(src + 2));
3791         __m64 vsrc3 = ldq_u ((__m64 *)(src + 4));
3792         __m64 vsrc4 = ldq_u ((__m64 *)(src + 6));
3793
3794         *(__m64 *)(dst + 0) = _mm_or_si64 (vsrc1, MC (ff000000));
3795         *(__m64 *)(dst + 2) = _mm_or_si64 (vsrc2, MC (ff000000));
3796         *(__m64 *)(dst + 4) = _mm_or_si64 (vsrc3, MC (ff000000));
3797         *(__m64 *)(dst + 6) = _mm_or_si64 (vsrc4, MC (ff000000));
3798
3799         dst += 8;
3800         src += 8;
3801         w -= 8;
3802     }
3803
3804     while (w)
3805     {
3806         *dst++ = (*src++) | 0xff000000;
3807         w--;
3808     }
3809
3810     _mm_empty ();
3811     return iter->buffer;
3812 }
3813
3814 static uint32_t *
3815 mmx_fetch_r5g6b5 (pixman_iter_t *iter, const uint32_t *mask)
3816 {
3817     int w = iter->width;
3818     uint32_t *dst = iter->buffer;
3819     uint16_t *src = (uint16_t *)iter->bits;
3820
3821     iter->bits += iter->stride;
3822
3823     while (w && ((uintptr_t)dst) & 0x0f)
3824     {
3825         uint16_t s = *src++;
3826
3827         *dst++ = convert_0565_to_8888 (s);
3828         w--;
3829     }
3830
3831     while (w >= 4)
3832     {
3833         __m64 vsrc = ldq_u ((__m64 *)src);
3834         __m64 mm0, mm1;
3835
3836         expand_4xpacked565 (vsrc, &mm0, &mm1, 1);
3837
3838         *(__m64 *)(dst + 0) = mm0;
3839         *(__m64 *)(dst + 2) = mm1;
3840
3841         dst += 4;
3842         src += 4;
3843         w -= 4;
3844     }
3845
3846     while (w)
3847     {
3848         uint16_t s = *src++;
3849
3850         *dst++ = convert_0565_to_8888 (s);
3851         w--;
3852     }
3853
3854     _mm_empty ();
3855     return iter->buffer;
3856 }
3857
3858 static uint32_t *
3859 mmx_fetch_a8 (pixman_iter_t *iter, const uint32_t *mask)
3860 {
3861     int w = iter->width;
3862     uint32_t *dst = iter->buffer;
3863     uint8_t *src = iter->bits;
3864
3865     iter->bits += iter->stride;
3866
3867     while (w && (((uintptr_t)dst) & 15))
3868     {
3869         *dst++ = *(src++) << 24;
3870         w--;
3871     }
3872
3873     while (w >= 8)
3874     {
3875         __m64 mm0 = ldq_u ((__m64 *)src);
3876
3877         __m64 mm1 = _mm_unpacklo_pi8  (_mm_setzero_si64(), mm0);
3878         __m64 mm2 = _mm_unpackhi_pi8  (_mm_setzero_si64(), mm0);
3879         __m64 mm3 = _mm_unpacklo_pi16 (_mm_setzero_si64(), mm1);
3880         __m64 mm4 = _mm_unpackhi_pi16 (_mm_setzero_si64(), mm1);
3881         __m64 mm5 = _mm_unpacklo_pi16 (_mm_setzero_si64(), mm2);
3882         __m64 mm6 = _mm_unpackhi_pi16 (_mm_setzero_si64(), mm2);
3883
3884         *(__m64 *)(dst + 0) = mm3;
3885         *(__m64 *)(dst + 2) = mm4;
3886         *(__m64 *)(dst + 4) = mm5;
3887         *(__m64 *)(dst + 6) = mm6;
3888
3889         dst += 8;
3890         src += 8;
3891         w -= 8;
3892     }
3893
3894     while (w)
3895     {
3896         *dst++ = *(src++) << 24;
3897         w--;
3898     }
3899
3900     _mm_empty ();
3901     return iter->buffer;
3902 }
3903
3904 #define IMAGE_FLAGS                                                     \
3905     (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM |                \
3906      FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
3907
3908 static const pixman_iter_info_t mmx_iters[] = 
3909 {
3910     { PIXMAN_x8r8g8b8, IMAGE_FLAGS, ITER_NARROW,
3911       _pixman_iter_init_bits_stride, mmx_fetch_x8r8g8b8, NULL
3912     },
3913     { PIXMAN_r5g6b5, IMAGE_FLAGS, ITER_NARROW,
3914       _pixman_iter_init_bits_stride, mmx_fetch_r5g6b5, NULL
3915     },
3916     { PIXMAN_a8, IMAGE_FLAGS, ITER_NARROW,
3917       _pixman_iter_init_bits_stride, mmx_fetch_a8, NULL
3918     },
3919     { PIXMAN_null },
3920 };
3921
3922 static const pixman_fast_path_t mmx_fast_paths[] =
3923 {
3924     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       r5g6b5,   mmx_composite_over_n_8_0565       ),
3925     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       b5g6r5,   mmx_composite_over_n_8_0565       ),
3926     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       a8r8g8b8, mmx_composite_over_n_8_8888       ),
3927     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       x8r8g8b8, mmx_composite_over_n_8_8888       ),
3928     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       a8b8g8r8, mmx_composite_over_n_8_8888       ),
3929     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       x8b8g8r8, mmx_composite_over_n_8_8888       ),
3930     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8r8g8b8, a8r8g8b8, mmx_composite_over_n_8888_8888_ca ),
3931     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8r8g8b8, x8r8g8b8, mmx_composite_over_n_8888_8888_ca ),
3932     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8r8g8b8, r5g6b5,   mmx_composite_over_n_8888_0565_ca ),
3933     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8b8g8r8, a8b8g8r8, mmx_composite_over_n_8888_8888_ca ),
3934     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8b8g8r8, x8b8g8r8, mmx_composite_over_n_8888_8888_ca ),
3935     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8b8g8r8, b5g6r5,   mmx_composite_over_n_8888_0565_ca ),
3936     PIXMAN_STD_FAST_PATH    (OVER, pixbuf,   pixbuf,   a8r8g8b8, mmx_composite_over_pixbuf_8888    ),
3937     PIXMAN_STD_FAST_PATH    (OVER, pixbuf,   pixbuf,   x8r8g8b8, mmx_composite_over_pixbuf_8888    ),
3938     PIXMAN_STD_FAST_PATH    (OVER, pixbuf,   pixbuf,   r5g6b5,   mmx_composite_over_pixbuf_0565    ),
3939     PIXMAN_STD_FAST_PATH    (OVER, rpixbuf,  rpixbuf,  a8b8g8r8, mmx_composite_over_pixbuf_8888    ),
3940     PIXMAN_STD_FAST_PATH    (OVER, rpixbuf,  rpixbuf,  x8b8g8r8, mmx_composite_over_pixbuf_8888    ),
3941     PIXMAN_STD_FAST_PATH    (OVER, rpixbuf,  rpixbuf,  b5g6r5,   mmx_composite_over_pixbuf_0565    ),
3942     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, solid,    a8r8g8b8, mmx_composite_over_x888_n_8888    ),
3943     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, solid,    x8r8g8b8, mmx_composite_over_x888_n_8888    ),
3944     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, solid,    a8b8g8r8, mmx_composite_over_x888_n_8888    ),
3945     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, solid,    x8b8g8r8, mmx_composite_over_x888_n_8888    ),
3946     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, solid,    a8r8g8b8, mmx_composite_over_8888_n_8888    ),
3947     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, solid,    x8r8g8b8, mmx_composite_over_8888_n_8888    ),
3948     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, solid,    a8b8g8r8, mmx_composite_over_8888_n_8888    ),
3949     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, solid,    x8b8g8r8, mmx_composite_over_8888_n_8888    ),
3950     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, a8,       x8r8g8b8, mmx_composite_over_x888_8_8888    ),
3951     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, a8,       a8r8g8b8, mmx_composite_over_x888_8_8888    ),
3952     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, a8,       x8b8g8r8, mmx_composite_over_x888_8_8888    ),
3953     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, a8,       a8b8g8r8, mmx_composite_over_x888_8_8888    ),
3954     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     a8r8g8b8, mmx_composite_over_n_8888         ),
3955     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     x8r8g8b8, mmx_composite_over_n_8888         ),
3956     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     r5g6b5,   mmx_composite_over_n_0565         ),
3957     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     b5g6r5,   mmx_composite_over_n_0565         ),
3958     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, null,     x8r8g8b8, mmx_composite_copy_area           ),
3959     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, null,     x8b8g8r8, mmx_composite_copy_area           ),
3960
3961     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, null,     a8r8g8b8, mmx_composite_over_8888_8888      ),
3962     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, null,     x8r8g8b8, mmx_composite_over_8888_8888      ),
3963     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, null,     r5g6b5,   mmx_composite_over_8888_0565      ),
3964     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, null,     a8b8g8r8, mmx_composite_over_8888_8888      ),
3965     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, null,     x8b8g8r8, mmx_composite_over_8888_8888      ),
3966     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, null,     b5g6r5,   mmx_composite_over_8888_0565      ),
3967
3968     PIXMAN_STD_FAST_PATH    (OVER_REVERSE, solid, null, a8r8g8b8, mmx_composite_over_reverse_n_8888),
3969     PIXMAN_STD_FAST_PATH    (OVER_REVERSE, solid, null, a8b8g8r8, mmx_composite_over_reverse_n_8888),
3970
3971     PIXMAN_STD_FAST_PATH    (ADD,  r5g6b5,   null,     r5g6b5,   mmx_composite_add_0565_0565       ),
3972     PIXMAN_STD_FAST_PATH    (ADD,  b5g6r5,   null,     b5g6r5,   mmx_composite_add_0565_0565       ),
3973     PIXMAN_STD_FAST_PATH    (ADD,  a8r8g8b8, null,     a8r8g8b8, mmx_composite_add_8888_8888       ),
3974     PIXMAN_STD_FAST_PATH    (ADD,  a8b8g8r8, null,     a8b8g8r8, mmx_composite_add_8888_8888       ),
3975     PIXMAN_STD_FAST_PATH    (ADD,  a8,       null,     a8,       mmx_composite_add_8_8             ),
3976     PIXMAN_STD_FAST_PATH    (ADD,  solid,    a8,       a8,       mmx_composite_add_n_8_8           ),
3977
3978     PIXMAN_STD_FAST_PATH    (SRC,  a8r8g8b8, null,     r5g6b5,   mmx_composite_src_x888_0565       ),
3979     PIXMAN_STD_FAST_PATH    (SRC,  a8b8g8r8, null,     b5g6r5,   mmx_composite_src_x888_0565       ),
3980     PIXMAN_STD_FAST_PATH    (SRC,  x8r8g8b8, null,     r5g6b5,   mmx_composite_src_x888_0565       ),
3981     PIXMAN_STD_FAST_PATH    (SRC,  x8b8g8r8, null,     b5g6r5,   mmx_composite_src_x888_0565       ),
3982     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       a8r8g8b8, mmx_composite_src_n_8_8888        ),
3983     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       x8r8g8b8, mmx_composite_src_n_8_8888        ),
3984     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       a8b8g8r8, mmx_composite_src_n_8_8888        ),
3985     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       x8b8g8r8, mmx_composite_src_n_8_8888        ),
3986     PIXMAN_STD_FAST_PATH    (SRC,  a8r8g8b8, null,     a8r8g8b8, mmx_composite_copy_area           ),
3987     PIXMAN_STD_FAST_PATH    (SRC,  a8b8g8r8, null,     a8b8g8r8, mmx_composite_copy_area           ),
3988     PIXMAN_STD_FAST_PATH    (SRC,  a8r8g8b8, null,     x8r8g8b8, mmx_composite_copy_area           ),
3989     PIXMAN_STD_FAST_PATH    (SRC,  a8b8g8r8, null,     x8b8g8r8, mmx_composite_copy_area           ),
3990     PIXMAN_STD_FAST_PATH    (SRC,  x8r8g8b8, null,     x8r8g8b8, mmx_composite_copy_area           ),
3991     PIXMAN_STD_FAST_PATH    (SRC,  x8b8g8r8, null,     x8b8g8r8, mmx_composite_copy_area           ),
3992     PIXMAN_STD_FAST_PATH    (SRC,  r5g6b5,   null,     r5g6b5,   mmx_composite_copy_area           ),
3993     PIXMAN_STD_FAST_PATH    (SRC,  b5g6r5,   null,     b5g6r5,   mmx_composite_copy_area           ),
3994
3995     PIXMAN_STD_FAST_PATH    (IN,   a8,       null,     a8,       mmx_composite_in_8_8              ),
3996     PIXMAN_STD_FAST_PATH    (IN,   solid,    a8,       a8,       mmx_composite_in_n_8_8            ),
3997
3998     SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8,          a8r8g8b8, mmx_8888_8888                     ),
3999     SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8,          x8r8g8b8, mmx_8888_8888                     ),
4000     SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8,          x8r8g8b8, mmx_8888_8888                     ),
4001     SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8,          a8b8g8r8, mmx_8888_8888                     ),
4002     SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8,          x8b8g8r8, mmx_8888_8888                     ),
4003     SIMPLE_BILINEAR_FAST_PATH (SRC, x8b8g8r8,          x8b8g8r8, mmx_8888_8888                     ),
4004
4005     SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8,         x8r8g8b8, mmx_8888_8888                     ),
4006     SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8,         x8b8g8r8, mmx_8888_8888                     ),
4007     SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8,         a8r8g8b8, mmx_8888_8888                     ),
4008     SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8,         a8b8g8r8, mmx_8888_8888                     ),
4009
4010     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_8_8888                   ),
4011     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_8_8888                   ),
4012     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_8_8888                   ),
4013     SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_8_8888                   ),
4014
4015     { PIXMAN_OP_NONE },
4016 };
4017
4018 pixman_implementation_t *
4019 _pixman_implementation_create_mmx (pixman_implementation_t *fallback)
4020 {
4021     pixman_implementation_t *imp = _pixman_implementation_create (fallback, mmx_fast_paths);
4022
4023     imp->combine_32[PIXMAN_OP_OVER] = mmx_combine_over_u;
4024     imp->combine_32[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_u;
4025     imp->combine_32[PIXMAN_OP_IN] = mmx_combine_in_u;
4026     imp->combine_32[PIXMAN_OP_IN_REVERSE] = mmx_combine_in_reverse_u;
4027     imp->combine_32[PIXMAN_OP_OUT] = mmx_combine_out_u;
4028     imp->combine_32[PIXMAN_OP_OUT_REVERSE] = mmx_combine_out_reverse_u;
4029     imp->combine_32[PIXMAN_OP_ATOP] = mmx_combine_atop_u;
4030     imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = mmx_combine_atop_reverse_u;
4031     imp->combine_32[PIXMAN_OP_XOR] = mmx_combine_xor_u;
4032     imp->combine_32[PIXMAN_OP_ADD] = mmx_combine_add_u;
4033     imp->combine_32[PIXMAN_OP_SATURATE] = mmx_combine_saturate_u;
4034
4035     imp->combine_32_ca[PIXMAN_OP_SRC] = mmx_combine_src_ca;
4036     imp->combine_32_ca[PIXMAN_OP_OVER] = mmx_combine_over_ca;
4037     imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_ca;
4038     imp->combine_32_ca[PIXMAN_OP_IN] = mmx_combine_in_ca;
4039     imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = mmx_combine_in_reverse_ca;
4040     imp->combine_32_ca[PIXMAN_OP_OUT] = mmx_combine_out_ca;
4041     imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = mmx_combine_out_reverse_ca;
4042     imp->combine_32_ca[PIXMAN_OP_ATOP] = mmx_combine_atop_ca;
4043     imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = mmx_combine_atop_reverse_ca;
4044     imp->combine_32_ca[PIXMAN_OP_XOR] = mmx_combine_xor_ca;
4045     imp->combine_32_ca[PIXMAN_OP_ADD] = mmx_combine_add_ca;
4046
4047     imp->blt = mmx_blt;
4048     imp->fill = mmx_fill;
4049
4050     imp->iter_info = mmx_iters;
4051
4052     return imp;
4053 }
4054
4055 #endif /* USE_X86_MMX || USE_ARM_IWMMXT || USE_LOONGSON_MMI */