mmx: introduce is_equal, is_opaque, and is_zero functions
[profile/ivi/pixman.git] / 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
46 #define no_vERBOSE
47
48 #ifdef VERBOSE
49 #define CHECKPOINT() error_f ("at %s %d\n", __FUNCTION__, __LINE__)
50 #else
51 #define CHECKPOINT()
52 #endif
53
54 #ifdef USE_ARM_IWMMXT
55 /* Empty the multimedia state. For some reason, ARM's mmintrin.h doesn't provide this.  */
56 extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
57 _mm_empty (void)
58 {
59
60 }
61 #endif
62
63 #ifdef USE_X86_MMX
64 # if (defined(__SUNPRO_C) || defined(_MSC_VER))
65 #  include <xmmintrin.h>
66 # else
67 /* We have to compile with -msse to use xmmintrin.h, but that causes SSE
68  * instructions to be generated that we don't want. Just duplicate the
69  * functions we want to use.  */
70 extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
71 _mm_movemask_pi8 (__m64 __A)
72 {
73     int ret;
74
75     asm ("pmovmskb %1, %0\n\t"
76         : "=r" (ret)
77         : "y" (__A)
78     );
79
80     return ret;
81 }
82
83 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
84 _mm_mulhi_pu16 (__m64 __A, __m64 __B)
85 {
86     asm ("pmulhuw %1, %0\n\t"
87         : "+y" (__A)
88         : "y" (__B)
89     );
90     return __A;
91 }
92
93 #  ifdef __OPTIMIZE__
94 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
95 _mm_shuffle_pi16 (__m64 __A, int8_t const __N)
96 {
97     __m64 ret;
98
99     asm ("pshufw %2, %1, %0\n\t"
100         : "=y" (ret)
101         : "y" (__A), "K" (__N)
102     );
103
104     return ret;
105 }
106 #  else
107 #   define _mm_shuffle_pi16(A, N) \
108     ((__m64) __builtin_ia32_pshufw ((__v4hi)(__m64)(A), (int)(N)))
109 #  endif
110 # endif
111 #endif
112
113 #ifndef _MSC_VER
114 #define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \
115  (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | (fp0))
116 #endif
117
118 /* Notes about writing mmx code
119  *
120  * give memory operands as the second operand. If you give it as the
121  * first, gcc will first load it into a register, then use that
122  * register
123  *
124  *   ie. use
125  *
126  *         _mm_mullo_pi16 (x, mmx_constant);
127  *
128  *   not
129  *
130  *         _mm_mullo_pi16 (mmx_constant, x);
131  *
132  * Also try to minimize dependencies. i.e. when you need a value, try
133  * to calculate it from a value that was calculated as early as
134  * possible.
135  */
136
137 /* --------------- MMX primitives ------------------------------------- */
138
139 /* If __m64 is defined as a struct or union, then define M64_MEMBER to be
140  * the name of the member used to access the data.
141  * If __m64 requires using mm_cvt* intrinsics functions to convert between
142  * uint64_t and __m64 values, then define USE_CVT_INTRINSICS.
143  * If __m64 and uint64_t values can just be cast to each other directly,
144  * then define USE_M64_CASTS.
145  * If __m64 is a double datatype, then define USE_M64_DOUBLE.
146  */
147 #ifdef _MSC_VER
148 # define M64_MEMBER m64_u64
149 #elif defined(__ICC)
150 # define USE_CVT_INTRINSICS
151 #elif defined(USE_LOONGSON_MMI)
152 # define USE_M64_DOUBLE
153 #elif defined(__GNUC__)
154 # define USE_M64_CASTS
155 #elif defined(__SUNPRO_C)
156 # if (__SUNPRO_C >= 0x5120) && !defined(__NOVECTORSIZE__)
157 /* Solaris Studio 12.3 (Sun C 5.12) introduces __attribute__(__vector_size__)
158  * support, and defaults to using it to define __m64, unless __NOVECTORSIZE__
159  * is defined.   If it is used, then the mm_cvt* intrinsics must be used.
160  */
161 #  define USE_CVT_INTRINSICS
162 # else
163 /* For Studio 12.2 or older, or when __attribute__(__vector_size__) is
164  * disabled, __m64 is defined as a struct containing "unsigned long long l_".
165  */
166 #  define M64_MEMBER l_
167 # endif
168 #endif
169
170 #if defined(USE_M64_CASTS) || defined(USE_CVT_INTRINSICS) || defined(USE_M64_DOUBLE)
171 typedef uint64_t mmxdatafield;
172 #else
173 typedef __m64 mmxdatafield;
174 #endif
175
176 typedef struct
177 {
178     mmxdatafield mmx_4x00ff;
179     mmxdatafield mmx_4x0080;
180     mmxdatafield mmx_565_rgb;
181     mmxdatafield mmx_565_unpack_multiplier;
182     mmxdatafield mmx_565_r;
183     mmxdatafield mmx_565_g;
184     mmxdatafield mmx_565_b;
185     mmxdatafield mmx_mask_0;
186     mmxdatafield mmx_mask_1;
187     mmxdatafield mmx_mask_2;
188     mmxdatafield mmx_mask_3;
189     mmxdatafield mmx_full_alpha;
190     mmxdatafield mmx_4x0101;
191 } mmx_data_t;
192
193 #if defined(_MSC_VER)
194 # define MMXDATA_INIT(field, val) { val ## UI64 }
195 #elif defined(M64_MEMBER)       /* __m64 is a struct, not an integral type */
196 # define MMXDATA_INIT(field, val) field =   { val ## ULL }
197 #else                           /* mmxdatafield is an integral type */
198 # define MMXDATA_INIT(field, val) field =   val ## ULL
199 #endif
200
201 static const mmx_data_t c =
202 {
203     MMXDATA_INIT (.mmx_4x00ff,                   0x00ff00ff00ff00ff),
204     MMXDATA_INIT (.mmx_4x0080,                   0x0080008000800080),
205     MMXDATA_INIT (.mmx_565_rgb,                  0x000001f0003f001f),
206     MMXDATA_INIT (.mmx_565_unpack_multiplier,    0x0000008404100840),
207     MMXDATA_INIT (.mmx_565_r,                    0x000000f800000000),
208     MMXDATA_INIT (.mmx_565_g,                    0x0000000000fc0000),
209     MMXDATA_INIT (.mmx_565_b,                    0x00000000000000f8),
210     MMXDATA_INIT (.mmx_mask_0,                   0xffffffffffff0000),
211     MMXDATA_INIT (.mmx_mask_1,                   0xffffffff0000ffff),
212     MMXDATA_INIT (.mmx_mask_2,                   0xffff0000ffffffff),
213     MMXDATA_INIT (.mmx_mask_3,                   0x0000ffffffffffff),
214     MMXDATA_INIT (.mmx_full_alpha,               0x00ff000000000000),
215     MMXDATA_INIT (.mmx_4x0101,                   0x0101010101010101),
216 };
217
218 #ifdef USE_CVT_INTRINSICS
219 #    define MC(x) to_m64 (c.mmx_ ## x)
220 #elif defined(USE_M64_CASTS)
221 #    define MC(x) ((__m64)c.mmx_ ## x)
222 #elif defined(USE_M64_DOUBLE)
223 #    define MC(x) (*(__m64 *)&c.mmx_ ## x)
224 #else
225 #    define MC(x) c.mmx_ ## x
226 #endif
227
228 static force_inline __m64
229 to_m64 (uint64_t x)
230 {
231 #ifdef USE_CVT_INTRINSICS
232     return _mm_cvtsi64_m64 (x);
233 #elif defined M64_MEMBER        /* __m64 is a struct, not an integral type */
234     __m64 res;
235
236     res.M64_MEMBER = x;
237     return res;
238 #elif defined USE_M64_DOUBLE
239     return *(__m64 *)&x;
240 #else /* USE_M64_CASTS */
241     return (__m64)x;
242 #endif
243 }
244
245 static force_inline uint64_t
246 to_uint64 (__m64 x)
247 {
248 #ifdef USE_CVT_INTRINSICS
249     return _mm_cvtm64_si64 (x);
250 #elif defined M64_MEMBER        /* __m64 is a struct, not an integral type */
251     uint64_t res = x.M64_MEMBER;
252     return res;
253 #elif defined USE_M64_DOUBLE
254     return *(uint64_t *)&x;
255 #else /* USE_M64_CASTS */
256     return (uint64_t)x;
257 #endif
258 }
259
260 static force_inline __m64
261 shift (__m64 v,
262        int   s)
263 {
264     if (s > 0)
265         return _mm_slli_si64 (v, s);
266     else if (s < 0)
267         return _mm_srli_si64 (v, -s);
268     else
269         return v;
270 }
271
272 static force_inline __m64
273 negate (__m64 mask)
274 {
275     return _mm_xor_si64 (mask, MC (4x00ff));
276 }
277
278 static force_inline __m64
279 pix_multiply (__m64 a, __m64 b)
280 {
281     __m64 res;
282
283     res = _mm_mullo_pi16 (a, b);
284     res = _mm_adds_pu16 (res, MC (4x0080));
285     res = _mm_mulhi_pu16 (res, MC (4x0101));
286
287     return res;
288 }
289
290 static force_inline __m64
291 pix_add (__m64 a, __m64 b)
292 {
293     return _mm_adds_pu8 (a, b);
294 }
295
296 static force_inline __m64
297 expand_alpha (__m64 pixel)
298 {
299     return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE (3, 3, 3, 3));
300 }
301
302 static force_inline __m64
303 expand_alpha_rev (__m64 pixel)
304 {
305     return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE (0, 0, 0, 0));
306 }
307
308 static force_inline __m64
309 invert_colors (__m64 pixel)
310 {
311     return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE (3, 0, 1, 2));
312 }
313
314 static force_inline __m64
315 over (__m64 src,
316       __m64 srca,
317       __m64 dest)
318 {
319     return _mm_adds_pu8 (src, pix_multiply (dest, negate (srca)));
320 }
321
322 static force_inline __m64
323 over_rev_non_pre (__m64 src, __m64 dest)
324 {
325     __m64 srca = expand_alpha (src);
326     __m64 srcfaaa = _mm_or_si64 (srca, MC (full_alpha));
327
328     return over (pix_multiply (invert_colors (src), srcfaaa), srca, dest);
329 }
330
331 static force_inline __m64
332 in (__m64 src, __m64 mask)
333 {
334     return pix_multiply (src, mask);
335 }
336
337 #ifndef _MSC_VER
338 static force_inline __m64
339 in_over (__m64 src, __m64 srca, __m64 mask, __m64 dest)
340 {
341     return over (in (src, mask), pix_multiply (srca, mask), dest);
342 }
343
344 #else
345
346 #define in_over(src, srca, mask, dest)                                  \
347     over (in (src, mask), pix_multiply (srca, mask), dest)
348
349 #endif
350
351 /* Elemental unaligned loads */
352
353 static force_inline __m64 ldq_u(__m64 *p)
354 {
355 #ifdef USE_X86_MMX
356     /* x86's alignment restrictions are very relaxed. */
357     return *(__m64 *)p;
358 #elif defined USE_ARM_IWMMXT
359     int align = (uintptr_t)p & 7;
360     __m64 *aligned_p;
361     if (align == 0)
362         return *p;
363     aligned_p = (__m64 *)((uintptr_t)p & ~7);
364     return (__m64) _mm_align_si64 (aligned_p[0], aligned_p[1], align);
365 #else
366     struct __una_u64 { __m64 x __attribute__((packed)); };
367     const struct __una_u64 *ptr = (const struct __una_u64 *) p;
368     return (__m64) ptr->x;
369 #endif
370 }
371
372 static force_inline uint32_t ldl_u(const uint32_t *p)
373 {
374 #ifdef USE_X86_MMX
375     /* x86's alignment restrictions are very relaxed. */
376     return *p;
377 #else
378     struct __una_u32 { uint32_t x __attribute__((packed)); };
379     const struct __una_u32 *ptr = (const struct __una_u32 *) p;
380     return ptr->x;
381 #endif
382 }
383
384 static force_inline __m64
385 load (const uint32_t *v)
386 {
387 #ifdef USE_LOONGSON_MMI
388     __m64 ret;
389     asm ("lwc1 %0, %1\n\t"
390         : "=f" (ret)
391         : "m" (*v)
392     );
393     return ret;
394 #else
395     return _mm_cvtsi32_si64 (*v);
396 #endif
397 }
398
399 static force_inline __m64
400 load8888 (const uint32_t *v)
401 {
402 #ifdef USE_LOONGSON_MMI
403     return _mm_unpacklo_pi8_f (*(__m32 *)v, _mm_setzero_si64 ());
404 #else
405     return _mm_unpacklo_pi8 (load (v), _mm_setzero_si64 ());
406 #endif
407 }
408
409 static force_inline __m64
410 load8888u (const uint32_t *v)
411 {
412     uint32_t l = ldl_u (v);
413     return load8888 (&l);
414 }
415
416 static force_inline __m64
417 pack8888 (__m64 lo, __m64 hi)
418 {
419     return _mm_packs_pu16 (lo, hi);
420 }
421
422 static force_inline void
423 store (uint32_t *dest, __m64 v)
424 {
425 #ifdef USE_LOONGSON_MMI
426     asm ("swc1 %1, %0\n\t"
427         : "=m" (*dest)
428         : "f" (v)
429         : "memory"
430     );
431 #else
432     *dest = _mm_cvtsi64_si32 (v);
433 #endif
434 }
435
436 static force_inline void
437 store8888 (uint32_t *dest, __m64 v)
438 {
439     v = pack8888 (v, _mm_setzero_si64 ());
440     store (dest, v);
441 }
442
443 static force_inline pixman_bool_t
444 is_equal (__m64 a, __m64 b)
445 {
446 #ifdef USE_LOONGSON_MMI
447     /* __m64 is double, we can compare directly. */
448     return a == b;
449 #else
450     return _mm_movemask_pi8 (_mm_cmpeq_pi8 (a, b)) == 0xff;
451 #endif
452 }
453
454 static force_inline pixman_bool_t
455 is_opaque (__m64 v)
456 {
457 #ifdef USE_LOONGSON_MMI
458     return is_equal (_mm_and_si64 (v, MC (full_alpha)), MC (full_alpha));
459 #else
460     __m64 ffs = _mm_cmpeq_pi8 (v, v);
461     return (_mm_movemask_pi8 (_mm_cmpeq_pi8 (v, ffs)) & 0x40);
462 #endif
463 }
464
465 static force_inline pixman_bool_t
466 is_zero (__m64 v)
467 {
468     return is_equal (v, _mm_setzero_si64 ());
469 }
470
471 /* Expand 16 bits positioned at @pos (0-3) of a mmx register into
472  *
473  *    00RR00GG00BB
474  *
475  * --- Expanding 565 in the low word ---
476  *
477  * m = (m << (32 - 3)) | (m << (16 - 5)) | m;
478  * m = m & (01f0003f001f);
479  * m = m * (008404100840);
480  * m = m >> 8;
481  *
482  * Note the trick here - the top word is shifted by another nibble to
483  * avoid it bumping into the middle word
484  */
485 static force_inline __m64
486 expand565 (__m64 pixel, int pos)
487 {
488     __m64 p = pixel;
489     __m64 t1, t2;
490
491     /* move pixel to low 16 bit and zero the rest */
492     p = shift (shift (p, (3 - pos) * 16), -48);
493
494     t1 = shift (p, 36 - 11);
495     t2 = shift (p, 16 - 5);
496
497     p = _mm_or_si64 (t1, p);
498     p = _mm_or_si64 (t2, p);
499     p = _mm_and_si64 (p, MC (565_rgb));
500
501     pixel = _mm_mullo_pi16 (p, MC (565_unpack_multiplier));
502     return _mm_srli_pi16 (pixel, 8);
503 }
504
505 static force_inline __m64
506 expand8888 (__m64 in, int pos)
507 {
508     if (pos == 0)
509         return _mm_unpacklo_pi8 (in, _mm_setzero_si64 ());
510     else
511         return _mm_unpackhi_pi8 (in, _mm_setzero_si64 ());
512 }
513
514 static force_inline __m64
515 expandx888 (__m64 in, int pos)
516 {
517     return _mm_or_si64 (expand8888 (in, pos), MC (full_alpha));
518 }
519
520 static force_inline __m64
521 pack_565 (__m64 pixel, __m64 target, int pos)
522 {
523     __m64 p = pixel;
524     __m64 t = target;
525     __m64 r, g, b;
526
527     r = _mm_and_si64 (p, MC (565_r));
528     g = _mm_and_si64 (p, MC (565_g));
529     b = _mm_and_si64 (p, MC (565_b));
530
531     r = shift (r, -(32 - 8) + pos * 16);
532     g = shift (g, -(16 - 3) + pos * 16);
533     b = shift (b, -(0  + 3) + pos * 16);
534
535     if (pos == 0)
536         t = _mm_and_si64 (t, MC (mask_0));
537     else if (pos == 1)
538         t = _mm_and_si64 (t, MC (mask_1));
539     else if (pos == 2)
540         t = _mm_and_si64 (t, MC (mask_2));
541     else if (pos == 3)
542         t = _mm_and_si64 (t, MC (mask_3));
543
544     p = _mm_or_si64 (r, t);
545     p = _mm_or_si64 (g, p);
546
547     return _mm_or_si64 (b, p);
548 }
549
550 #ifndef _MSC_VER
551
552 static force_inline __m64
553 pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b)
554 {
555     x = pix_multiply (x, a);
556     y = pix_multiply (y, b);
557
558     return pix_add (x, y);
559 }
560
561 #else
562
563 #define pix_add_mul(x, a, y, b)  \
564     ( x = pix_multiply (x, a),   \
565       y = pix_multiply (y, b),   \
566       pix_add (x, y) )
567
568 #endif
569
570 /* --------------- MMX code patch for fbcompose.c --------------------- */
571
572 static force_inline uint32_t
573 combine (const uint32_t *src, const uint32_t *mask)
574 {
575     uint32_t ssrc = *src;
576
577     if (mask)
578     {
579         __m64 m = load8888 (mask);
580         __m64 s = load8888 (&ssrc);
581
582         m = expand_alpha (m);
583         s = pix_multiply (s, m);
584
585         store8888 (&ssrc, s);
586     }
587
588     return ssrc;
589 }
590
591 static void
592 mmx_combine_over_u (pixman_implementation_t *imp,
593                     pixman_op_t              op,
594                     uint32_t *               dest,
595                     const uint32_t *         src,
596                     const uint32_t *         mask,
597                     int                      width)
598 {
599     const uint32_t *end = dest + width;
600
601     while (dest < end)
602     {
603         uint32_t ssrc = combine (src, mask);
604         uint32_t a = ssrc >> 24;
605
606         if (a == 0xff)
607         {
608             *dest = ssrc;
609         }
610         else if (ssrc)
611         {
612             __m64 s, sa;
613             s = load8888 (&ssrc);
614             sa = expand_alpha (s);
615             store8888 (dest, over (s, sa, load8888 (dest)));
616         }
617
618         ++dest;
619         ++src;
620         if (mask)
621             ++mask;
622     }
623     _mm_empty ();
624 }
625
626 static void
627 mmx_combine_over_reverse_u (pixman_implementation_t *imp,
628                             pixman_op_t              op,
629                             uint32_t *               dest,
630                             const uint32_t *         src,
631                             const uint32_t *         mask,
632                             int                      width)
633 {
634     const uint32_t *end = dest + width;
635
636     while (dest < end)
637     {
638         __m64 d, da;
639         uint32_t s = combine (src, mask);
640
641         d = load8888 (dest);
642         da = expand_alpha (d);
643         store8888 (dest, over (d, da, load8888 (&s)));
644
645         ++dest;
646         ++src;
647         if (mask)
648             mask++;
649     }
650     _mm_empty ();
651 }
652
653 static void
654 mmx_combine_in_u (pixman_implementation_t *imp,
655                   pixman_op_t              op,
656                   uint32_t *               dest,
657                   const uint32_t *         src,
658                   const uint32_t *         mask,
659                   int                      width)
660 {
661     const uint32_t *end = dest + width;
662
663     while (dest < end)
664     {
665         __m64 x, a;
666         uint32_t ssrc = combine (src, mask);
667
668         x = load8888 (&ssrc);
669         a = load8888 (dest);
670         a = expand_alpha (a);
671         x = pix_multiply (x, a);
672
673         store8888 (dest, x);
674
675         ++dest;
676         ++src;
677         if (mask)
678             mask++;
679     }
680     _mm_empty ();
681 }
682
683 static void
684 mmx_combine_in_reverse_u (pixman_implementation_t *imp,
685                           pixman_op_t              op,
686                           uint32_t *               dest,
687                           const uint32_t *         src,
688                           const uint32_t *         mask,
689                           int                      width)
690 {
691     const uint32_t *end = dest + width;
692
693     while (dest < end)
694     {
695         __m64 x, a;
696         uint32_t ssrc = combine (src, mask);
697
698         x = load8888 (dest);
699         a = load8888 (&ssrc);
700         a = expand_alpha (a);
701         x = pix_multiply (x, a);
702         store8888 (dest, x);
703
704         ++dest;
705         ++src;
706         if (mask)
707             mask++;
708     }
709     _mm_empty ();
710 }
711
712 static void
713 mmx_combine_out_u (pixman_implementation_t *imp,
714                    pixman_op_t              op,
715                    uint32_t *               dest,
716                    const uint32_t *         src,
717                    const uint32_t *         mask,
718                    int                      width)
719 {
720     const uint32_t *end = dest + width;
721
722     while (dest < end)
723     {
724         __m64 x, a;
725         uint32_t ssrc = combine (src, mask);
726
727         x = load8888 (&ssrc);
728         a = load8888 (dest);
729         a = expand_alpha (a);
730         a = negate (a);
731         x = pix_multiply (x, a);
732         store8888 (dest, x);
733
734         ++dest;
735         ++src;
736         if (mask)
737             mask++;
738     }
739     _mm_empty ();
740 }
741
742 static void
743 mmx_combine_out_reverse_u (pixman_implementation_t *imp,
744                            pixman_op_t              op,
745                            uint32_t *               dest,
746                            const uint32_t *         src,
747                            const uint32_t *         mask,
748                            int                      width)
749 {
750     const uint32_t *end = dest + width;
751
752     while (dest < end)
753     {
754         __m64 x, a;
755         uint32_t ssrc = combine (src, mask);
756
757         x = load8888 (dest);
758         a = load8888 (&ssrc);
759         a = expand_alpha (a);
760         a = negate (a);
761         x = pix_multiply (x, a);
762
763         store8888 (dest, x);
764
765         ++dest;
766         ++src;
767         if (mask)
768             mask++;
769     }
770     _mm_empty ();
771 }
772
773 static void
774 mmx_combine_atop_u (pixman_implementation_t *imp,
775                     pixman_op_t              op,
776                     uint32_t *               dest,
777                     const uint32_t *         src,
778                     const uint32_t *         mask,
779                     int                      width)
780 {
781     const uint32_t *end = dest + width;
782
783     while (dest < end)
784     {
785         __m64 s, da, d, sia;
786         uint32_t ssrc = combine (src, mask);
787
788         s = load8888 (&ssrc);
789         d = load8888 (dest);
790         sia = expand_alpha (s);
791         sia = negate (sia);
792         da = expand_alpha (d);
793         s = pix_add_mul (s, da, d, sia);
794         store8888 (dest, s);
795
796         ++dest;
797         ++src;
798         if (mask)
799             mask++;
800     }
801     _mm_empty ();
802 }
803
804 static void
805 mmx_combine_atop_reverse_u (pixman_implementation_t *imp,
806                             pixman_op_t              op,
807                             uint32_t *               dest,
808                             const uint32_t *         src,
809                             const uint32_t *         mask,
810                             int                      width)
811 {
812     const uint32_t *end;
813
814     end = dest + width;
815
816     while (dest < end)
817     {
818         __m64 s, dia, d, sa;
819         uint32_t ssrc = combine (src, mask);
820
821         s = load8888 (&ssrc);
822         d = load8888 (dest);
823         sa = expand_alpha (s);
824         dia = expand_alpha (d);
825         dia = negate (dia);
826         s = pix_add_mul (s, dia, d, sa);
827         store8888 (dest, s);
828
829         ++dest;
830         ++src;
831         if (mask)
832             mask++;
833     }
834     _mm_empty ();
835 }
836
837 static void
838 mmx_combine_xor_u (pixman_implementation_t *imp,
839                    pixman_op_t              op,
840                    uint32_t *               dest,
841                    const uint32_t *         src,
842                    const uint32_t *         mask,
843                    int                      width)
844 {
845     const uint32_t *end = dest + width;
846
847     while (dest < end)
848     {
849         __m64 s, dia, d, sia;
850         uint32_t ssrc = combine (src, mask);
851
852         s = load8888 (&ssrc);
853         d = load8888 (dest);
854         sia = expand_alpha (s);
855         dia = expand_alpha (d);
856         sia = negate (sia);
857         dia = negate (dia);
858         s = pix_add_mul (s, dia, d, sia);
859         store8888 (dest, s);
860
861         ++dest;
862         ++src;
863         if (mask)
864             mask++;
865     }
866     _mm_empty ();
867 }
868
869 static void
870 mmx_combine_add_u (pixman_implementation_t *imp,
871                    pixman_op_t              op,
872                    uint32_t *               dest,
873                    const uint32_t *         src,
874                    const uint32_t *         mask,
875                    int                      width)
876 {
877     const uint32_t *end = dest + width;
878
879     while (dest < end)
880     {
881         __m64 s, d;
882         uint32_t ssrc = combine (src, mask);
883
884         s = load8888 (&ssrc);
885         d = load8888 (dest);
886         s = pix_add (s, d);
887         store8888 (dest, s);
888
889         ++dest;
890         ++src;
891         if (mask)
892             mask++;
893     }
894     _mm_empty ();
895 }
896
897 static void
898 mmx_combine_saturate_u (pixman_implementation_t *imp,
899                         pixman_op_t              op,
900                         uint32_t *               dest,
901                         const uint32_t *         src,
902                         const uint32_t *         mask,
903                         int                      width)
904 {
905     const uint32_t *end = dest + width;
906
907     while (dest < end)
908     {
909         uint32_t s = combine (src, mask);
910         uint32_t d = *dest;
911         __m64 ms = load8888 (&s);
912         __m64 md = load8888 (&d);
913         uint32_t sa = s >> 24;
914         uint32_t da = ~d >> 24;
915
916         if (sa > da)
917         {
918             uint32_t quot = DIV_UN8 (da, sa) << 24;
919             __m64 msa = load8888 (&quot);
920             msa = expand_alpha (msa);
921             ms = pix_multiply (ms, msa);
922         }
923
924         md = pix_add (md, ms);
925         store8888 (dest, md);
926
927         ++src;
928         ++dest;
929         if (mask)
930             mask++;
931     }
932     _mm_empty ();
933 }
934
935 static void
936 mmx_combine_src_ca (pixman_implementation_t *imp,
937                     pixman_op_t              op,
938                     uint32_t *               dest,
939                     const uint32_t *         src,
940                     const uint32_t *         mask,
941                     int                      width)
942 {
943     const uint32_t *end = src + width;
944
945     while (src < end)
946     {
947         __m64 a = load8888 (mask);
948         __m64 s = load8888 (src);
949
950         s = pix_multiply (s, a);
951         store8888 (dest, s);
952
953         ++src;
954         ++mask;
955         ++dest;
956     }
957     _mm_empty ();
958 }
959
960 static void
961 mmx_combine_over_ca (pixman_implementation_t *imp,
962                      pixman_op_t              op,
963                      uint32_t *               dest,
964                      const uint32_t *         src,
965                      const uint32_t *         mask,
966                      int                      width)
967 {
968     const uint32_t *end = src + width;
969
970     while (src < end)
971     {
972         __m64 a = load8888 (mask);
973         __m64 s = load8888 (src);
974         __m64 d = load8888 (dest);
975         __m64 sa = expand_alpha (s);
976
977         store8888 (dest, in_over (s, sa, a, d));
978
979         ++src;
980         ++dest;
981         ++mask;
982     }
983     _mm_empty ();
984 }
985
986 static void
987 mmx_combine_over_reverse_ca (pixman_implementation_t *imp,
988                              pixman_op_t              op,
989                              uint32_t *               dest,
990                              const uint32_t *         src,
991                              const uint32_t *         mask,
992                              int                      width)
993 {
994     const uint32_t *end = src + width;
995
996     while (src < end)
997     {
998         __m64 a = load8888 (mask);
999         __m64 s = load8888 (src);
1000         __m64 d = load8888 (dest);
1001         __m64 da = expand_alpha (d);
1002
1003         store8888 (dest, over (d, da, in (s, a)));
1004
1005         ++src;
1006         ++dest;
1007         ++mask;
1008     }
1009     _mm_empty ();
1010 }
1011
1012 static void
1013 mmx_combine_in_ca (pixman_implementation_t *imp,
1014                    pixman_op_t              op,
1015                    uint32_t *               dest,
1016                    const uint32_t *         src,
1017                    const uint32_t *         mask,
1018                    int                      width)
1019 {
1020     const uint32_t *end = src + width;
1021
1022     while (src < end)
1023     {
1024         __m64 a = load8888 (mask);
1025         __m64 s = load8888 (src);
1026         __m64 d = load8888 (dest);
1027         __m64 da = expand_alpha (d);
1028
1029         s = pix_multiply (s, a);
1030         s = pix_multiply (s, da);
1031         store8888 (dest, s);
1032
1033         ++src;
1034         ++dest;
1035         ++mask;
1036     }
1037     _mm_empty ();
1038 }
1039
1040 static void
1041 mmx_combine_in_reverse_ca (pixman_implementation_t *imp,
1042                            pixman_op_t              op,
1043                            uint32_t *               dest,
1044                            const uint32_t *         src,
1045                            const uint32_t *         mask,
1046                            int                      width)
1047 {
1048     const uint32_t *end = src + width;
1049
1050     while (src < end)
1051     {
1052         __m64 a = load8888 (mask);
1053         __m64 s = load8888 (src);
1054         __m64 d = load8888 (dest);
1055         __m64 sa = expand_alpha (s);
1056
1057         a = pix_multiply (a, sa);
1058         d = pix_multiply (d, a);
1059         store8888 (dest, d);
1060
1061         ++src;
1062         ++dest;
1063         ++mask;
1064     }
1065     _mm_empty ();
1066 }
1067
1068 static void
1069 mmx_combine_out_ca (pixman_implementation_t *imp,
1070                     pixman_op_t              op,
1071                     uint32_t *               dest,
1072                     const uint32_t *         src,
1073                     const uint32_t *         mask,
1074                     int                      width)
1075 {
1076     const uint32_t *end = src + width;
1077
1078     while (src < end)
1079     {
1080         __m64 a = load8888 (mask);
1081         __m64 s = load8888 (src);
1082         __m64 d = load8888 (dest);
1083         __m64 da = expand_alpha (d);
1084
1085         da = negate (da);
1086         s = pix_multiply (s, a);
1087         s = pix_multiply (s, da);
1088         store8888 (dest, s);
1089
1090         ++src;
1091         ++dest;
1092         ++mask;
1093     }
1094     _mm_empty ();
1095 }
1096
1097 static void
1098 mmx_combine_out_reverse_ca (pixman_implementation_t *imp,
1099                             pixman_op_t              op,
1100                             uint32_t *               dest,
1101                             const uint32_t *         src,
1102                             const uint32_t *         mask,
1103                             int                      width)
1104 {
1105     const uint32_t *end = src + width;
1106
1107     while (src < end)
1108     {
1109         __m64 a = load8888 (mask);
1110         __m64 s = load8888 (src);
1111         __m64 d = load8888 (dest);
1112         __m64 sa = expand_alpha (s);
1113
1114         a = pix_multiply (a, sa);
1115         a = negate (a);
1116         d = pix_multiply (d, a);
1117         store8888 (dest, d);
1118
1119         ++src;
1120         ++dest;
1121         ++mask;
1122     }
1123     _mm_empty ();
1124 }
1125
1126 static void
1127 mmx_combine_atop_ca (pixman_implementation_t *imp,
1128                      pixman_op_t              op,
1129                      uint32_t *               dest,
1130                      const uint32_t *         src,
1131                      const uint32_t *         mask,
1132                      int                      width)
1133 {
1134     const uint32_t *end = src + width;
1135
1136     while (src < end)
1137     {
1138         __m64 a = load8888 (mask);
1139         __m64 s = load8888 (src);
1140         __m64 d = load8888 (dest);
1141         __m64 da = expand_alpha (d);
1142         __m64 sa = expand_alpha (s);
1143
1144         s = pix_multiply (s, a);
1145         a = pix_multiply (a, sa);
1146         a = negate (a);
1147         d = pix_add_mul (d, a, s, da);
1148         store8888 (dest, d);
1149
1150         ++src;
1151         ++dest;
1152         ++mask;
1153     }
1154     _mm_empty ();
1155 }
1156
1157 static void
1158 mmx_combine_atop_reverse_ca (pixman_implementation_t *imp,
1159                              pixman_op_t              op,
1160                              uint32_t *               dest,
1161                              const uint32_t *         src,
1162                              const uint32_t *         mask,
1163                              int                      width)
1164 {
1165     const uint32_t *end = src + width;
1166
1167     while (src < end)
1168     {
1169         __m64 a = load8888 (mask);
1170         __m64 s = load8888 (src);
1171         __m64 d = load8888 (dest);
1172         __m64 da = expand_alpha (d);
1173         __m64 sa = expand_alpha (s);
1174
1175         s = pix_multiply (s, a);
1176         a = pix_multiply (a, sa);
1177         da = negate (da);
1178         d = pix_add_mul (d, a, s, da);
1179         store8888 (dest, d);
1180
1181         ++src;
1182         ++dest;
1183         ++mask;
1184     }
1185     _mm_empty ();
1186 }
1187
1188 static void
1189 mmx_combine_xor_ca (pixman_implementation_t *imp,
1190                     pixman_op_t              op,
1191                     uint32_t *               dest,
1192                     const uint32_t *         src,
1193                     const uint32_t *         mask,
1194                     int                      width)
1195 {
1196     const uint32_t *end = src + width;
1197
1198     while (src < end)
1199     {
1200         __m64 a = load8888 (mask);
1201         __m64 s = load8888 (src);
1202         __m64 d = load8888 (dest);
1203         __m64 da = expand_alpha (d);
1204         __m64 sa = expand_alpha (s);
1205
1206         s = pix_multiply (s, a);
1207         a = pix_multiply (a, sa);
1208         da = negate (da);
1209         a = negate (a);
1210         d = pix_add_mul (d, a, s, da);
1211         store8888 (dest, d);
1212
1213         ++src;
1214         ++dest;
1215         ++mask;
1216     }
1217     _mm_empty ();
1218 }
1219
1220 static void
1221 mmx_combine_add_ca (pixman_implementation_t *imp,
1222                     pixman_op_t              op,
1223                     uint32_t *               dest,
1224                     const uint32_t *         src,
1225                     const uint32_t *         mask,
1226                     int                      width)
1227 {
1228     const uint32_t *end = src + width;
1229
1230     while (src < end)
1231     {
1232         __m64 a = load8888 (mask);
1233         __m64 s = load8888 (src);
1234         __m64 d = load8888 (dest);
1235
1236         s = pix_multiply (s, a);
1237         d = pix_add (s, d);
1238         store8888 (dest, d);
1239
1240         ++src;
1241         ++dest;
1242         ++mask;
1243     }
1244     _mm_empty ();
1245 }
1246
1247 /* ------------- MMX code paths called from fbpict.c -------------------- */
1248
1249 static void
1250 mmx_composite_over_n_8888 (pixman_implementation_t *imp,
1251                            pixman_composite_info_t *info)
1252 {
1253     PIXMAN_COMPOSITE_ARGS (info);
1254     uint32_t src;
1255     uint32_t    *dst_line, *dst;
1256     int32_t w;
1257     int dst_stride;
1258     __m64 vsrc, vsrca;
1259
1260     CHECKPOINT ();
1261
1262     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1263
1264     if (src == 0)
1265         return;
1266
1267     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1268
1269     vsrc = load8888 (&src);
1270     vsrca = expand_alpha (vsrc);
1271
1272     while (height--)
1273     {
1274         dst = dst_line;
1275         dst_line += dst_stride;
1276         w = width;
1277
1278         CHECKPOINT ();
1279
1280         while (w && (unsigned long)dst & 7)
1281         {
1282             store8888 (dst, over (vsrc, vsrca, load8888 (dst)));
1283
1284             w--;
1285             dst++;
1286         }
1287
1288         while (w >= 2)
1289         {
1290             __m64 vdest;
1291             __m64 dest0, dest1;
1292
1293             vdest = *(__m64 *)dst;
1294
1295             dest0 = over (vsrc, vsrca, expand8888 (vdest, 0));
1296             dest1 = over (vsrc, vsrca, expand8888 (vdest, 1));
1297
1298             *(__m64 *)dst = pack8888 (dest0, dest1);
1299
1300             dst += 2;
1301             w -= 2;
1302         }
1303
1304         CHECKPOINT ();
1305
1306         if (w)
1307         {
1308             store8888 (dst, over (vsrc, vsrca, load8888 (dst)));
1309         }
1310     }
1311
1312     _mm_empty ();
1313 }
1314
1315 static void
1316 mmx_composite_over_n_0565 (pixman_implementation_t *imp,
1317                            pixman_composite_info_t *info)
1318 {
1319     PIXMAN_COMPOSITE_ARGS (info);
1320     uint32_t src;
1321     uint16_t    *dst_line, *dst;
1322     int32_t w;
1323     int dst_stride;
1324     __m64 vsrc, vsrca;
1325
1326     CHECKPOINT ();
1327
1328     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1329
1330     if (src == 0)
1331         return;
1332
1333     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1334
1335     vsrc = load8888 (&src);
1336     vsrca = expand_alpha (vsrc);
1337
1338     while (height--)
1339     {
1340         dst = dst_line;
1341         dst_line += dst_stride;
1342         w = width;
1343
1344         CHECKPOINT ();
1345
1346         while (w && (unsigned long)dst & 7)
1347         {
1348             uint64_t d = *dst;
1349             __m64 vdest = expand565 (to_m64 (d), 0);
1350
1351             vdest = pack_565 (over (vsrc, vsrca, vdest), vdest, 0);
1352             *dst = to_uint64 (vdest);
1353
1354             w--;
1355             dst++;
1356         }
1357
1358         while (w >= 4)
1359         {
1360             __m64 vdest;
1361
1362             vdest = *(__m64 *)dst;
1363
1364             vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 0)), vdest, 0);
1365             vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 1)), vdest, 1);
1366             vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 2)), vdest, 2);
1367             vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 3)), vdest, 3);
1368
1369             *(__m64 *)dst = vdest;
1370
1371             dst += 4;
1372             w -= 4;
1373         }
1374
1375         CHECKPOINT ();
1376
1377         while (w)
1378         {
1379             uint64_t d = *dst;
1380             __m64 vdest = expand565 (to_m64 (d), 0);
1381
1382             vdest = pack_565 (over (vsrc, vsrca, vdest), vdest, 0);
1383             *dst = to_uint64 (vdest);
1384
1385             w--;
1386             dst++;
1387         }
1388     }
1389
1390     _mm_empty ();
1391 }
1392
1393 static void
1394 mmx_composite_over_n_8888_8888_ca (pixman_implementation_t *imp,
1395                                    pixman_composite_info_t *info)
1396 {
1397     PIXMAN_COMPOSITE_ARGS (info);
1398     uint32_t src;
1399     uint32_t    *dst_line;
1400     uint32_t    *mask_line;
1401     int dst_stride, mask_stride;
1402     __m64 vsrc, vsrca;
1403
1404     CHECKPOINT ();
1405
1406     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1407
1408     if (src == 0)
1409         return;
1410
1411     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1412     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
1413
1414     vsrc = load8888 (&src);
1415     vsrca = expand_alpha (vsrc);
1416
1417     while (height--)
1418     {
1419         int twidth = width;
1420         uint32_t *p = (uint32_t *)mask_line;
1421         uint32_t *q = (uint32_t *)dst_line;
1422
1423         while (twidth && (unsigned long)q & 7)
1424         {
1425             uint32_t m = *(uint32_t *)p;
1426
1427             if (m)
1428             {
1429                 __m64 vdest = load8888 (q);
1430                 vdest = in_over (vsrc, vsrca, load8888 (&m), vdest);
1431                 store8888 (q, vdest);
1432             }
1433
1434             twidth--;
1435             p++;
1436             q++;
1437         }
1438
1439         while (twidth >= 2)
1440         {
1441             uint32_t m0, m1;
1442             m0 = *p;
1443             m1 = *(p + 1);
1444
1445             if (m0 | m1)
1446             {
1447                 __m64 dest0, dest1;
1448                 __m64 vdest = *(__m64 *)q;
1449
1450                 dest0 = in_over (vsrc, vsrca, load8888 (&m0),
1451                                  expand8888 (vdest, 0));
1452                 dest1 = in_over (vsrc, vsrca, load8888 (&m1),
1453                                  expand8888 (vdest, 1));
1454
1455                 *(__m64 *)q = pack8888 (dest0, dest1);
1456             }
1457
1458             p += 2;
1459             q += 2;
1460             twidth -= 2;
1461         }
1462
1463         if (twidth)
1464         {
1465             uint32_t m = *(uint32_t *)p;
1466
1467             if (m)
1468             {
1469                 __m64 vdest = load8888 (q);
1470                 vdest = in_over (vsrc, vsrca, load8888 (&m), vdest);
1471                 store8888 (q, vdest);
1472             }
1473
1474             twidth--;
1475             p++;
1476             q++;
1477         }
1478
1479         dst_line += dst_stride;
1480         mask_line += mask_stride;
1481     }
1482
1483     _mm_empty ();
1484 }
1485
1486 static void
1487 mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp,
1488                                 pixman_composite_info_t *info)
1489 {
1490     PIXMAN_COMPOSITE_ARGS (info);
1491     uint32_t    *dst_line, *dst;
1492     uint32_t    *src_line, *src;
1493     uint32_t mask;
1494     __m64 vmask;
1495     int dst_stride, src_stride;
1496     int32_t w;
1497
1498     CHECKPOINT ();
1499
1500     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1501     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1502
1503     mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format);
1504     mask &= 0xff000000;
1505     mask = mask | mask >> 8 | mask >> 16 | mask >> 24;
1506     vmask = load8888 (&mask);
1507
1508     while (height--)
1509     {
1510         dst = dst_line;
1511         dst_line += dst_stride;
1512         src = src_line;
1513         src_line += src_stride;
1514         w = width;
1515
1516         while (w && (unsigned long)dst & 7)
1517         {
1518             __m64 s = load8888 (src);
1519             __m64 d = load8888 (dst);
1520
1521             store8888 (dst, in_over (s, expand_alpha (s), vmask, d));
1522
1523             w--;
1524             dst++;
1525             src++;
1526         }
1527
1528         while (w >= 2)
1529         {
1530             __m64 vs = ldq_u ((__m64 *)src);
1531             __m64 vd = *(__m64 *)dst;
1532             __m64 vsrc0 = expand8888 (vs, 0);
1533             __m64 vsrc1 = expand8888 (vs, 1);
1534
1535             *(__m64 *)dst = pack8888 (
1536                 in_over (vsrc0, expand_alpha (vsrc0), vmask, expand8888 (vd, 0)),
1537                 in_over (vsrc1, expand_alpha (vsrc1), vmask, expand8888 (vd, 1)));
1538
1539             w -= 2;
1540             dst += 2;
1541             src += 2;
1542         }
1543
1544         if (w)
1545         {
1546             __m64 s = load8888 (src);
1547             __m64 d = load8888 (dst);
1548
1549             store8888 (dst, in_over (s, expand_alpha (s), vmask, d));
1550         }
1551     }
1552
1553     _mm_empty ();
1554 }
1555
1556 static void
1557 mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp,
1558                                 pixman_composite_info_t *info)
1559 {
1560     PIXMAN_COMPOSITE_ARGS (info);
1561     uint32_t *dst_line, *dst;
1562     uint32_t *src_line, *src;
1563     uint32_t mask;
1564     __m64 vmask;
1565     int dst_stride, src_stride;
1566     int32_t w;
1567     __m64 srca;
1568
1569     CHECKPOINT ();
1570
1571     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1572     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1573     mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format);
1574
1575     mask &= 0xff000000;
1576     mask = mask | mask >> 8 | mask >> 16 | mask >> 24;
1577     vmask = load8888 (&mask);
1578     srca = MC (4x00ff);
1579
1580     while (height--)
1581     {
1582         dst = dst_line;
1583         dst_line += dst_stride;
1584         src = src_line;
1585         src_line += src_stride;
1586         w = width;
1587
1588         while (w && (unsigned long)dst & 7)
1589         {
1590             uint32_t ssrc = *src | 0xff000000;
1591             __m64 s = load8888 (&ssrc);
1592             __m64 d = load8888 (dst);
1593
1594             store8888 (dst, in_over (s, srca, vmask, d));
1595
1596             w--;
1597             dst++;
1598             src++;
1599         }
1600
1601         while (w >= 16)
1602         {
1603             __m64 vd0 = *(__m64 *)(dst + 0);
1604             __m64 vd1 = *(__m64 *)(dst + 2);
1605             __m64 vd2 = *(__m64 *)(dst + 4);
1606             __m64 vd3 = *(__m64 *)(dst + 6);
1607             __m64 vd4 = *(__m64 *)(dst + 8);
1608             __m64 vd5 = *(__m64 *)(dst + 10);
1609             __m64 vd6 = *(__m64 *)(dst + 12);
1610             __m64 vd7 = *(__m64 *)(dst + 14);
1611
1612             __m64 vs0 = ldq_u ((__m64 *)(src + 0));
1613             __m64 vs1 = ldq_u ((__m64 *)(src + 2));
1614             __m64 vs2 = ldq_u ((__m64 *)(src + 4));
1615             __m64 vs3 = ldq_u ((__m64 *)(src + 6));
1616             __m64 vs4 = ldq_u ((__m64 *)(src + 8));
1617             __m64 vs5 = ldq_u ((__m64 *)(src + 10));
1618             __m64 vs6 = ldq_u ((__m64 *)(src + 12));
1619             __m64 vs7 = ldq_u ((__m64 *)(src + 14));
1620
1621             vd0 = pack8888 (
1622                 in_over (expandx888 (vs0, 0), srca, vmask, expand8888 (vd0, 0)),
1623                 in_over (expandx888 (vs0, 1), srca, vmask, expand8888 (vd0, 1)));
1624
1625             vd1 = pack8888 (
1626                 in_over (expandx888 (vs1, 0), srca, vmask, expand8888 (vd1, 0)),
1627                 in_over (expandx888 (vs1, 1), srca, vmask, expand8888 (vd1, 1)));
1628
1629             vd2 = pack8888 (
1630                 in_over (expandx888 (vs2, 0), srca, vmask, expand8888 (vd2, 0)),
1631                 in_over (expandx888 (vs2, 1), srca, vmask, expand8888 (vd2, 1)));
1632
1633             vd3 = pack8888 (
1634                 in_over (expandx888 (vs3, 0), srca, vmask, expand8888 (vd3, 0)),
1635                 in_over (expandx888 (vs3, 1), srca, vmask, expand8888 (vd3, 1)));
1636
1637             vd4 = pack8888 (
1638                 in_over (expandx888 (vs4, 0), srca, vmask, expand8888 (vd4, 0)),
1639                 in_over (expandx888 (vs4, 1), srca, vmask, expand8888 (vd4, 1)));
1640
1641             vd5 = pack8888 (
1642                 in_over (expandx888 (vs5, 0), srca, vmask, expand8888 (vd5, 0)),
1643                 in_over (expandx888 (vs5, 1), srca, vmask, expand8888 (vd5, 1)));
1644
1645             vd6 = pack8888 (
1646                 in_over (expandx888 (vs6, 0), srca, vmask, expand8888 (vd6, 0)),
1647                 in_over (expandx888 (vs6, 1), srca, vmask, expand8888 (vd6, 1)));
1648
1649             vd7 = pack8888 (
1650                 in_over (expandx888 (vs7, 0), srca, vmask, expand8888 (vd7, 0)),
1651                 in_over (expandx888 (vs7, 1), srca, vmask, expand8888 (vd7, 1)));
1652
1653             *(__m64 *)(dst + 0) = vd0;
1654             *(__m64 *)(dst + 2) = vd1;
1655             *(__m64 *)(dst + 4) = vd2;
1656             *(__m64 *)(dst + 6) = vd3;
1657             *(__m64 *)(dst + 8) = vd4;
1658             *(__m64 *)(dst + 10) = vd5;
1659             *(__m64 *)(dst + 12) = vd6;
1660             *(__m64 *)(dst + 14) = vd7;
1661
1662             w -= 16;
1663             dst += 16;
1664             src += 16;
1665         }
1666
1667         while (w)
1668         {
1669             uint32_t ssrc = *src | 0xff000000;
1670             __m64 s = load8888 (&ssrc);
1671             __m64 d = load8888 (dst);
1672
1673             store8888 (dst, in_over (s, srca, vmask, d));
1674
1675             w--;
1676             dst++;
1677             src++;
1678         }
1679     }
1680
1681     _mm_empty ();
1682 }
1683
1684 static void
1685 mmx_composite_over_8888_8888 (pixman_implementation_t *imp,
1686                               pixman_composite_info_t *info)
1687 {
1688     PIXMAN_COMPOSITE_ARGS (info);
1689     uint32_t *dst_line, *dst;
1690     uint32_t *src_line, *src;
1691     uint32_t s;
1692     int dst_stride, src_stride;
1693     uint8_t a;
1694     int32_t w;
1695
1696     CHECKPOINT ();
1697
1698     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1699     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1700
1701     while (height--)
1702     {
1703         dst = dst_line;
1704         dst_line += dst_stride;
1705         src = src_line;
1706         src_line += src_stride;
1707         w = width;
1708
1709         while (w--)
1710         {
1711             s = *src++;
1712             a = s >> 24;
1713
1714             if (a == 0xff)
1715             {
1716                 *dst = s;
1717             }
1718             else if (s)
1719             {
1720                 __m64 ms, sa;
1721                 ms = load8888 (&s);
1722                 sa = expand_alpha (ms);
1723                 store8888 (dst, over (ms, sa, load8888 (dst)));
1724             }
1725
1726             dst++;
1727         }
1728     }
1729     _mm_empty ();
1730 }
1731
1732 static void
1733 mmx_composite_over_8888_0565 (pixman_implementation_t *imp,
1734                               pixman_composite_info_t *info)
1735 {
1736     PIXMAN_COMPOSITE_ARGS (info);
1737     uint16_t    *dst_line, *dst;
1738     uint32_t    *src_line, *src;
1739     int dst_stride, src_stride;
1740     int32_t w;
1741
1742     CHECKPOINT ();
1743
1744     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1745     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1746
1747 #if 0
1748     /* FIXME */
1749     assert (src_image->drawable == mask_image->drawable);
1750 #endif
1751
1752     while (height--)
1753     {
1754         dst = dst_line;
1755         dst_line += dst_stride;
1756         src = src_line;
1757         src_line += src_stride;
1758         w = width;
1759
1760         CHECKPOINT ();
1761
1762         while (w && (unsigned long)dst & 7)
1763         {
1764             __m64 vsrc = load8888 (src);
1765             uint64_t d = *dst;
1766             __m64 vdest = expand565 (to_m64 (d), 0);
1767
1768             vdest = pack_565 (
1769                 over (vsrc, expand_alpha (vsrc), vdest), vdest, 0);
1770
1771             *dst = to_uint64 (vdest);
1772
1773             w--;
1774             dst++;
1775             src++;
1776         }
1777
1778         CHECKPOINT ();
1779
1780         while (w >= 4)
1781         {
1782             __m64 vsrc0, vsrc1, vsrc2, vsrc3;
1783             __m64 vdest;
1784
1785             vsrc0 = load8888 ((src + 0));
1786             vsrc1 = load8888 ((src + 1));
1787             vsrc2 = load8888 ((src + 2));
1788             vsrc3 = load8888 ((src + 3));
1789
1790             vdest = *(__m64 *)dst;
1791
1792             vdest = pack_565 (over (vsrc0, expand_alpha (vsrc0), expand565 (vdest, 0)), vdest, 0);
1793             vdest = pack_565 (over (vsrc1, expand_alpha (vsrc1), expand565 (vdest, 1)), vdest, 1);
1794             vdest = pack_565 (over (vsrc2, expand_alpha (vsrc2), expand565 (vdest, 2)), vdest, 2);
1795             vdest = pack_565 (over (vsrc3, expand_alpha (vsrc3), expand565 (vdest, 3)), vdest, 3);
1796
1797             *(__m64 *)dst = vdest;
1798
1799             w -= 4;
1800             dst += 4;
1801             src += 4;
1802         }
1803
1804         CHECKPOINT ();
1805
1806         while (w)
1807         {
1808             __m64 vsrc = load8888 (src);
1809             uint64_t d = *dst;
1810             __m64 vdest = expand565 (to_m64 (d), 0);
1811
1812             vdest = pack_565 (over (vsrc, expand_alpha (vsrc), vdest), vdest, 0);
1813
1814             *dst = to_uint64 (vdest);
1815
1816             w--;
1817             dst++;
1818             src++;
1819         }
1820     }
1821
1822     _mm_empty ();
1823 }
1824
1825 static void
1826 mmx_composite_over_n_8_8888 (pixman_implementation_t *imp,
1827                              pixman_composite_info_t *info)
1828 {
1829     PIXMAN_COMPOSITE_ARGS (info);
1830     uint32_t src, srca;
1831     uint32_t *dst_line, *dst;
1832     uint8_t *mask_line, *mask;
1833     int dst_stride, mask_stride;
1834     int32_t w;
1835     __m64 vsrc, vsrca;
1836     uint64_t srcsrc;
1837
1838     CHECKPOINT ();
1839
1840     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1841
1842     srca = src >> 24;
1843     if (src == 0)
1844         return;
1845
1846     srcsrc = (uint64_t)src << 32 | src;
1847
1848     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1849     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
1850
1851     vsrc = load8888 (&src);
1852     vsrca = expand_alpha (vsrc);
1853
1854     while (height--)
1855     {
1856         dst = dst_line;
1857         dst_line += dst_stride;
1858         mask = mask_line;
1859         mask_line += mask_stride;
1860         w = width;
1861
1862         CHECKPOINT ();
1863
1864         while (w && (unsigned long)dst & 7)
1865         {
1866             uint64_t m = *mask;
1867
1868             if (m)
1869             {
1870                 __m64 vdest = in_over (vsrc, vsrca,
1871                                        expand_alpha_rev (to_m64 (m)),
1872                                        load8888 (dst));
1873
1874                 store8888 (dst, vdest);
1875             }
1876
1877             w--;
1878             mask++;
1879             dst++;
1880         }
1881
1882         CHECKPOINT ();
1883
1884         while (w >= 2)
1885         {
1886             uint64_t m0, m1;
1887
1888             m0 = *mask;
1889             m1 = *(mask + 1);
1890
1891             if (srca == 0xff && (m0 & m1) == 0xff)
1892             {
1893                 *(uint64_t *)dst = srcsrc;
1894             }
1895             else if (m0 | m1)
1896             {
1897                 __m64 vdest;
1898                 __m64 dest0, dest1;
1899
1900                 vdest = *(__m64 *)dst;
1901
1902                 dest0 = in_over (vsrc, vsrca, expand_alpha_rev (to_m64 (m0)),
1903                                  expand8888 (vdest, 0));
1904                 dest1 = in_over (vsrc, vsrca, expand_alpha_rev (to_m64 (m1)),
1905                                  expand8888 (vdest, 1));
1906
1907                 *(__m64 *)dst = pack8888 (dest0, dest1);
1908             }
1909
1910             mask += 2;
1911             dst += 2;
1912             w -= 2;
1913         }
1914
1915         CHECKPOINT ();
1916
1917         if (w)
1918         {
1919             uint64_t m = *mask;
1920
1921             if (m)
1922             {
1923                 __m64 vdest = load8888 (dst);
1924
1925                 vdest = in_over (
1926                     vsrc, vsrca, expand_alpha_rev (to_m64 (m)), vdest);
1927                 store8888 (dst, vdest);
1928             }
1929         }
1930     }
1931
1932     _mm_empty ();
1933 }
1934
1935 pixman_bool_t
1936 pixman_fill_mmx (uint32_t *bits,
1937                  int       stride,
1938                  int       bpp,
1939                  int       x,
1940                  int       y,
1941                  int       width,
1942                  int       height,
1943                  uint32_t xor)
1944 {
1945     uint64_t fill;
1946     __m64 vfill;
1947     uint32_t byte_width;
1948     uint8_t     *byte_line;
1949
1950 #if defined __GNUC__ && defined USE_X86_MMX
1951     __m64 v1, v2, v3, v4, v5, v6, v7;
1952 #endif
1953
1954     if (bpp != 16 && bpp != 32 && bpp != 8)
1955         return FALSE;
1956
1957     if (bpp == 8)
1958     {
1959         stride = stride * (int) sizeof (uint32_t) / 1;
1960         byte_line = (uint8_t *)(((uint8_t *)bits) + stride * y + x);
1961         byte_width = width;
1962         stride *= 1;
1963         xor = (xor & 0xff) * 0x01010101;
1964     }
1965     else if (bpp == 16)
1966     {
1967         stride = stride * (int) sizeof (uint32_t) / 2;
1968         byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x);
1969         byte_width = 2 * width;
1970         stride *= 2;
1971         xor = (xor & 0xffff) * 0x00010001;
1972     }
1973     else
1974     {
1975         stride = stride * (int) sizeof (uint32_t) / 4;
1976         byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x);
1977         byte_width = 4 * width;
1978         stride *= 4;
1979     }
1980
1981     fill = ((uint64_t)xor << 32) | xor;
1982     vfill = to_m64 (fill);
1983
1984 #if defined __GNUC__ && defined USE_X86_MMX
1985     __asm__ (
1986         "movq           %7,     %0\n"
1987         "movq           %7,     %1\n"
1988         "movq           %7,     %2\n"
1989         "movq           %7,     %3\n"
1990         "movq           %7,     %4\n"
1991         "movq           %7,     %5\n"
1992         "movq           %7,     %6\n"
1993         : "=&y" (v1), "=&y" (v2), "=&y" (v3),
1994           "=&y" (v4), "=&y" (v5), "=&y" (v6), "=y" (v7)
1995         : "y" (vfill));
1996 #endif
1997
1998     while (height--)
1999     {
2000         int w;
2001         uint8_t *d = byte_line;
2002
2003         byte_line += stride;
2004         w = byte_width;
2005
2006         if (w >= 1 && ((unsigned long)d & 1))
2007         {
2008             *(uint8_t *)d = (xor & 0xff);
2009             w--;
2010             d++;
2011         }
2012
2013         if (w >= 2 && ((unsigned long)d & 3))
2014         {
2015             *(uint16_t *)d = xor;
2016             w -= 2;
2017             d += 2;
2018         }
2019
2020         while (w >= 4 && ((unsigned long)d & 7))
2021         {
2022             *(uint32_t *)d = xor;
2023
2024             w -= 4;
2025             d += 4;
2026         }
2027
2028         while (w >= 64)
2029         {
2030 #if defined __GNUC__ && defined USE_X86_MMX
2031             __asm__ (
2032                 "movq   %1,       (%0)\n"
2033                 "movq   %2,      8(%0)\n"
2034                 "movq   %3,     16(%0)\n"
2035                 "movq   %4,     24(%0)\n"
2036                 "movq   %5,     32(%0)\n"
2037                 "movq   %6,     40(%0)\n"
2038                 "movq   %7,     48(%0)\n"
2039                 "movq   %8,     56(%0)\n"
2040                 :
2041                 : "r" (d),
2042                   "y" (vfill), "y" (v1), "y" (v2), "y" (v3),
2043                   "y" (v4), "y" (v5), "y" (v6), "y" (v7)
2044                 : "memory");
2045 #else
2046             *(__m64*) (d +  0) = vfill;
2047             *(__m64*) (d +  8) = vfill;
2048             *(__m64*) (d + 16) = vfill;
2049             *(__m64*) (d + 24) = vfill;
2050             *(__m64*) (d + 32) = vfill;
2051             *(__m64*) (d + 40) = vfill;
2052             *(__m64*) (d + 48) = vfill;
2053             *(__m64*) (d + 56) = vfill;
2054 #endif
2055             w -= 64;
2056             d += 64;
2057         }
2058
2059         while (w >= 4)
2060         {
2061             *(uint32_t *)d = xor;
2062
2063             w -= 4;
2064             d += 4;
2065         }
2066         if (w >= 2)
2067         {
2068             *(uint16_t *)d = xor;
2069             w -= 2;
2070             d += 2;
2071         }
2072         if (w >= 1)
2073         {
2074             *(uint8_t *)d = (xor & 0xff);
2075             w--;
2076             d++;
2077         }
2078
2079     }
2080
2081     _mm_empty ();
2082     return TRUE;
2083 }
2084
2085 static void
2086 mmx_composite_src_n_8_8888 (pixman_implementation_t *imp,
2087                             pixman_composite_info_t *info)
2088 {
2089     PIXMAN_COMPOSITE_ARGS (info);
2090     uint32_t src, srca;
2091     uint32_t    *dst_line, *dst;
2092     uint8_t     *mask_line, *mask;
2093     int dst_stride, mask_stride;
2094     int32_t w;
2095     __m64 vsrc;
2096     uint64_t srcsrc;
2097
2098     CHECKPOINT ();
2099
2100     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2101
2102     srca = src >> 24;
2103     if (src == 0)
2104     {
2105         pixman_fill_mmx (dest_image->bits.bits, dest_image->bits.rowstride,
2106                          PIXMAN_FORMAT_BPP (dest_image->bits.format),
2107                          dest_x, dest_y, width, height, 0);
2108         return;
2109     }
2110
2111     srcsrc = (uint64_t)src << 32 | src;
2112
2113     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
2114     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2115
2116     vsrc = load8888 (&src);
2117
2118     while (height--)
2119     {
2120         dst = dst_line;
2121         dst_line += dst_stride;
2122         mask = mask_line;
2123         mask_line += mask_stride;
2124         w = width;
2125
2126         CHECKPOINT ();
2127
2128         while (w && (unsigned long)dst & 7)
2129         {
2130             uint64_t m = *mask;
2131
2132             if (m)
2133             {
2134                 __m64 vdest = in (vsrc, expand_alpha_rev (to_m64 (m)));
2135
2136                 store8888 (dst, vdest);
2137             }
2138             else
2139             {
2140                 *dst = 0;
2141             }
2142
2143             w--;
2144             mask++;
2145             dst++;
2146         }
2147
2148         CHECKPOINT ();
2149
2150         while (w >= 2)
2151         {
2152             uint64_t m0, m1;
2153             m0 = *mask;
2154             m1 = *(mask + 1);
2155
2156             if (srca == 0xff && (m0 & m1) == 0xff)
2157             {
2158                 *(uint64_t *)dst = srcsrc;
2159             }
2160             else if (m0 | m1)
2161             {
2162                 __m64 dest0, dest1;
2163
2164                 dest0 = in (vsrc, expand_alpha_rev (to_m64 (m0)));
2165                 dest1 = in (vsrc, expand_alpha_rev (to_m64 (m1)));
2166
2167                 *(__m64 *)dst = pack8888 (dest0, dest1);
2168             }
2169             else
2170             {
2171                 *(uint64_t *)dst = 0;
2172             }
2173
2174             mask += 2;
2175             dst += 2;
2176             w -= 2;
2177         }
2178
2179         CHECKPOINT ();
2180
2181         if (w)
2182         {
2183             uint64_t m = *mask;
2184
2185             if (m)
2186             {
2187                 __m64 vdest = load8888 (dst);
2188
2189                 vdest = in (vsrc, expand_alpha_rev (to_m64 (m)));
2190                 store8888 (dst, vdest);
2191             }
2192             else
2193             {
2194                 *dst = 0;
2195             }
2196         }
2197     }
2198
2199     _mm_empty ();
2200 }
2201
2202 static void
2203 mmx_composite_over_n_8_0565 (pixman_implementation_t *imp,
2204                              pixman_composite_info_t *info)
2205 {
2206     PIXMAN_COMPOSITE_ARGS (info);
2207     uint32_t src, srca;
2208     uint16_t *dst_line, *dst;
2209     uint8_t *mask_line, *mask;
2210     int dst_stride, mask_stride;
2211     int32_t w;
2212     __m64 vsrc, vsrca, tmp;
2213     __m64 srcsrcsrcsrc;
2214
2215     CHECKPOINT ();
2216
2217     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2218
2219     srca = src >> 24;
2220     if (src == 0)
2221         return;
2222
2223     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2224     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2225
2226     vsrc = load8888 (&src);
2227     vsrca = expand_alpha (vsrc);
2228
2229     tmp = pack_565 (vsrc, _mm_setzero_si64 (), 0);
2230     srcsrcsrcsrc = expand_alpha_rev (tmp);
2231
2232     while (height--)
2233     {
2234         dst = dst_line;
2235         dst_line += dst_stride;
2236         mask = mask_line;
2237         mask_line += mask_stride;
2238         w = width;
2239
2240         CHECKPOINT ();
2241
2242         while (w && (unsigned long)dst & 7)
2243         {
2244             uint64_t m = *mask;
2245
2246             if (m)
2247             {
2248                 uint64_t d = *dst;
2249                 __m64 vd = to_m64 (d);
2250                 __m64 vdest = in_over (
2251                     vsrc, vsrca, expand_alpha_rev (to_m64 (m)), expand565 (vd, 0));
2252
2253                 vd = pack_565 (vdest, _mm_setzero_si64 (), 0);
2254                 *dst = to_uint64 (vd);
2255             }
2256
2257             w--;
2258             mask++;
2259             dst++;
2260         }
2261
2262         CHECKPOINT ();
2263
2264         while (w >= 4)
2265         {
2266             uint64_t m0, m1, m2, m3;
2267             m0 = *mask;
2268             m1 = *(mask + 1);
2269             m2 = *(mask + 2);
2270             m3 = *(mask + 3);
2271
2272             if (srca == 0xff && (m0 & m1 & m2 & m3) == 0xff)
2273             {
2274                 *(__m64 *)dst = srcsrcsrcsrc;
2275             }
2276             else if (m0 | m1 | m2 | m3)
2277             {
2278                 __m64 vdest;
2279                 __m64 vm0, vm1, vm2, vm3;
2280
2281                 vdest = *(__m64 *)dst;
2282
2283                 vm0 = to_m64 (m0);
2284                 vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm0),
2285                                            expand565 (vdest, 0)), vdest, 0);
2286                 vm1 = to_m64 (m1);
2287                 vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm1),
2288                                            expand565 (vdest, 1)), vdest, 1);
2289                 vm2 = to_m64 (m2);
2290                 vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm2),
2291                                            expand565 (vdest, 2)), vdest, 2);
2292                 vm3 = to_m64 (m3);
2293                 vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm3),
2294                                            expand565 (vdest, 3)), vdest, 3);
2295
2296                 *(__m64 *)dst = vdest;
2297             }
2298
2299             w -= 4;
2300             mask += 4;
2301             dst += 4;
2302         }
2303
2304         CHECKPOINT ();
2305
2306         while (w)
2307         {
2308             uint64_t m = *mask;
2309
2310             if (m)
2311             {
2312                 uint64_t d = *dst;
2313                 __m64 vd = to_m64 (d);
2314                 __m64 vdest = in_over (vsrc, vsrca, expand_alpha_rev (to_m64 (m)),
2315                                        expand565 (vd, 0));
2316                 vd = pack_565 (vdest, _mm_setzero_si64 (), 0);
2317                 *dst = to_uint64 (vd);
2318             }
2319
2320             w--;
2321             mask++;
2322             dst++;
2323         }
2324     }
2325
2326     _mm_empty ();
2327 }
2328
2329 static void
2330 mmx_composite_over_pixbuf_0565 (pixman_implementation_t *imp,
2331                                 pixman_composite_info_t *info)
2332 {
2333     PIXMAN_COMPOSITE_ARGS (info);
2334     uint16_t    *dst_line, *dst;
2335     uint32_t    *src_line, *src;
2336     int dst_stride, src_stride;
2337     int32_t w;
2338
2339     CHECKPOINT ();
2340
2341     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2342     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2343
2344 #if 0
2345     /* FIXME */
2346     assert (src_image->drawable == mask_image->drawable);
2347 #endif
2348
2349     while (height--)
2350     {
2351         dst = dst_line;
2352         dst_line += dst_stride;
2353         src = src_line;
2354         src_line += src_stride;
2355         w = width;
2356
2357         CHECKPOINT ();
2358
2359         while (w && (unsigned long)dst & 7)
2360         {
2361             __m64 vsrc = load8888 (src);
2362             uint64_t d = *dst;
2363             __m64 vdest = expand565 (to_m64 (d), 0);
2364
2365             vdest = pack_565 (over_rev_non_pre (vsrc, vdest), vdest, 0);
2366
2367             *dst = to_uint64 (vdest);
2368
2369             w--;
2370             dst++;
2371             src++;
2372         }
2373
2374         CHECKPOINT ();
2375
2376         while (w >= 4)
2377         {
2378             uint32_t s0, s1, s2, s3;
2379             unsigned char a0, a1, a2, a3;
2380
2381             s0 = *src;
2382             s1 = *(src + 1);
2383             s2 = *(src + 2);
2384             s3 = *(src + 3);
2385
2386             a0 = (s0 >> 24);
2387             a1 = (s1 >> 24);
2388             a2 = (s2 >> 24);
2389             a3 = (s3 >> 24);
2390
2391             if ((a0 & a1 & a2 & a3) == 0xFF)
2392             {
2393                 __m64 vdest;
2394                 vdest = pack_565 (invert_colors (load8888 (&s0)), _mm_setzero_si64 (), 0);
2395                 vdest = pack_565 (invert_colors (load8888 (&s1)), vdest, 1);
2396                 vdest = pack_565 (invert_colors (load8888 (&s2)), vdest, 2);
2397                 vdest = pack_565 (invert_colors (load8888 (&s3)), vdest, 3);
2398
2399                 *(__m64 *)dst = vdest;
2400             }
2401             else if (s0 | s1 | s2 | s3)
2402             {
2403                 __m64 vdest = *(__m64 *)dst;
2404
2405                 vdest = pack_565 (over_rev_non_pre (load8888 (&s0), expand565 (vdest, 0)), vdest, 0);
2406                 vdest = pack_565 (over_rev_non_pre (load8888 (&s1), expand565 (vdest, 1)), vdest, 1);
2407                 vdest = pack_565 (over_rev_non_pre (load8888 (&s2), expand565 (vdest, 2)), vdest, 2);
2408                 vdest = pack_565 (over_rev_non_pre (load8888 (&s3), expand565 (vdest, 3)), vdest, 3);
2409
2410                 *(__m64 *)dst = vdest;
2411             }
2412
2413             w -= 4;
2414             dst += 4;
2415             src += 4;
2416         }
2417
2418         CHECKPOINT ();
2419
2420         while (w)
2421         {
2422             __m64 vsrc = load8888 (src);
2423             uint64_t d = *dst;
2424             __m64 vdest = expand565 (to_m64 (d), 0);
2425
2426             vdest = pack_565 (over_rev_non_pre (vsrc, vdest), vdest, 0);
2427
2428             *dst = to_uint64 (vdest);
2429
2430             w--;
2431             dst++;
2432             src++;
2433         }
2434     }
2435
2436     _mm_empty ();
2437 }
2438
2439 static void
2440 mmx_composite_over_pixbuf_8888 (pixman_implementation_t *imp,
2441                                 pixman_composite_info_t *info)
2442 {
2443     PIXMAN_COMPOSITE_ARGS (info);
2444     uint32_t    *dst_line, *dst;
2445     uint32_t    *src_line, *src;
2446     int dst_stride, src_stride;
2447     int32_t w;
2448
2449     CHECKPOINT ();
2450
2451     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
2452     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2453
2454 #if 0
2455     /* FIXME */
2456     assert (src_image->drawable == mask_image->drawable);
2457 #endif
2458
2459     while (height--)
2460     {
2461         dst = dst_line;
2462         dst_line += dst_stride;
2463         src = src_line;
2464         src_line += src_stride;
2465         w = width;
2466
2467         while (w && (unsigned long)dst & 7)
2468         {
2469             __m64 s = load8888 (src);
2470             __m64 d = load8888 (dst);
2471
2472             store8888 (dst, over_rev_non_pre (s, d));
2473
2474             w--;
2475             dst++;
2476             src++;
2477         }
2478
2479         while (w >= 2)
2480         {
2481             uint32_t s0, s1;
2482             unsigned char a0, a1;
2483             __m64 d0, d1;
2484
2485             s0 = *src;
2486             s1 = *(src + 1);
2487
2488             a0 = (s0 >> 24);
2489             a1 = (s1 >> 24);
2490
2491             if ((a0 & a1) == 0xFF)
2492             {
2493                 d0 = invert_colors (load8888 (&s0));
2494                 d1 = invert_colors (load8888 (&s1));
2495
2496                 *(__m64 *)dst = pack8888 (d0, d1);
2497             }
2498             else if (s0 | s1)
2499             {
2500                 __m64 vdest = *(__m64 *)dst;
2501
2502                 d0 = over_rev_non_pre (load8888 (&s0), expand8888 (vdest, 0));
2503                 d1 = over_rev_non_pre (load8888 (&s1), expand8888 (vdest, 1));
2504
2505                 *(__m64 *)dst = pack8888 (d0, d1);
2506             }
2507
2508             w -= 2;
2509             dst += 2;
2510             src += 2;
2511         }
2512
2513         if (w)
2514         {
2515             __m64 s = load8888 (src);
2516             __m64 d = load8888 (dst);
2517
2518             store8888 (dst, over_rev_non_pre (s, d));
2519         }
2520     }
2521
2522     _mm_empty ();
2523 }
2524
2525 static void
2526 mmx_composite_over_n_8888_0565_ca (pixman_implementation_t *imp,
2527                                    pixman_composite_info_t *info)
2528 {
2529     PIXMAN_COMPOSITE_ARGS (info);
2530     uint32_t src;
2531     uint16_t    *dst_line;
2532     uint32_t    *mask_line;
2533     int dst_stride, mask_stride;
2534     __m64 vsrc, vsrca;
2535
2536     CHECKPOINT ();
2537
2538     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2539
2540     if (src == 0)
2541         return;
2542
2543     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2544     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
2545
2546     vsrc = load8888 (&src);
2547     vsrca = expand_alpha (vsrc);
2548
2549     while (height--)
2550     {
2551         int twidth = width;
2552         uint32_t *p = (uint32_t *)mask_line;
2553         uint16_t *q = (uint16_t *)dst_line;
2554
2555         while (twidth && ((unsigned long)q & 7))
2556         {
2557             uint32_t m = *(uint32_t *)p;
2558
2559             if (m)
2560             {
2561                 uint64_t d = *q;
2562                 __m64 vdest = expand565 (to_m64 (d), 0);
2563                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m), vdest), vdest, 0);
2564                 *q = to_uint64 (vdest);
2565             }
2566
2567             twidth--;
2568             p++;
2569             q++;
2570         }
2571
2572         while (twidth >= 4)
2573         {
2574             uint32_t m0, m1, m2, m3;
2575
2576             m0 = *p;
2577             m1 = *(p + 1);
2578             m2 = *(p + 2);
2579             m3 = *(p + 3);
2580
2581             if ((m0 | m1 | m2 | m3))
2582             {
2583                 __m64 vdest = *(__m64 *)q;
2584
2585                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m0), expand565 (vdest, 0)), vdest, 0);
2586                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m1), expand565 (vdest, 1)), vdest, 1);
2587                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m2), expand565 (vdest, 2)), vdest, 2);
2588                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m3), expand565 (vdest, 3)), vdest, 3);
2589
2590                 *(__m64 *)q = vdest;
2591             }
2592             twidth -= 4;
2593             p += 4;
2594             q += 4;
2595         }
2596
2597         while (twidth)
2598         {
2599             uint32_t m;
2600
2601             m = *(uint32_t *)p;
2602             if (m)
2603             {
2604                 uint64_t d = *q;
2605                 __m64 vdest = expand565 (to_m64 (d), 0);
2606                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m), vdest), vdest, 0);
2607                 *q = to_uint64 (vdest);
2608             }
2609
2610             twidth--;
2611             p++;
2612             q++;
2613         }
2614
2615         mask_line += mask_stride;
2616         dst_line += dst_stride;
2617     }
2618
2619     _mm_empty ();
2620 }
2621
2622 static void
2623 mmx_composite_in_n_8_8 (pixman_implementation_t *imp,
2624                         pixman_composite_info_t *info)
2625 {
2626     PIXMAN_COMPOSITE_ARGS (info);
2627     uint8_t *dst_line, *dst;
2628     uint8_t *mask_line, *mask;
2629     int dst_stride, mask_stride;
2630     int32_t w;
2631     uint32_t src;
2632     uint8_t sa;
2633     __m64 vsrc, vsrca;
2634
2635     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2636     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2637
2638     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2639
2640     sa = src >> 24;
2641
2642     vsrc = load8888 (&src);
2643     vsrca = expand_alpha (vsrc);
2644
2645     while (height--)
2646     {
2647         dst = dst_line;
2648         dst_line += dst_stride;
2649         mask = mask_line;
2650         mask_line += mask_stride;
2651         w = width;
2652
2653         while (w && (unsigned long)dst & 7)
2654         {
2655             uint16_t tmp;
2656             uint8_t a;
2657             uint32_t m, d;
2658
2659             a = *mask++;
2660             d = *dst;
2661
2662             m = MUL_UN8 (sa, a, tmp);
2663             d = MUL_UN8 (m, d, tmp);
2664
2665             *dst++ = d;
2666             w--;
2667         }
2668
2669         while (w >= 4)
2670         {
2671             __m64 vmask;
2672             __m64 vdest;
2673
2674             vmask = load8888u ((uint32_t *)mask);
2675             vdest = load8888 ((uint32_t *)dst);
2676
2677             store8888 ((uint32_t *)dst, in (in (vsrca, vmask), vdest));
2678
2679             dst += 4;
2680             mask += 4;
2681             w -= 4;
2682         }
2683
2684         while (w--)
2685         {
2686             uint16_t tmp;
2687             uint8_t a;
2688             uint32_t m, d;
2689
2690             a = *mask++;
2691             d = *dst;
2692
2693             m = MUL_UN8 (sa, a, tmp);
2694             d = MUL_UN8 (m, d, tmp);
2695
2696             *dst++ = d;
2697         }
2698     }
2699
2700     _mm_empty ();
2701 }
2702
2703 static void
2704 mmx_composite_in_8_8 (pixman_implementation_t *imp,
2705                       pixman_composite_info_t *info)
2706 {
2707     PIXMAN_COMPOSITE_ARGS (info);
2708     uint8_t     *dst_line, *dst;
2709     uint8_t     *src_line, *src;
2710     int src_stride, dst_stride;
2711     int32_t w;
2712
2713     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2714     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
2715
2716     while (height--)
2717     {
2718         dst = dst_line;
2719         dst_line += dst_stride;
2720         src = src_line;
2721         src_line += src_stride;
2722         w = width;
2723
2724         while (w && (unsigned long)dst & 3)
2725         {
2726             uint8_t s, d;
2727             uint16_t tmp;
2728
2729             s = *src;
2730             d = *dst;
2731
2732             *dst = MUL_UN8 (s, d, tmp);
2733
2734             src++;
2735             dst++;
2736             w--;
2737         }
2738
2739         while (w >= 4)
2740         {
2741             uint32_t *s = (uint32_t *)src;
2742             uint32_t *d = (uint32_t *)dst;
2743
2744             store8888 (d, in (load8888u (s), load8888 (d)));
2745
2746             w -= 4;
2747             dst += 4;
2748             src += 4;
2749         }
2750
2751         while (w--)
2752         {
2753             uint8_t s, d;
2754             uint16_t tmp;
2755
2756             s = *src;
2757             d = *dst;
2758
2759             *dst = MUL_UN8 (s, d, tmp);
2760
2761             src++;
2762             dst++;
2763         }
2764     }
2765
2766     _mm_empty ();
2767 }
2768
2769 static void
2770 mmx_composite_add_n_8_8 (pixman_implementation_t *imp,
2771                          pixman_composite_info_t *info)
2772 {
2773     PIXMAN_COMPOSITE_ARGS (info);
2774     uint8_t     *dst_line, *dst;
2775     uint8_t     *mask_line, *mask;
2776     int dst_stride, mask_stride;
2777     int32_t w;
2778     uint32_t src;
2779     uint8_t sa;
2780     __m64 vsrc, vsrca;
2781
2782     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2783     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2784
2785     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2786
2787     sa = src >> 24;
2788
2789     if (src == 0)
2790         return;
2791
2792     vsrc = load8888 (&src);
2793     vsrca = expand_alpha (vsrc);
2794
2795     while (height--)
2796     {
2797         dst = dst_line;
2798         dst_line += dst_stride;
2799         mask = mask_line;
2800         mask_line += mask_stride;
2801         w = width;
2802
2803         while (w && (unsigned long)dst & 3)
2804         {
2805             uint16_t tmp;
2806             uint16_t a;
2807             uint32_t m, d;
2808             uint32_t r;
2809
2810             a = *mask++;
2811             d = *dst;
2812
2813             m = MUL_UN8 (sa, a, tmp);
2814             r = ADD_UN8 (m, d, tmp);
2815
2816             *dst++ = r;
2817             w--;
2818         }
2819
2820         while (w >= 4)
2821         {
2822             __m64 vmask;
2823             __m64 vdest;
2824
2825             vmask = load8888u ((uint32_t *)mask);
2826             vdest = load8888 ((uint32_t *)dst);
2827
2828             store8888 ((uint32_t *)dst, _mm_adds_pu8 (in (vsrca, vmask), vdest));
2829
2830             dst += 4;
2831             mask += 4;
2832             w -= 4;
2833         }
2834
2835         while (w--)
2836         {
2837             uint16_t tmp;
2838             uint16_t a;
2839             uint32_t m, d;
2840             uint32_t r;
2841
2842             a = *mask++;
2843             d = *dst;
2844
2845             m = MUL_UN8 (sa, a, tmp);
2846             r = ADD_UN8 (m, d, tmp);
2847
2848             *dst++ = r;
2849         }
2850     }
2851
2852     _mm_empty ();
2853 }
2854
2855 static void
2856 mmx_composite_add_8_8 (pixman_implementation_t *imp,
2857                        pixman_composite_info_t *info)
2858 {
2859     PIXMAN_COMPOSITE_ARGS (info);
2860     uint8_t *dst_line, *dst;
2861     uint8_t *src_line, *src;
2862     int dst_stride, src_stride;
2863     int32_t w;
2864     uint8_t s, d;
2865     uint16_t t;
2866
2867     CHECKPOINT ();
2868
2869     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
2870     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2871
2872     while (height--)
2873     {
2874         dst = dst_line;
2875         dst_line += dst_stride;
2876         src = src_line;
2877         src_line += src_stride;
2878         w = width;
2879
2880         while (w && (unsigned long)dst & 7)
2881         {
2882             s = *src;
2883             d = *dst;
2884             t = d + s;
2885             s = t | (0 - (t >> 8));
2886             *dst = s;
2887
2888             dst++;
2889             src++;
2890             w--;
2891         }
2892
2893         while (w >= 8)
2894         {
2895             *(__m64*)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst);
2896             dst += 8;
2897             src += 8;
2898             w -= 8;
2899         }
2900
2901         while (w)
2902         {
2903             s = *src;
2904             d = *dst;
2905             t = d + s;
2906             s = t | (0 - (t >> 8));
2907             *dst = s;
2908
2909             dst++;
2910             src++;
2911             w--;
2912         }
2913     }
2914
2915     _mm_empty ();
2916 }
2917
2918 static void
2919 mmx_composite_add_8888_8888 (pixman_implementation_t *imp,
2920                              pixman_composite_info_t *info)
2921 {
2922     PIXMAN_COMPOSITE_ARGS (info);
2923     uint32_t    *dst_line, *dst;
2924     uint32_t    *src_line, *src;
2925     int dst_stride, src_stride;
2926     int32_t w;
2927
2928     CHECKPOINT ();
2929
2930     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2931     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
2932
2933     while (height--)
2934     {
2935         dst = dst_line;
2936         dst_line += dst_stride;
2937         src = src_line;
2938         src_line += src_stride;
2939         w = width;
2940
2941         while (w && (unsigned long)dst & 7)
2942         {
2943             store (dst, _mm_adds_pu8 (load ((const uint32_t *)src),
2944                                       load ((const uint32_t *)dst)));
2945             dst++;
2946             src++;
2947             w--;
2948         }
2949
2950         while (w >= 2)
2951         {
2952             *(__m64 *)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst);
2953             dst += 2;
2954             src += 2;
2955             w -= 2;
2956         }
2957
2958         if (w)
2959         {
2960             store (dst, _mm_adds_pu8 (load ((const uint32_t *)src),
2961                                       load ((const uint32_t *)dst)));
2962
2963         }
2964     }
2965
2966     _mm_empty ();
2967 }
2968
2969 static pixman_bool_t
2970 pixman_blt_mmx (uint32_t *src_bits,
2971                 uint32_t *dst_bits,
2972                 int       src_stride,
2973                 int       dst_stride,
2974                 int       src_bpp,
2975                 int       dst_bpp,
2976                 int       src_x,
2977                 int       src_y,
2978                 int       dest_x,
2979                 int       dest_y,
2980                 int       width,
2981                 int       height)
2982 {
2983     uint8_t *   src_bytes;
2984     uint8_t *   dst_bytes;
2985     int byte_width;
2986
2987     if (src_bpp != dst_bpp)
2988         return FALSE;
2989
2990     if (src_bpp == 16)
2991     {
2992         src_stride = src_stride * (int) sizeof (uint32_t) / 2;
2993         dst_stride = dst_stride * (int) sizeof (uint32_t) / 2;
2994         src_bytes = (uint8_t *)(((uint16_t *)src_bits) + src_stride * (src_y) + (src_x));
2995         dst_bytes = (uint8_t *)(((uint16_t *)dst_bits) + dst_stride * (dest_y) + (dest_x));
2996         byte_width = 2 * width;
2997         src_stride *= 2;
2998         dst_stride *= 2;
2999     }
3000     else if (src_bpp == 32)
3001     {
3002         src_stride = src_stride * (int) sizeof (uint32_t) / 4;
3003         dst_stride = dst_stride * (int) sizeof (uint32_t) / 4;
3004         src_bytes = (uint8_t *)(((uint32_t *)src_bits) + src_stride * (src_y) + (src_x));
3005         dst_bytes = (uint8_t *)(((uint32_t *)dst_bits) + dst_stride * (dest_y) + (dest_x));
3006         byte_width = 4 * width;
3007         src_stride *= 4;
3008         dst_stride *= 4;
3009     }
3010     else
3011     {
3012         return FALSE;
3013     }
3014
3015     while (height--)
3016     {
3017         int w;
3018         uint8_t *s = src_bytes;
3019         uint8_t *d = dst_bytes;
3020         src_bytes += src_stride;
3021         dst_bytes += dst_stride;
3022         w = byte_width;
3023
3024         if (w >= 1 && ((unsigned long)d & 1))
3025         {
3026             *(uint8_t *)d = *(uint8_t *)s;
3027             w -= 1;
3028             s += 1;
3029             d += 1;
3030         }
3031
3032         if (w >= 2 && ((unsigned long)d & 3))
3033         {
3034             *(uint16_t *)d = *(uint16_t *)s;
3035             w -= 2;
3036             s += 2;
3037             d += 2;
3038         }
3039
3040         while (w >= 4 && ((unsigned long)d & 7))
3041         {
3042             *(uint32_t *)d = ldl_u ((uint32_t *)s);
3043
3044             w -= 4;
3045             s += 4;
3046             d += 4;
3047         }
3048
3049         while (w >= 64)
3050         {
3051 #if (defined (__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))) && defined USE_X86_MMX
3052             __asm__ (
3053                 "movq     (%1),   %%mm0\n"
3054                 "movq    8(%1),   %%mm1\n"
3055                 "movq   16(%1),   %%mm2\n"
3056                 "movq   24(%1),   %%mm3\n"
3057                 "movq   32(%1),   %%mm4\n"
3058                 "movq   40(%1),   %%mm5\n"
3059                 "movq   48(%1),   %%mm6\n"
3060                 "movq   56(%1),   %%mm7\n"
3061
3062                 "movq   %%mm0,    (%0)\n"
3063                 "movq   %%mm1,   8(%0)\n"
3064                 "movq   %%mm2,  16(%0)\n"
3065                 "movq   %%mm3,  24(%0)\n"
3066                 "movq   %%mm4,  32(%0)\n"
3067                 "movq   %%mm5,  40(%0)\n"
3068                 "movq   %%mm6,  48(%0)\n"
3069                 "movq   %%mm7,  56(%0)\n"
3070                 :
3071                 : "r" (d), "r" (s)
3072                 : "memory",
3073                   "%mm0", "%mm1", "%mm2", "%mm3",
3074                   "%mm4", "%mm5", "%mm6", "%mm7");
3075 #else
3076             __m64 v0 = ldq_u ((__m64 *)(s + 0));
3077             __m64 v1 = ldq_u ((__m64 *)(s + 8));
3078             __m64 v2 = ldq_u ((__m64 *)(s + 16));
3079             __m64 v3 = ldq_u ((__m64 *)(s + 24));
3080             __m64 v4 = ldq_u ((__m64 *)(s + 32));
3081             __m64 v5 = ldq_u ((__m64 *)(s + 40));
3082             __m64 v6 = ldq_u ((__m64 *)(s + 48));
3083             __m64 v7 = ldq_u ((__m64 *)(s + 56));
3084             *(__m64 *)(d + 0)  = v0;
3085             *(__m64 *)(d + 8)  = v1;
3086             *(__m64 *)(d + 16) = v2;
3087             *(__m64 *)(d + 24) = v3;
3088             *(__m64 *)(d + 32) = v4;
3089             *(__m64 *)(d + 40) = v5;
3090             *(__m64 *)(d + 48) = v6;
3091             *(__m64 *)(d + 56) = v7;
3092 #endif
3093
3094             w -= 64;
3095             s += 64;
3096             d += 64;
3097         }
3098         while (w >= 4)
3099         {
3100             *(uint32_t *)d = ldl_u ((uint32_t *)s);
3101
3102             w -= 4;
3103             s += 4;
3104             d += 4;
3105         }
3106         if (w >= 2)
3107         {
3108             *(uint16_t *)d = *(uint16_t *)s;
3109             w -= 2;
3110             s += 2;
3111             d += 2;
3112         }
3113     }
3114
3115     _mm_empty ();
3116
3117     return TRUE;
3118 }
3119
3120 static void
3121 mmx_composite_copy_area (pixman_implementation_t *imp,
3122                          pixman_composite_info_t *info)
3123 {
3124     PIXMAN_COMPOSITE_ARGS (info);
3125
3126     pixman_blt_mmx (src_image->bits.bits,
3127                     dest_image->bits.bits,
3128                     src_image->bits.rowstride,
3129                     dest_image->bits.rowstride,
3130                     PIXMAN_FORMAT_BPP (src_image->bits.format),
3131                     PIXMAN_FORMAT_BPP (dest_image->bits.format),
3132                     src_x, src_y, dest_x, dest_y, width, height);
3133 }
3134
3135 static void
3136 mmx_composite_over_x888_8_8888 (pixman_implementation_t *imp,
3137                                 pixman_composite_info_t *info)
3138 {
3139     PIXMAN_COMPOSITE_ARGS (info);
3140     uint32_t  *src, *src_line;
3141     uint32_t  *dst, *dst_line;
3142     uint8_t  *mask, *mask_line;
3143     int src_stride, mask_stride, dst_stride;
3144     int32_t w;
3145
3146     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
3147     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
3148     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
3149
3150     while (height--)
3151     {
3152         src = src_line;
3153         src_line += src_stride;
3154         dst = dst_line;
3155         dst_line += dst_stride;
3156         mask = mask_line;
3157         mask_line += mask_stride;
3158
3159         w = width;
3160
3161         while (w--)
3162         {
3163             uint64_t m = *mask;
3164
3165             if (m)
3166             {
3167                 uint32_t ssrc = *src | 0xff000000;
3168                 __m64 s = load8888 (&ssrc);
3169
3170                 if (m == 0xff)
3171                 {
3172                     store8888 (dst, s);
3173                 }
3174                 else
3175                 {
3176                     __m64 sa = expand_alpha (s);
3177                     __m64 vm = expand_alpha_rev (to_m64 (m));
3178                     __m64 vdest = in_over (s, sa, vm, load8888 (dst));
3179
3180                     store8888 (dst, vdest);
3181                 }
3182             }
3183
3184             mask++;
3185             dst++;
3186             src++;
3187         }
3188     }
3189
3190     _mm_empty ();
3191 }
3192
3193 static const pixman_fast_path_t mmx_fast_paths[] =
3194 {
3195     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       r5g6b5,   mmx_composite_over_n_8_0565       ),
3196     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       b5g6r5,   mmx_composite_over_n_8_0565       ),
3197     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       a8r8g8b8, mmx_composite_over_n_8_8888       ),
3198     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       x8r8g8b8, mmx_composite_over_n_8_8888       ),
3199     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       a8b8g8r8, mmx_composite_over_n_8_8888       ),
3200     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       x8b8g8r8, mmx_composite_over_n_8_8888       ),
3201     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8r8g8b8, a8r8g8b8, mmx_composite_over_n_8888_8888_ca ),
3202     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8r8g8b8, x8r8g8b8, mmx_composite_over_n_8888_8888_ca ),
3203     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8r8g8b8, r5g6b5,   mmx_composite_over_n_8888_0565_ca ),
3204     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8b8g8r8, a8b8g8r8, mmx_composite_over_n_8888_8888_ca ),
3205     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8b8g8r8, x8b8g8r8, mmx_composite_over_n_8888_8888_ca ),
3206     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8b8g8r8, b5g6r5,   mmx_composite_over_n_8888_0565_ca ),
3207     PIXMAN_STD_FAST_PATH    (OVER, pixbuf,   pixbuf,   a8r8g8b8, mmx_composite_over_pixbuf_8888    ),
3208     PIXMAN_STD_FAST_PATH    (OVER, pixbuf,   pixbuf,   x8r8g8b8, mmx_composite_over_pixbuf_8888    ),
3209     PIXMAN_STD_FAST_PATH    (OVER, pixbuf,   pixbuf,   r5g6b5,   mmx_composite_over_pixbuf_0565    ),
3210     PIXMAN_STD_FAST_PATH    (OVER, rpixbuf,  rpixbuf,  a8b8g8r8, mmx_composite_over_pixbuf_8888    ),
3211     PIXMAN_STD_FAST_PATH    (OVER, rpixbuf,  rpixbuf,  x8b8g8r8, mmx_composite_over_pixbuf_8888    ),
3212     PIXMAN_STD_FAST_PATH    (OVER, rpixbuf,  rpixbuf,  b5g6r5,   mmx_composite_over_pixbuf_0565    ),
3213     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, solid,    a8r8g8b8, mmx_composite_over_x888_n_8888    ),
3214     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, solid,    x8r8g8b8, mmx_composite_over_x888_n_8888    ),
3215     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, solid,    a8b8g8r8, mmx_composite_over_x888_n_8888    ),
3216     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, solid,    x8b8g8r8, mmx_composite_over_x888_n_8888    ),
3217     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, solid,    a8r8g8b8, mmx_composite_over_8888_n_8888    ),
3218     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, solid,    x8r8g8b8, mmx_composite_over_8888_n_8888    ),
3219     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, solid,    a8b8g8r8, mmx_composite_over_8888_n_8888    ),
3220     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, solid,    x8b8g8r8, mmx_composite_over_8888_n_8888    ),
3221     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, a8,       x8r8g8b8, mmx_composite_over_x888_8_8888    ),
3222     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, a8,       a8r8g8b8, mmx_composite_over_x888_8_8888    ),
3223     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, a8,       x8b8g8r8, mmx_composite_over_x888_8_8888    ),
3224     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, a8,       a8b8g8r8, mmx_composite_over_x888_8_8888    ),
3225     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     a8r8g8b8, mmx_composite_over_n_8888         ),
3226     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     x8r8g8b8, mmx_composite_over_n_8888         ),
3227     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     r5g6b5,   mmx_composite_over_n_0565         ),
3228     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     b5g6r5,   mmx_composite_over_n_0565         ),
3229     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, null,     x8r8g8b8, mmx_composite_copy_area           ),
3230     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, null,     x8b8g8r8, mmx_composite_copy_area           ),
3231
3232     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, null,     a8r8g8b8, mmx_composite_over_8888_8888      ),
3233     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, null,     x8r8g8b8, mmx_composite_over_8888_8888      ),
3234     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, null,     r5g6b5,   mmx_composite_over_8888_0565      ),
3235     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, null,     a8b8g8r8, mmx_composite_over_8888_8888      ),
3236     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, null,     x8b8g8r8, mmx_composite_over_8888_8888      ),
3237     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, null,     b5g6r5,   mmx_composite_over_8888_0565      ),
3238
3239     PIXMAN_STD_FAST_PATH    (ADD,  a8r8g8b8, null,     a8r8g8b8, mmx_composite_add_8888_8888       ),
3240     PIXMAN_STD_FAST_PATH    (ADD,  a8b8g8r8, null,     a8b8g8r8, mmx_composite_add_8888_8888       ),
3241     PIXMAN_STD_FAST_PATH    (ADD,  a8,       null,     a8,       mmx_composite_add_8_8             ),
3242     PIXMAN_STD_FAST_PATH    (ADD,  solid,    a8,       a8,       mmx_composite_add_n_8_8           ),
3243
3244     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       a8r8g8b8, mmx_composite_src_n_8_8888        ),
3245     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       x8r8g8b8, mmx_composite_src_n_8_8888        ),
3246     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       a8b8g8r8, mmx_composite_src_n_8_8888        ),
3247     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       x8b8g8r8, mmx_composite_src_n_8_8888        ),
3248     PIXMAN_STD_FAST_PATH    (SRC,  a8r8g8b8, null,     a8r8g8b8, mmx_composite_copy_area           ),
3249     PIXMAN_STD_FAST_PATH    (SRC,  a8b8g8r8, null,     a8b8g8r8, mmx_composite_copy_area           ),
3250     PIXMAN_STD_FAST_PATH    (SRC,  a8r8g8b8, null,     x8r8g8b8, mmx_composite_copy_area           ),
3251     PIXMAN_STD_FAST_PATH    (SRC,  a8b8g8r8, null,     x8b8g8r8, mmx_composite_copy_area           ),
3252     PIXMAN_STD_FAST_PATH    (SRC,  x8r8g8b8, null,     x8r8g8b8, mmx_composite_copy_area           ),
3253     PIXMAN_STD_FAST_PATH    (SRC,  x8b8g8r8, null,     x8b8g8r8, mmx_composite_copy_area           ),
3254     PIXMAN_STD_FAST_PATH    (SRC,  r5g6b5,   null,     r5g6b5,   mmx_composite_copy_area           ),
3255     PIXMAN_STD_FAST_PATH    (SRC,  b5g6r5,   null,     b5g6r5,   mmx_composite_copy_area           ),
3256
3257     PIXMAN_STD_FAST_PATH    (IN,   a8,       null,     a8,       mmx_composite_in_8_8              ),
3258     PIXMAN_STD_FAST_PATH    (IN,   solid,    a8,       a8,       mmx_composite_in_n_8_8            ),
3259
3260     { PIXMAN_OP_NONE },
3261 };
3262
3263 static pixman_bool_t
3264 mmx_blt (pixman_implementation_t *imp,
3265          uint32_t *               src_bits,
3266          uint32_t *               dst_bits,
3267          int                      src_stride,
3268          int                      dst_stride,
3269          int                      src_bpp,
3270          int                      dst_bpp,
3271          int                      src_x,
3272          int                      src_y,
3273          int                      dest_x,
3274          int                      dest_y,
3275          int                      width,
3276          int                      height)
3277 {
3278     if (!pixman_blt_mmx (
3279             src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
3280             src_x, src_y, dest_x, dest_y, width, height))
3281
3282     {
3283         return _pixman_implementation_blt (
3284             imp->delegate,
3285             src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
3286             src_x, src_y, dest_x, dest_y, width, height);
3287     }
3288
3289     return TRUE;
3290 }
3291
3292 static pixman_bool_t
3293 mmx_fill (pixman_implementation_t *imp,
3294           uint32_t *               bits,
3295           int                      stride,
3296           int                      bpp,
3297           int                      x,
3298           int                      y,
3299           int                      width,
3300           int                      height,
3301           uint32_t xor)
3302 {
3303     if (!pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor))
3304     {
3305         return _pixman_implementation_fill (
3306             imp->delegate, bits, stride, bpp, x, y, width, height, xor);
3307     }
3308
3309     return TRUE;
3310 }
3311
3312 pixman_implementation_t *
3313 _pixman_implementation_create_mmx (pixman_implementation_t *fallback)
3314 {
3315     pixman_implementation_t *imp = _pixman_implementation_create (fallback, mmx_fast_paths);
3316
3317     imp->combine_32[PIXMAN_OP_OVER] = mmx_combine_over_u;
3318     imp->combine_32[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_u;
3319     imp->combine_32[PIXMAN_OP_IN] = mmx_combine_in_u;
3320     imp->combine_32[PIXMAN_OP_IN_REVERSE] = mmx_combine_in_reverse_u;
3321     imp->combine_32[PIXMAN_OP_OUT] = mmx_combine_out_u;
3322     imp->combine_32[PIXMAN_OP_OUT_REVERSE] = mmx_combine_out_reverse_u;
3323     imp->combine_32[PIXMAN_OP_ATOP] = mmx_combine_atop_u;
3324     imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = mmx_combine_atop_reverse_u;
3325     imp->combine_32[PIXMAN_OP_XOR] = mmx_combine_xor_u;
3326     imp->combine_32[PIXMAN_OP_ADD] = mmx_combine_add_u;
3327     imp->combine_32[PIXMAN_OP_SATURATE] = mmx_combine_saturate_u;
3328
3329     imp->combine_32_ca[PIXMAN_OP_SRC] = mmx_combine_src_ca;
3330     imp->combine_32_ca[PIXMAN_OP_OVER] = mmx_combine_over_ca;
3331     imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_ca;
3332     imp->combine_32_ca[PIXMAN_OP_IN] = mmx_combine_in_ca;
3333     imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = mmx_combine_in_reverse_ca;
3334     imp->combine_32_ca[PIXMAN_OP_OUT] = mmx_combine_out_ca;
3335     imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = mmx_combine_out_reverse_ca;
3336     imp->combine_32_ca[PIXMAN_OP_ATOP] = mmx_combine_atop_ca;
3337     imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = mmx_combine_atop_reverse_ca;
3338     imp->combine_32_ca[PIXMAN_OP_XOR] = mmx_combine_xor_ca;
3339     imp->combine_32_ca[PIXMAN_OP_ADD] = mmx_combine_add_ca;
3340
3341     imp->blt = mmx_blt;
3342     imp->fill = mmx_fill;
3343
3344     return imp;
3345 }
3346
3347 #endif /* USE_X86_MMX || USE_ARM_IWMMXT || USE_LOONGSON_MMI */