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