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