Add qemu 2.4.0
[kvmfornfv.git] / qemu / pixman / pixman / pixman-vmx.c
1 /*
2  * Copyright © 2007 Luca Barbato
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Luca Barbato not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  Luca Barbato makes no representations about the
11  * suitability of this software for any purpose.  It is provided "as is"
12  * without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
19  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
20  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21  * SOFTWARE.
22  *
23  * Author:  Luca Barbato (lu_zero@gentoo.org)
24  *
25  * Based on fbmmx.c by Owen Taylor, Søren Sandmann and Nicholas Miell
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "pixman-private.h"
32 #include "pixman-combine32.h"
33 #include <altivec.h>
34
35 #define AVV(x...) {x}
36
37 static force_inline vector unsigned int
38 splat_alpha (vector unsigned int pix)
39 {
40     return vec_perm (pix, pix,
41                      (vector unsigned char)AVV (
42                          0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04,
43                          0x08, 0x08, 0x08, 0x08, 0x0C, 0x0C, 0x0C, 0x0C));
44 }
45
46 static force_inline vector unsigned int
47 pix_multiply (vector unsigned int p, vector unsigned int a)
48 {
49     vector unsigned short hi, lo, mod;
50
51     /* unpack to short */
52     hi = (vector unsigned short)
53         vec_mergeh ((vector unsigned char)AVV (0),
54                     (vector unsigned char)p);
55
56     mod = (vector unsigned short)
57         vec_mergeh ((vector unsigned char)AVV (0),
58                     (vector unsigned char)a);
59
60     hi = vec_mladd (hi, mod, (vector unsigned short)
61                     AVV (0x0080, 0x0080, 0x0080, 0x0080,
62                          0x0080, 0x0080, 0x0080, 0x0080));
63
64     hi = vec_adds (hi, vec_sr (hi, vec_splat_u16 (8)));
65
66     hi = vec_sr (hi, vec_splat_u16 (8));
67
68     /* unpack to short */
69     lo = (vector unsigned short)
70         vec_mergel ((vector unsigned char)AVV (0),
71                     (vector unsigned char)p);
72     mod = (vector unsigned short)
73         vec_mergel ((vector unsigned char)AVV (0),
74                     (vector unsigned char)a);
75
76     lo = vec_mladd (lo, mod, (vector unsigned short)
77                     AVV (0x0080, 0x0080, 0x0080, 0x0080,
78                          0x0080, 0x0080, 0x0080, 0x0080));
79
80     lo = vec_adds (lo, vec_sr (lo, vec_splat_u16 (8)));
81
82     lo = vec_sr (lo, vec_splat_u16 (8));
83
84     return (vector unsigned int)vec_packsu (hi, lo);
85 }
86
87 static force_inline vector unsigned int
88 pix_add (vector unsigned int a, vector unsigned int b)
89 {
90     return (vector unsigned int)vec_adds ((vector unsigned char)a,
91                                           (vector unsigned char)b);
92 }
93
94 static force_inline vector unsigned int
95 pix_add_mul (vector unsigned int x,
96              vector unsigned int a,
97              vector unsigned int y,
98              vector unsigned int b)
99 {
100     vector unsigned int t1, t2;
101
102     t1 = pix_multiply (x, a);
103     t2 = pix_multiply (y, b);
104
105     return pix_add (t1, t2);
106 }
107
108 static force_inline vector unsigned int
109 negate (vector unsigned int src)
110 {
111     return vec_nor (src, src);
112 }
113
114 /* dest*~srca + src */
115 static force_inline vector unsigned int
116 over (vector unsigned int src,
117       vector unsigned int srca,
118       vector unsigned int dest)
119 {
120     vector unsigned char tmp = (vector unsigned char)
121         pix_multiply (dest, negate (srca));
122
123     tmp = vec_adds ((vector unsigned char)src, tmp);
124     return (vector unsigned int)tmp;
125 }
126
127 /* in == pix_multiply */
128 #define in_over(src, srca, mask, dest)                                  \
129     over (pix_multiply (src, mask),                                     \
130           pix_multiply (srca, mask), dest)
131
132
133 #define COMPUTE_SHIFT_MASK(source)                                      \
134     source ## _mask = vec_lvsl (0, source);
135
136 #define COMPUTE_SHIFT_MASKS(dest, source)                               \
137     source ## _mask = vec_lvsl (0, source);
138
139 #define COMPUTE_SHIFT_MASKC(dest, source, mask)                         \
140     mask ## _mask = vec_lvsl (0, mask);                                 \
141     source ## _mask = vec_lvsl (0, source);
142
143 /* notice you have to declare temp vars...
144  * Note: tmp3 and tmp4 must remain untouched!
145  */
146
147 #define LOAD_VECTORS(dest, source)                        \
148     tmp1 = (typeof(tmp1))vec_ld (0, source);              \
149     tmp2 = (typeof(tmp2))vec_ld (15, source);             \
150     v ## source = (typeof(v ## source))                   \
151         vec_perm (tmp1, tmp2, source ## _mask);           \
152     v ## dest = (typeof(v ## dest))vec_ld (0, dest);
153
154 #define LOAD_VECTORSC(dest, source, mask)                 \
155     tmp1 = (typeof(tmp1))vec_ld (0, source);              \
156     tmp2 = (typeof(tmp2))vec_ld (15, source);             \
157     v ## source = (typeof(v ## source))                   \
158         vec_perm (tmp1, tmp2, source ## _mask);           \
159     tmp1 = (typeof(tmp1))vec_ld (0, mask);                \
160     v ## dest = (typeof(v ## dest))vec_ld (0, dest);      \
161     tmp2 = (typeof(tmp2))vec_ld (15, mask);               \
162     v ## mask = (typeof(v ## mask))                       \
163         vec_perm (tmp1, tmp2, mask ## _mask);
164
165 #define LOAD_VECTORSM(dest, source, mask)                               \
166     LOAD_VECTORSC (dest, source, mask)                                  \
167     v ## source = pix_multiply (v ## source,                            \
168                                 splat_alpha (v ## mask));
169
170 #define STORE_VECTOR(dest)                                              \
171     vec_st ((vector unsigned int) v ## dest, 0, dest);
172
173 static void
174 vmx_combine_over_u_no_mask (uint32_t *      dest,
175                             const uint32_t *src,
176                             int             width)
177 {
178     int i;
179     vector unsigned int vdest, vsrc;
180     vector unsigned char tmp1, tmp2, src_mask;
181
182     while (width && ((uintptr_t)dest & 15))
183     {
184         uint32_t s = *src++;
185         uint32_t d = *dest;
186         uint32_t ia = ALPHA_8 (~s);
187
188         UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
189
190         *dest++ = d;
191         width--;
192     }
193
194     COMPUTE_SHIFT_MASKS (dest, src);
195
196     /* printf ("%s\n",__PRETTY_FUNCTION__); */
197     for (i = width / 4; i > 0; i--)
198     {
199
200         LOAD_VECTORS (dest, src);
201
202         vdest = over (vsrc, splat_alpha (vsrc), vdest);
203
204         STORE_VECTOR (dest);
205
206         src += 4;
207         dest += 4;
208     }
209
210     for (i = width % 4; --i >= 0;)
211     {
212         uint32_t s = src[i];
213         uint32_t d = dest[i];
214         uint32_t ia = ALPHA_8 (~s);
215
216         UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
217
218         dest[i] = d;
219     }
220 }
221
222 static void
223 vmx_combine_over_u_mask (uint32_t *      dest,
224                          const uint32_t *src,
225                          const uint32_t *mask,
226                          int             width)
227 {
228     int i;
229     vector unsigned int vdest, vsrc, vmask;
230     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
231
232     while (width && ((uintptr_t)dest & 15))
233     {
234         uint32_t m = ALPHA_8 (*mask++);
235         uint32_t s = *src++;
236         uint32_t d = *dest;
237         uint32_t ia;
238
239         UN8x4_MUL_UN8 (s, m);
240
241         ia = ALPHA_8 (~s);
242
243         UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
244         *dest++ = d;
245         width--;
246     }
247
248     COMPUTE_SHIFT_MASKC (dest, src, mask);
249
250     /* printf ("%s\n",__PRETTY_FUNCTION__); */
251     for (i = width / 4; i > 0; i--)
252     {
253         LOAD_VECTORSM (dest, src, mask);
254
255         vdest = over (vsrc, splat_alpha (vsrc), vdest);
256
257         STORE_VECTOR (dest);
258
259         src += 4;
260         dest += 4;
261         mask += 4;
262     }
263
264     for (i = width % 4; --i >= 0;)
265     {
266         uint32_t m = ALPHA_8 (mask[i]);
267         uint32_t s = src[i];
268         uint32_t d = dest[i];
269         uint32_t ia;
270
271         UN8x4_MUL_UN8 (s, m);
272
273         ia = ALPHA_8 (~s);
274
275         UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
276         dest[i] = d;
277     }
278 }
279
280 static void
281 vmx_combine_over_u (pixman_implementation_t *imp,
282                     pixman_op_t              op,
283                     uint32_t *               dest,
284                     const uint32_t *         src,
285                     const uint32_t *         mask,
286                     int                      width)
287 {
288     if (mask)
289         vmx_combine_over_u_mask (dest, src, mask, width);
290     else
291         vmx_combine_over_u_no_mask (dest, src, width);
292 }
293
294 static void
295 vmx_combine_over_reverse_u_no_mask (uint32_t *      dest,
296                                     const uint32_t *src,
297                                     int             width)
298 {
299     int i;
300     vector unsigned int vdest, vsrc;
301     vector unsigned char tmp1, tmp2, src_mask;
302
303     while (width && ((uintptr_t)dest & 15))
304     {
305         uint32_t s = *src++;
306         uint32_t d = *dest;
307         uint32_t ia = ALPHA_8 (~d);
308
309         UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d);
310         *dest++ = s;
311         width--;
312     }
313
314     COMPUTE_SHIFT_MASKS (dest, src);
315
316     /* printf ("%s\n",__PRETTY_FUNCTION__); */
317     for (i = width / 4; i > 0; i--)
318     {
319
320         LOAD_VECTORS (dest, src);
321
322         vdest = over (vdest, splat_alpha (vdest), vsrc);
323
324         STORE_VECTOR (dest);
325
326         src += 4;
327         dest += 4;
328     }
329
330     for (i = width % 4; --i >= 0;)
331     {
332         uint32_t s = src[i];
333         uint32_t d = dest[i];
334         uint32_t ia = ALPHA_8 (~dest[i]);
335
336         UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d);
337         dest[i] = s;
338     }
339 }
340
341 static void
342 vmx_combine_over_reverse_u_mask (uint32_t *      dest,
343                                  const uint32_t *src,
344                                  const uint32_t *mask,
345                                  int             width)
346 {
347     int i;
348     vector unsigned int vdest, vsrc, vmask;
349     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
350
351     while (width && ((uintptr_t)dest & 15))
352     {
353         uint32_t m = ALPHA_8 (*mask++);
354         uint32_t s = *src++;
355         uint32_t d = *dest;
356         uint32_t ia = ALPHA_8 (~d);
357
358         UN8x4_MUL_UN8 (s, m);
359
360         UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d);
361         *dest++ = s;
362         width--;
363     }
364
365     COMPUTE_SHIFT_MASKC (dest, src, mask);
366
367     /* printf ("%s\n",__PRETTY_FUNCTION__); */
368     for (i = width / 4; i > 0; i--)
369     {
370
371         LOAD_VECTORSM (dest, src, mask);
372
373         vdest = over (vdest, splat_alpha (vdest), vsrc);
374
375         STORE_VECTOR (dest);
376
377         src += 4;
378         dest += 4;
379         mask += 4;
380     }
381
382     for (i = width % 4; --i >= 0;)
383     {
384         uint32_t m = ALPHA_8 (mask[i]);
385         uint32_t s = src[i];
386         uint32_t d = dest[i];
387         uint32_t ia = ALPHA_8 (~dest[i]);
388
389         UN8x4_MUL_UN8 (s, m);
390
391         UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d);
392         dest[i] = s;
393     }
394 }
395
396 static void
397 vmx_combine_over_reverse_u (pixman_implementation_t *imp,
398                             pixman_op_t              op,
399                             uint32_t *               dest,
400                             const uint32_t *         src,
401                             const uint32_t *         mask,
402                             int                      width)
403 {
404     if (mask)
405         vmx_combine_over_reverse_u_mask (dest, src, mask, width);
406     else
407         vmx_combine_over_reverse_u_no_mask (dest, src, width);
408 }
409
410 static void
411 vmx_combine_in_u_no_mask (uint32_t *      dest,
412                           const uint32_t *src,
413                           int             width)
414 {
415     int i;
416     vector unsigned int vdest, vsrc;
417     vector unsigned char tmp1, tmp2, src_mask;
418
419     while (width && ((uintptr_t)dest & 15))
420     {
421         uint32_t s = *src++;
422         uint32_t a = ALPHA_8 (*dest);
423
424         UN8x4_MUL_UN8 (s, a);
425         *dest++ = s;
426         width--;
427     }
428
429     COMPUTE_SHIFT_MASKS (dest, src);
430
431     /* printf ("%s\n",__PRETTY_FUNCTION__); */
432     for (i = width / 4; i > 0; i--)
433     {
434         LOAD_VECTORS (dest, src);
435
436         vdest = pix_multiply (vsrc, splat_alpha (vdest));
437
438         STORE_VECTOR (dest);
439
440         src += 4;
441         dest += 4;
442     }
443
444     for (i = width % 4; --i >= 0;)
445     {
446         uint32_t s = src[i];
447         uint32_t a = ALPHA_8 (dest[i]);
448
449         UN8x4_MUL_UN8 (s, a);
450         dest[i] = s;
451     }
452 }
453
454 static void
455 vmx_combine_in_u_mask (uint32_t *      dest,
456                        const uint32_t *src,
457                        const uint32_t *mask,
458                        int             width)
459 {
460     int i;
461     vector unsigned int vdest, vsrc, vmask;
462     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
463
464     while (width && ((uintptr_t)dest & 15))
465     {
466         uint32_t m = ALPHA_8 (*mask++);
467         uint32_t s = *src++;
468         uint32_t a = ALPHA_8 (*dest);
469
470         UN8x4_MUL_UN8 (s, m);
471         UN8x4_MUL_UN8 (s, a);
472
473         *dest++ = s;
474         width--;
475     }
476
477     COMPUTE_SHIFT_MASKC (dest, src, mask);
478
479     /* printf ("%s\n",__PRETTY_FUNCTION__); */
480     for (i = width / 4; i > 0; i--)
481     {
482         LOAD_VECTORSM (dest, src, mask);
483
484         vdest = pix_multiply (vsrc, splat_alpha (vdest));
485
486         STORE_VECTOR (dest);
487
488         src += 4;
489         dest += 4;
490         mask += 4;
491     }
492
493     for (i = width % 4; --i >= 0;)
494     {
495         uint32_t m = ALPHA_8 (mask[i]);
496         uint32_t s = src[i];
497         uint32_t a = ALPHA_8 (dest[i]);
498
499         UN8x4_MUL_UN8 (s, m);
500         UN8x4_MUL_UN8 (s, a);
501
502         dest[i] = s;
503     }
504 }
505
506 static void
507 vmx_combine_in_u (pixman_implementation_t *imp,
508                   pixman_op_t              op,
509                   uint32_t *               dest,
510                   const uint32_t *         src,
511                   const uint32_t *         mask,
512                   int                      width)
513 {
514     if (mask)
515         vmx_combine_in_u_mask (dest, src, mask, width);
516     else
517         vmx_combine_in_u_no_mask (dest, src, width);
518 }
519
520 static void
521 vmx_combine_in_reverse_u_no_mask (uint32_t *      dest,
522                                   const uint32_t *src,
523                                   int             width)
524 {
525     int i;
526     vector unsigned int vdest, vsrc;
527     vector unsigned char tmp1, tmp2, src_mask;
528
529     while (width && ((uintptr_t)dest & 15))
530     {
531         uint32_t d = *dest;
532         uint32_t a = ALPHA_8 (*src++);
533
534         UN8x4_MUL_UN8 (d, a);
535
536         *dest++ = d;
537         width--;
538     }
539
540     COMPUTE_SHIFT_MASKS (dest, src);
541
542     /* printf ("%s\n",__PRETTY_FUNCTION__); */
543     for (i = width / 4; i > 0; i--)
544     {
545         LOAD_VECTORS (dest, src);
546
547         vdest = pix_multiply (vdest, splat_alpha (vsrc));
548
549         STORE_VECTOR (dest);
550
551         src += 4;
552         dest += 4;
553     }
554
555     for (i = width % 4; --i >= 0;)
556     {
557         uint32_t d = dest[i];
558         uint32_t a = ALPHA_8 (src[i]);
559
560         UN8x4_MUL_UN8 (d, a);
561
562         dest[i] = d;
563     }
564 }
565
566 static void
567 vmx_combine_in_reverse_u_mask (uint32_t *      dest,
568                                const uint32_t *src,
569                                const uint32_t *mask,
570                                int             width)
571 {
572     int i;
573     vector unsigned int vdest, vsrc, vmask;
574     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
575
576     while (width && ((uintptr_t)dest & 15))
577     {
578         uint32_t m = ALPHA_8 (*mask++);
579         uint32_t d = *dest;
580         uint32_t a = *src++;
581
582         UN8x4_MUL_UN8 (a, m);
583         a = ALPHA_8 (a);
584         UN8x4_MUL_UN8 (d, a);
585
586         *dest++ = d;
587         width--;
588     }
589
590     COMPUTE_SHIFT_MASKC (dest, src, mask);
591
592     /* printf ("%s\n",__PRETTY_FUNCTION__); */
593     for (i = width / 4; i > 0; i--)
594     {
595         LOAD_VECTORSM (dest, src, mask);
596
597         vdest = pix_multiply (vdest, splat_alpha (vsrc));
598
599         STORE_VECTOR (dest);
600
601         src += 4;
602         dest += 4;
603         mask += 4;
604     }
605
606     for (i = width % 4; --i >= 0;)
607     {
608         uint32_t m = ALPHA_8 (mask[i]);
609         uint32_t d = dest[i];
610         uint32_t a = src[i];
611
612         UN8x4_MUL_UN8 (a, m);
613         a = ALPHA_8 (a);
614         UN8x4_MUL_UN8 (d, a);
615
616         dest[i] = d;
617     }
618 }
619
620 static void
621 vmx_combine_in_reverse_u (pixman_implementation_t *imp,
622                           pixman_op_t              op,
623                           uint32_t *               dest,
624                           const uint32_t *         src,
625                           const uint32_t *         mask,
626                           int                      width)
627 {
628     if (mask)
629         vmx_combine_in_reverse_u_mask (dest, src, mask, width);
630     else
631         vmx_combine_in_reverse_u_no_mask (dest, src, width);
632 }
633
634 static void
635 vmx_combine_out_u_no_mask (uint32_t *      dest,
636                            const uint32_t *src,
637                            int             width)
638 {
639     int i;
640     vector unsigned int vdest, vsrc;
641     vector unsigned char tmp1, tmp2, src_mask;
642
643     while (width && ((uintptr_t)dest & 15))
644     {
645         uint32_t s = *src++;
646         uint32_t a = ALPHA_8 (~(*dest));
647
648         UN8x4_MUL_UN8 (s, a);
649
650         *dest++ = s;
651         width--;
652     }
653
654     COMPUTE_SHIFT_MASKS (dest, src);
655
656     /* printf ("%s\n",__PRETTY_FUNCTION__); */
657     for (i = width / 4; i > 0; i--)
658     {
659         LOAD_VECTORS (dest, src);
660
661         vdest = pix_multiply (vsrc, splat_alpha (negate (vdest)));
662
663         STORE_VECTOR (dest);
664
665         src += 4;
666         dest += 4;
667     }
668
669     for (i = width % 4; --i >= 0;)
670     {
671         uint32_t s = src[i];
672         uint32_t a = ALPHA_8 (~dest[i]);
673
674         UN8x4_MUL_UN8 (s, a);
675
676         dest[i] = s;
677     }
678 }
679
680 static void
681 vmx_combine_out_u_mask (uint32_t *      dest,
682                         const uint32_t *src,
683                         const uint32_t *mask,
684                         int             width)
685 {
686     int i;
687     vector unsigned int vdest, vsrc, vmask;
688     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
689
690     while (width && ((uintptr_t)dest & 15))
691     {
692         uint32_t m = ALPHA_8 (*mask++);
693         uint32_t s = *src++;
694         uint32_t a = ALPHA_8 (~(*dest));
695
696         UN8x4_MUL_UN8 (s, m);
697         UN8x4_MUL_UN8 (s, a);
698
699         *dest++ = s;
700         width--;
701     }
702
703     COMPUTE_SHIFT_MASKC (dest, src, mask);
704
705     /* printf ("%s\n",__PRETTY_FUNCTION__); */
706     for (i = width / 4; i > 0; i--)
707     {
708         LOAD_VECTORSM (dest, src, mask);
709
710         vdest = pix_multiply (vsrc, splat_alpha (negate (vdest)));
711
712         STORE_VECTOR (dest);
713
714         src += 4;
715         dest += 4;
716         mask += 4;
717     }
718
719     for (i = width % 4; --i >= 0;)
720     {
721         uint32_t m = ALPHA_8 (mask[i]);
722         uint32_t s = src[i];
723         uint32_t a = ALPHA_8 (~dest[i]);
724
725         UN8x4_MUL_UN8 (s, m);
726         UN8x4_MUL_UN8 (s, a);
727
728         dest[i] = s;
729     }
730 }
731
732 static void
733 vmx_combine_out_u (pixman_implementation_t *imp,
734                    pixman_op_t              op,
735                    uint32_t *               dest,
736                    const uint32_t *         src,
737                    const uint32_t *         mask,
738                    int                      width)
739 {
740     if (mask)
741         vmx_combine_out_u_mask (dest, src, mask, width);
742     else
743         vmx_combine_out_u_no_mask (dest, src, width);
744 }
745
746 static void
747 vmx_combine_out_reverse_u_no_mask (uint32_t *      dest,
748                                    const uint32_t *src,
749                                    int             width)
750 {
751     int i;
752     vector unsigned int vdest, vsrc;
753     vector unsigned char tmp1, tmp2, src_mask;
754
755     while (width && ((uintptr_t)dest & 15))
756     {
757         uint32_t d = *dest;
758         uint32_t a = ALPHA_8 (~(*src++));
759
760         UN8x4_MUL_UN8 (d, a);
761
762         *dest++ = d;
763         width--;
764     }
765
766     COMPUTE_SHIFT_MASKS (dest, src);
767
768     /* printf ("%s\n",__PRETTY_FUNCTION__); */
769     for (i = width / 4; i > 0; i--)
770     {
771
772         LOAD_VECTORS (dest, src);
773
774         vdest = pix_multiply (vdest, splat_alpha (negate (vsrc)));
775
776         STORE_VECTOR (dest);
777
778         src += 4;
779         dest += 4;
780     }
781
782     for (i = width % 4; --i >= 0;)
783     {
784         uint32_t d = dest[i];
785         uint32_t a = ALPHA_8 (~src[i]);
786
787         UN8x4_MUL_UN8 (d, a);
788
789         dest[i] = d;
790     }
791 }
792
793 static void
794 vmx_combine_out_reverse_u_mask (uint32_t *      dest,
795                                 const uint32_t *src,
796                                 const uint32_t *mask,
797                                 int             width)
798 {
799     int i;
800     vector unsigned int vdest, vsrc, vmask;
801     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
802
803     while (width && ((uintptr_t)dest & 15))
804     {
805         uint32_t m = ALPHA_8 (*mask++);
806         uint32_t d = *dest;
807         uint32_t a = *src++;
808
809         UN8x4_MUL_UN8 (a, m);
810         a = ALPHA_8 (~a);
811         UN8x4_MUL_UN8 (d, a);
812
813         *dest++ = d;
814         width--;
815     }
816
817     COMPUTE_SHIFT_MASKC (dest, src, mask);
818
819     /* printf ("%s\n",__PRETTY_FUNCTION__); */
820     for (i = width / 4; i > 0; i--)
821     {
822         LOAD_VECTORSM (dest, src, mask);
823
824         vdest = pix_multiply (vdest, splat_alpha (negate (vsrc)));
825
826         STORE_VECTOR (dest);
827
828         src += 4;
829         dest += 4;
830         mask += 4;
831     }
832
833     for (i = width % 4; --i >= 0;)
834     {
835         uint32_t m = ALPHA_8 (mask[i]);
836         uint32_t d = dest[i];
837         uint32_t a = src[i];
838
839         UN8x4_MUL_UN8 (a, m);
840         a = ALPHA_8 (~a);
841         UN8x4_MUL_UN8 (d, a);
842
843         dest[i] = d;
844     }
845 }
846
847 static void
848 vmx_combine_out_reverse_u (pixman_implementation_t *imp,
849                            pixman_op_t              op,
850                            uint32_t *               dest,
851                            const uint32_t *         src,
852                            const uint32_t *         mask,
853                            int                      width)
854 {
855     if (mask)
856         vmx_combine_out_reverse_u_mask (dest, src, mask, width);
857     else
858         vmx_combine_out_reverse_u_no_mask (dest, src, width);
859 }
860
861 static void
862 vmx_combine_atop_u_no_mask (uint32_t *      dest,
863                             const uint32_t *src,
864                             int             width)
865 {
866     int i;
867     vector unsigned int vdest, vsrc;
868     vector unsigned char tmp1, tmp2, src_mask;
869
870     while (width && ((uintptr_t)dest & 15))
871     {
872         uint32_t s = *src++;
873         uint32_t d = *dest;
874         uint32_t dest_a = ALPHA_8 (d);
875         uint32_t src_ia = ALPHA_8 (~s);
876
877         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia);
878
879         *dest++ = s;
880         width--;
881     }
882
883     COMPUTE_SHIFT_MASKS (dest, src);
884
885     /* printf ("%s\n",__PRETTY_FUNCTION__); */
886     for (i = width / 4; i > 0; i--)
887     {
888         LOAD_VECTORS (dest, src);
889
890         vdest = pix_add_mul (vsrc, splat_alpha (vdest),
891                              vdest, splat_alpha (negate (vsrc)));
892
893         STORE_VECTOR (dest);
894
895         src += 4;
896         dest += 4;
897     }
898
899     for (i = width % 4; --i >= 0;)
900     {
901         uint32_t s = src[i];
902         uint32_t d = dest[i];
903         uint32_t dest_a = ALPHA_8 (d);
904         uint32_t src_ia = ALPHA_8 (~s);
905
906         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia);
907
908         dest[i] = s;
909     }
910 }
911
912 static void
913 vmx_combine_atop_u_mask (uint32_t *      dest,
914                          const uint32_t *src,
915                          const uint32_t *mask,
916                          int             width)
917 {
918     int i;
919     vector unsigned int vdest, vsrc, vmask;
920     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
921
922     while (width && ((uintptr_t)dest & 15))
923     {
924         uint32_t m = ALPHA_8 (*mask++);
925         uint32_t s = *src++;
926         uint32_t d = *dest;
927         uint32_t dest_a = ALPHA_8 (d);
928         uint32_t src_ia;
929
930         UN8x4_MUL_UN8 (s, m);
931
932         src_ia = ALPHA_8 (~s);
933
934         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia);
935
936         *dest++ = s;
937         width--;
938     }
939
940     COMPUTE_SHIFT_MASKC (dest, src, mask);
941
942     /* printf ("%s\n",__PRETTY_FUNCTION__); */
943     for (i = width / 4; i > 0; i--)
944     {
945         LOAD_VECTORSM (dest, src, mask);
946
947         vdest = pix_add_mul (vsrc, splat_alpha (vdest),
948                              vdest, splat_alpha (negate (vsrc)));
949
950         STORE_VECTOR (dest);
951
952         src += 4;
953         dest += 4;
954         mask += 4;
955     }
956
957     for (i = width % 4; --i >= 0;)
958     {
959         uint32_t m = ALPHA_8 (mask[i]);
960         uint32_t s = src[i];
961         uint32_t d = dest[i];
962         uint32_t dest_a = ALPHA_8 (d);
963         uint32_t src_ia;
964
965         UN8x4_MUL_UN8 (s, m);
966
967         src_ia = ALPHA_8 (~s);
968
969         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia);
970
971         dest[i] = s;
972     }
973 }
974
975 static void
976 vmx_combine_atop_u (pixman_implementation_t *imp,
977                     pixman_op_t              op,
978                     uint32_t *               dest,
979                     const uint32_t *         src,
980                     const uint32_t *         mask,
981                     int                      width)
982 {
983     if (mask)
984         vmx_combine_atop_u_mask (dest, src, mask, width);
985     else
986         vmx_combine_atop_u_no_mask (dest, src, width);
987 }
988
989 static void
990 vmx_combine_atop_reverse_u_no_mask (uint32_t *      dest,
991                                     const uint32_t *src,
992                                     int             width)
993 {
994     int i;
995     vector unsigned int vdest, vsrc;
996     vector unsigned char tmp1, tmp2, src_mask;
997
998     while (width && ((uintptr_t)dest & 15))
999     {
1000         uint32_t s = *src++;
1001         uint32_t d = *dest;
1002         uint32_t src_a = ALPHA_8 (s);
1003         uint32_t dest_ia = ALPHA_8 (~d);
1004
1005         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a);
1006
1007         *dest++ = s;
1008         width--;
1009     }
1010
1011     COMPUTE_SHIFT_MASKS (dest, src);
1012
1013     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1014     for (i = width / 4; i > 0; i--)
1015     {
1016         LOAD_VECTORS (dest, src);
1017
1018         vdest = pix_add_mul (vdest, splat_alpha (vsrc),
1019                              vsrc, splat_alpha (negate (vdest)));
1020
1021         STORE_VECTOR (dest);
1022
1023         src += 4;
1024         dest += 4;
1025     }
1026
1027     for (i = width % 4; --i >= 0;)
1028     {
1029         uint32_t s = src[i];
1030         uint32_t d = dest[i];
1031         uint32_t src_a = ALPHA_8 (s);
1032         uint32_t dest_ia = ALPHA_8 (~d);
1033
1034         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a);
1035
1036         dest[i] = s;
1037     }
1038 }
1039
1040 static void
1041 vmx_combine_atop_reverse_u_mask (uint32_t *      dest,
1042                                  const uint32_t *src,
1043                                  const uint32_t *mask,
1044                                  int             width)
1045 {
1046     int i;
1047     vector unsigned int vdest, vsrc, vmask;
1048     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
1049
1050     while (width && ((uintptr_t)dest & 15))
1051     {
1052         uint32_t m = ALPHA_8 (*mask++);
1053         uint32_t s = *src++;
1054         uint32_t d = *dest;
1055         uint32_t src_a;
1056         uint32_t dest_ia = ALPHA_8 (~d);
1057
1058         UN8x4_MUL_UN8 (s, m);
1059
1060         src_a = ALPHA_8 (s);
1061
1062         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a);
1063
1064         *dest++ = s;
1065         width--;
1066     }
1067
1068     COMPUTE_SHIFT_MASKC (dest, src, mask);
1069
1070     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1071     for (i = width / 4; i > 0; i--)
1072     {
1073         LOAD_VECTORSM (dest, src, mask);
1074
1075         vdest = pix_add_mul (vdest, splat_alpha (vsrc),
1076                              vsrc, splat_alpha (negate (vdest)));
1077
1078         STORE_VECTOR (dest);
1079
1080         src += 4;
1081         dest += 4;
1082         mask += 4;
1083     }
1084
1085     for (i = width % 4; --i >= 0;)
1086     {
1087         uint32_t m = ALPHA_8 (mask[i]);
1088         uint32_t s = src[i];
1089         uint32_t d = dest[i];
1090         uint32_t src_a;
1091         uint32_t dest_ia = ALPHA_8 (~d);
1092
1093         UN8x4_MUL_UN8 (s, m);
1094
1095         src_a = ALPHA_8 (s);
1096
1097         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a);
1098
1099         dest[i] = s;
1100     }
1101 }
1102
1103 static void
1104 vmx_combine_atop_reverse_u (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     if (mask)
1112         vmx_combine_atop_reverse_u_mask (dest, src, mask, width);
1113     else
1114         vmx_combine_atop_reverse_u_no_mask (dest, src, width);
1115 }
1116
1117 static void
1118 vmx_combine_xor_u_no_mask (uint32_t *      dest,
1119                            const uint32_t *src,
1120                            int             width)
1121 {
1122     int i;
1123     vector unsigned int vdest, vsrc;
1124     vector unsigned char tmp1, tmp2, src_mask;
1125
1126     while (width && ((uintptr_t)dest & 15))
1127     {
1128         uint32_t s = *src++;
1129         uint32_t d = *dest;
1130         uint32_t src_ia = ALPHA_8 (~s);
1131         uint32_t dest_ia = ALPHA_8 (~d);
1132
1133         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_ia);
1134
1135         *dest++ = s;
1136         width--;
1137     }
1138
1139     COMPUTE_SHIFT_MASKS (dest, src);
1140
1141     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1142     for (i = width / 4; i > 0; i--)
1143     {
1144         LOAD_VECTORS (dest, src);
1145
1146         vdest = pix_add_mul (vsrc, splat_alpha (negate (vdest)),
1147                              vdest, splat_alpha (negate (vsrc)));
1148
1149         STORE_VECTOR (dest);
1150
1151         src += 4;
1152         dest += 4;
1153     }
1154
1155     for (i = width % 4; --i >= 0;)
1156     {
1157         uint32_t s = src[i];
1158         uint32_t d = dest[i];
1159         uint32_t src_ia = ALPHA_8 (~s);
1160         uint32_t dest_ia = ALPHA_8 (~d);
1161
1162         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_ia);
1163
1164         dest[i] = s;
1165     }
1166 }
1167
1168 static void
1169 vmx_combine_xor_u_mask (uint32_t *      dest,
1170                         const uint32_t *src,
1171                         const uint32_t *mask,
1172                         int             width)
1173 {
1174     int i;
1175     vector unsigned int vdest, vsrc, vmask;
1176     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
1177
1178     while (width && ((uintptr_t)dest & 15))
1179     {
1180         uint32_t m = ALPHA_8 (*mask++);
1181         uint32_t s = *src++;
1182         uint32_t d = *dest;
1183         uint32_t src_ia;
1184         uint32_t dest_ia = ALPHA_8 (~d);
1185
1186         UN8x4_MUL_UN8 (s, m);
1187
1188         src_ia = ALPHA_8 (~s);
1189
1190         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_ia);
1191
1192         *dest++ = s;
1193         width--;
1194     }
1195
1196     COMPUTE_SHIFT_MASKC (dest, src, mask);
1197
1198     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1199     for (i = width / 4; i > 0; i--)
1200     {
1201         LOAD_VECTORSM (dest, src, mask);
1202
1203         vdest = pix_add_mul (vsrc, splat_alpha (negate (vdest)),
1204                              vdest, splat_alpha (negate (vsrc)));
1205
1206         STORE_VECTOR (dest);
1207
1208         src += 4;
1209         dest += 4;
1210         mask += 4;
1211     }
1212
1213     for (i = width % 4; --i >= 0;)
1214     {
1215         uint32_t m = ALPHA_8 (mask[i]);
1216         uint32_t s = src[i];
1217         uint32_t d = dest[i];
1218         uint32_t src_ia;
1219         uint32_t dest_ia = ALPHA_8 (~d);
1220
1221         UN8x4_MUL_UN8 (s, m);
1222
1223         src_ia = ALPHA_8 (~s);
1224
1225         UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_ia);
1226
1227         dest[i] = s;
1228     }
1229 }
1230
1231 static void
1232 vmx_combine_xor_u (pixman_implementation_t *imp,
1233                    pixman_op_t              op,
1234                    uint32_t *               dest,
1235                    const uint32_t *         src,
1236                    const uint32_t *         mask,
1237                    int                      width)
1238 {
1239     if (mask)
1240         vmx_combine_xor_u_mask (dest, src, mask, width);
1241     else
1242         vmx_combine_xor_u_no_mask (dest, src, width);
1243 }
1244
1245 static void
1246 vmx_combine_add_u_no_mask (uint32_t *      dest,
1247                            const uint32_t *src,
1248                            int             width)
1249 {
1250     int i;
1251     vector unsigned int vdest, vsrc;
1252     vector unsigned char tmp1, tmp2, src_mask;
1253
1254     while (width && ((uintptr_t)dest & 15))
1255     {
1256         uint32_t s = *src++;
1257         uint32_t d = *dest;
1258
1259         UN8x4_ADD_UN8x4 (d, s);
1260
1261         *dest++ = d;
1262         width--;
1263     }
1264
1265     COMPUTE_SHIFT_MASKS (dest, src);
1266     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1267     for (i = width / 4; i > 0; i--)
1268     {
1269         LOAD_VECTORS (dest, src);
1270
1271         vdest = pix_add (vsrc, vdest);
1272
1273         STORE_VECTOR (dest);
1274
1275         src += 4;
1276         dest += 4;
1277     }
1278
1279     for (i = width % 4; --i >= 0;)
1280     {
1281         uint32_t s = src[i];
1282         uint32_t d = dest[i];
1283
1284         UN8x4_ADD_UN8x4 (d, s);
1285
1286         dest[i] = d;
1287     }
1288 }
1289
1290 static void
1291 vmx_combine_add_u_mask (uint32_t *      dest,
1292                         const uint32_t *src,
1293                         const uint32_t *mask,
1294                         int             width)
1295 {
1296     int i;
1297     vector unsigned int vdest, vsrc, vmask;
1298     vector unsigned char tmp1, tmp2, src_mask, mask_mask;
1299
1300     while (width && ((uintptr_t)dest & 15))
1301     {
1302         uint32_t m = ALPHA_8 (*mask++);
1303         uint32_t s = *src++;
1304         uint32_t d = *dest;
1305
1306         UN8x4_MUL_UN8 (s, m);
1307         UN8x4_ADD_UN8x4 (d, s);
1308
1309         *dest++ = d;
1310         width--;
1311     }
1312
1313     COMPUTE_SHIFT_MASKC (dest, src, mask);
1314
1315     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1316     for (i = width / 4; i > 0; i--)
1317     {
1318         LOAD_VECTORSM (dest, src, mask);
1319
1320         vdest = pix_add (vsrc, vdest);
1321
1322         STORE_VECTOR (dest);
1323
1324         src += 4;
1325         dest += 4;
1326         mask += 4;
1327     }
1328
1329     for (i = width % 4; --i >= 0;)
1330     {
1331         uint32_t m = ALPHA_8 (mask[i]);
1332         uint32_t s = src[i];
1333         uint32_t d = dest[i];
1334
1335         UN8x4_MUL_UN8 (s, m);
1336         UN8x4_ADD_UN8x4 (d, s);
1337
1338         dest[i] = d;
1339     }
1340 }
1341
1342 static void
1343 vmx_combine_add_u (pixman_implementation_t *imp,
1344                    pixman_op_t              op,
1345                    uint32_t *               dest,
1346                    const uint32_t *         src,
1347                    const uint32_t *         mask,
1348                    int                      width)
1349 {
1350     if (mask)
1351         vmx_combine_add_u_mask (dest, src, mask, width);
1352     else
1353         vmx_combine_add_u_no_mask (dest, src, width);
1354 }
1355
1356 static void
1357 vmx_combine_src_ca (pixman_implementation_t *imp,
1358                     pixman_op_t              op,
1359                     uint32_t *               dest,
1360                     const uint32_t *         src,
1361                     const uint32_t *         mask,
1362                     int                      width)
1363 {
1364     int i;
1365     vector unsigned int vdest, vsrc, vmask;
1366     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1367
1368     while (width && ((uintptr_t)dest & 15))
1369     {
1370         uint32_t a = *mask++;
1371         uint32_t s = *src++;
1372
1373         UN8x4_MUL_UN8x4 (s, a);
1374
1375         *dest++ = s;
1376         width--;
1377     }
1378
1379     COMPUTE_SHIFT_MASKC (dest, src, mask);
1380
1381     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1382     for (i = width / 4; i > 0; i--)
1383     {
1384         LOAD_VECTORSC (dest, src, mask);
1385
1386         vdest = pix_multiply (vsrc, vmask);
1387
1388         STORE_VECTOR (dest);
1389
1390         mask += 4;
1391         src += 4;
1392         dest += 4;
1393     }
1394
1395     for (i = width % 4; --i >= 0;)
1396     {
1397         uint32_t a = mask[i];
1398         uint32_t s = src[i];
1399
1400         UN8x4_MUL_UN8x4 (s, a);
1401
1402         dest[i] = s;
1403     }
1404 }
1405
1406 static void
1407 vmx_combine_over_ca (pixman_implementation_t *imp,
1408                      pixman_op_t              op,
1409                      uint32_t *               dest,
1410                      const uint32_t *         src,
1411                      const uint32_t *         mask,
1412                      int                      width)
1413 {
1414     int i;
1415     vector unsigned int vdest, vsrc, vmask;
1416     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1417
1418     while (width && ((uintptr_t)dest & 15))
1419     {
1420         uint32_t a = *mask++;
1421         uint32_t s = *src++;
1422         uint32_t d = *dest;
1423         uint32_t sa = ALPHA_8 (s);
1424
1425         UN8x4_MUL_UN8x4 (s, a);
1426         UN8x4_MUL_UN8 (a, sa);
1427         UN8x4_MUL_UN8x4_ADD_UN8x4 (d, ~a, s);
1428
1429         *dest++ = d;
1430         width--;
1431     }
1432
1433     COMPUTE_SHIFT_MASKC (dest, src, mask);
1434
1435     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1436     for (i = width / 4; i > 0; i--)
1437     {
1438         LOAD_VECTORSC (dest, src, mask);
1439
1440         vdest = in_over (vsrc, splat_alpha (vsrc), vmask, vdest);
1441
1442         STORE_VECTOR (dest);
1443
1444         mask += 4;
1445         src += 4;
1446         dest += 4;
1447     }
1448
1449     for (i = width % 4; --i >= 0;)
1450     {
1451         uint32_t a = mask[i];
1452         uint32_t s = src[i];
1453         uint32_t d = dest[i];
1454         uint32_t sa = ALPHA_8 (s);
1455
1456         UN8x4_MUL_UN8x4 (s, a);
1457         UN8x4_MUL_UN8 (a, sa);
1458         UN8x4_MUL_UN8x4_ADD_UN8x4 (d, ~a, s);
1459
1460         dest[i] = d;
1461     }
1462 }
1463
1464 static void
1465 vmx_combine_over_reverse_ca (pixman_implementation_t *imp,
1466                              pixman_op_t              op,
1467                              uint32_t *               dest,
1468                              const uint32_t *         src,
1469                              const uint32_t *         mask,
1470                              int                      width)
1471 {
1472     int i;
1473     vector unsigned int vdest, vsrc, vmask;
1474     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1475
1476     while (width && ((uintptr_t)dest & 15))
1477     {
1478         uint32_t a = *mask++;
1479         uint32_t s = *src++;
1480         uint32_t d = *dest;
1481         uint32_t ida = ALPHA_8 (~d);
1482
1483         UN8x4_MUL_UN8x4 (s, a);
1484         UN8x4_MUL_UN8_ADD_UN8x4 (s, ida, d);
1485
1486         *dest++ = s;
1487         width--;
1488     }
1489
1490     COMPUTE_SHIFT_MASKC (dest, src, mask);
1491
1492     /* printf("%s\n",__PRETTY_FUNCTION__); */
1493     for (i = width / 4; i > 0; i--)
1494     {
1495         LOAD_VECTORSC (dest, src, mask);
1496
1497         vdest = over (vdest, splat_alpha (vdest), pix_multiply (vsrc, vmask));
1498
1499         STORE_VECTOR (dest);
1500
1501         mask += 4;
1502         src += 4;
1503         dest += 4;
1504     }
1505
1506     for (i = width % 4; --i >= 0;)
1507     {
1508         uint32_t a = mask[i];
1509         uint32_t s = src[i];
1510         uint32_t d = dest[i];
1511         uint32_t ida = ALPHA_8 (~d);
1512
1513         UN8x4_MUL_UN8x4 (s, a);
1514         UN8x4_MUL_UN8_ADD_UN8x4 (s, ida, d);
1515
1516         dest[i] = s;
1517     }
1518 }
1519
1520 static void
1521 vmx_combine_in_ca (pixman_implementation_t *imp,
1522                    pixman_op_t              op,
1523                    uint32_t *               dest,
1524                    const uint32_t *         src,
1525                    const uint32_t *         mask,
1526                    int                      width)
1527 {
1528     int i;
1529     vector unsigned int vdest, vsrc, vmask;
1530     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1531
1532     while (width && ((uintptr_t)dest & 15))
1533     {
1534         uint32_t a = *mask++;
1535         uint32_t s = *src++;
1536         uint32_t da = ALPHA_8 (*dest);
1537
1538         UN8x4_MUL_UN8x4 (s, a);
1539         UN8x4_MUL_UN8 (s, da);
1540
1541         *dest++ = s;
1542         width--;
1543     }
1544
1545     COMPUTE_SHIFT_MASKC (dest, src, mask);
1546
1547     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1548     for (i = width / 4; i > 0; i--)
1549     {
1550         LOAD_VECTORSC (dest, src, mask);
1551
1552         vdest = pix_multiply (pix_multiply (vsrc, vmask), splat_alpha (vdest));
1553
1554         STORE_VECTOR (dest);
1555
1556         src += 4;
1557         dest += 4;
1558         mask += 4;
1559     }
1560
1561     for (i = width % 4; --i >= 0;)
1562     {
1563         uint32_t a = mask[i];
1564         uint32_t s = src[i];
1565         uint32_t da = ALPHA_8 (dest[i]);
1566
1567         UN8x4_MUL_UN8x4 (s, a);
1568         UN8x4_MUL_UN8 (s, da);
1569
1570         dest[i] = s;
1571     }
1572 }
1573
1574 static void
1575 vmx_combine_in_reverse_ca (pixman_implementation_t *imp,
1576                            pixman_op_t              op,
1577                            uint32_t *               dest,
1578                            const uint32_t *         src,
1579                            const uint32_t *         mask,
1580                            int                      width)
1581 {
1582     int i;
1583     vector unsigned int vdest, vsrc, vmask;
1584     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1585
1586     while (width && ((uintptr_t)dest & 15))
1587     {
1588         uint32_t a = *mask++;
1589         uint32_t d = *dest;
1590         uint32_t sa = ALPHA_8 (*src++);
1591
1592         UN8x4_MUL_UN8 (a, sa);
1593         UN8x4_MUL_UN8x4 (d, a);
1594
1595         *dest++ = d;
1596         width--;
1597     }
1598
1599     COMPUTE_SHIFT_MASKC (dest, src, mask);
1600
1601     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1602     for (i = width / 4; i > 0; i--)
1603     {
1604
1605         LOAD_VECTORSC (dest, src, mask);
1606
1607         vdest = pix_multiply (vdest, pix_multiply (vmask, splat_alpha (vsrc)));
1608
1609         STORE_VECTOR (dest);
1610
1611         src += 4;
1612         dest += 4;
1613         mask += 4;
1614     }
1615
1616     for (i = width % 4; --i >= 0;)
1617     {
1618         uint32_t a = mask[i];
1619         uint32_t d = dest[i];
1620         uint32_t sa = ALPHA_8 (src[i]);
1621
1622         UN8x4_MUL_UN8 (a, sa);
1623         UN8x4_MUL_UN8x4 (d, a);
1624
1625         dest[i] = d;
1626     }
1627 }
1628
1629 static void
1630 vmx_combine_out_ca (pixman_implementation_t *imp,
1631                     pixman_op_t              op,
1632                     uint32_t *               dest,
1633                     const uint32_t *         src,
1634                     const uint32_t *         mask,
1635                     int                      width)
1636 {
1637     int i;
1638     vector unsigned int vdest, vsrc, vmask;
1639     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1640
1641     while (width && ((uintptr_t)dest & 15))
1642     {
1643         uint32_t a = *mask++;
1644         uint32_t s = *src++;
1645         uint32_t d = *dest;
1646         uint32_t da = ALPHA_8 (~d);
1647
1648         UN8x4_MUL_UN8x4 (s, a);
1649         UN8x4_MUL_UN8 (s, da);
1650
1651         *dest++ = s;
1652         width--;
1653     }
1654
1655     COMPUTE_SHIFT_MASKC (dest, src, mask);
1656
1657     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1658     for (i = width / 4; i > 0; i--)
1659     {
1660         LOAD_VECTORSC (dest, src, mask);
1661
1662         vdest = pix_multiply (
1663             pix_multiply (vsrc, vmask), splat_alpha (negate (vdest)));
1664
1665         STORE_VECTOR (dest);
1666
1667         src += 4;
1668         dest += 4;
1669         mask += 4;
1670     }
1671
1672     for (i = width % 4; --i >= 0;)
1673     {
1674         uint32_t a = mask[i];
1675         uint32_t s = src[i];
1676         uint32_t d = dest[i];
1677         uint32_t da = ALPHA_8 (~d);
1678
1679         UN8x4_MUL_UN8x4 (s, a);
1680         UN8x4_MUL_UN8 (s, da);
1681
1682         dest[i] = s;
1683     }
1684 }
1685
1686 static void
1687 vmx_combine_out_reverse_ca (pixman_implementation_t *imp,
1688                             pixman_op_t              op,
1689                             uint32_t *               dest,
1690                             const uint32_t *         src,
1691                             const uint32_t *         mask,
1692                             int                      width)
1693 {
1694     int i;
1695     vector unsigned int vdest, vsrc, vmask;
1696     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1697
1698     while (width && ((uintptr_t)dest & 15))
1699     {
1700         uint32_t a = *mask++;
1701         uint32_t s = *src++;
1702         uint32_t d = *dest;
1703         uint32_t sa = ALPHA_8 (s);
1704
1705         UN8x4_MUL_UN8 (a, sa);
1706         UN8x4_MUL_UN8x4 (d, ~a);
1707
1708         *dest++ = d;
1709         width--;
1710     }
1711
1712     COMPUTE_SHIFT_MASKC (dest, src, mask);
1713
1714     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1715     for (i = width / 4; i > 0; i--)
1716     {
1717         LOAD_VECTORSC (dest, src, mask);
1718
1719         vdest = pix_multiply (
1720             vdest, negate (pix_multiply (vmask, splat_alpha (vsrc))));
1721
1722         STORE_VECTOR (dest);
1723
1724         src += 4;
1725         dest += 4;
1726         mask += 4;
1727     }
1728
1729     for (i = width % 4; --i >= 0;)
1730     {
1731         uint32_t a = mask[i];
1732         uint32_t s = src[i];
1733         uint32_t d = dest[i];
1734         uint32_t sa = ALPHA_8 (s);
1735
1736         UN8x4_MUL_UN8 (a, sa);
1737         UN8x4_MUL_UN8x4 (d, ~a);
1738
1739         dest[i] = d;
1740     }
1741 }
1742
1743 static void
1744 vmx_combine_atop_ca (pixman_implementation_t *imp,
1745                      pixman_op_t              op,
1746                      uint32_t *               dest,
1747                      const uint32_t *         src,
1748                      const uint32_t *         mask,
1749                      int                      width)
1750 {
1751     int i;
1752     vector unsigned int vdest, vsrc, vmask, vsrca;
1753     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1754
1755     while (width && ((uintptr_t)dest & 15))
1756     {
1757         uint32_t a = *mask++;
1758         uint32_t s = *src++;
1759         uint32_t d = *dest;
1760         uint32_t sa = ALPHA_8 (s);
1761         uint32_t da = ALPHA_8 (d);
1762
1763         UN8x4_MUL_UN8x4 (s, a);
1764         UN8x4_MUL_UN8 (a, sa);
1765         UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ~a, s, da);
1766
1767         *dest++ = d;
1768         width--;
1769     }
1770
1771     COMPUTE_SHIFT_MASKC (dest, src, mask);
1772
1773     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1774     for (i = width / 4; i > 0; i--)
1775     {
1776         LOAD_VECTORSC (dest, src, mask);
1777
1778         vsrca = splat_alpha (vsrc);
1779
1780         vsrc = pix_multiply (vsrc, vmask);
1781         vmask = pix_multiply (vmask, vsrca);
1782
1783         vdest = pix_add_mul (vsrc, splat_alpha (vdest),
1784                              negate (vmask), vdest);
1785
1786         STORE_VECTOR (dest);
1787
1788         src += 4;
1789         dest += 4;
1790         mask += 4;
1791     }
1792
1793     for (i = width % 4; --i >= 0;)
1794     {
1795         uint32_t a = mask[i];
1796         uint32_t s = src[i];
1797         uint32_t d = dest[i];
1798         uint32_t sa = ALPHA_8 (s);
1799         uint32_t da = ALPHA_8 (d);
1800
1801         UN8x4_MUL_UN8x4 (s, a);
1802         UN8x4_MUL_UN8 (a, sa);
1803         UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ~a, s, da);
1804
1805         dest[i] = d;
1806     }
1807 }
1808
1809 static void
1810 vmx_combine_atop_reverse_ca (pixman_implementation_t *imp,
1811                              pixman_op_t              op,
1812                              uint32_t *               dest,
1813                              const uint32_t *         src,
1814                              const uint32_t *         mask,
1815                              int                      width)
1816 {
1817     int i;
1818     vector unsigned int vdest, vsrc, vmask;
1819     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1820
1821     while (width && ((uintptr_t)dest & 15))
1822     {
1823         uint32_t a = *mask++;
1824         uint32_t s = *src++;
1825         uint32_t d = *dest;
1826         uint32_t sa = ALPHA_8 (s);
1827         uint32_t da = ALPHA_8 (~d);
1828
1829         UN8x4_MUL_UN8x4 (s, a);
1830         UN8x4_MUL_UN8 (a, sa);
1831         UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, a, s, da);
1832
1833         *dest++ = d;
1834         width--;
1835     }
1836
1837     COMPUTE_SHIFT_MASKC (dest, src, mask);
1838
1839     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1840     for (i = width / 4; i > 0; i--)
1841     {
1842         LOAD_VECTORSC (dest, src, mask);
1843
1844         vdest = pix_add_mul (vdest,
1845                              pix_multiply (vmask, splat_alpha (vsrc)),
1846                              pix_multiply (vsrc, vmask),
1847                              negate (splat_alpha (vdest)));
1848
1849         STORE_VECTOR (dest);
1850
1851         src += 4;
1852         dest += 4;
1853         mask += 4;
1854     }
1855
1856     for (i = width % 4; --i >= 0;)
1857     {
1858         uint32_t a = mask[i];
1859         uint32_t s = src[i];
1860         uint32_t d = dest[i];
1861         uint32_t sa = ALPHA_8 (s);
1862         uint32_t da = ALPHA_8 (~d);
1863
1864         UN8x4_MUL_UN8x4 (s, a);
1865         UN8x4_MUL_UN8 (a, sa);
1866         UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, a, s, da);
1867
1868         dest[i] = d;
1869     }
1870 }
1871
1872 static void
1873 vmx_combine_xor_ca (pixman_implementation_t *imp,
1874                     pixman_op_t              op,
1875                     uint32_t *               dest,
1876                     const uint32_t *         src,
1877                     const uint32_t *         mask,
1878                     int                      width)
1879 {
1880     int i;
1881     vector unsigned int vdest, vsrc, vmask;
1882     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1883
1884     while (width && ((uintptr_t)dest & 15))
1885     {
1886         uint32_t a = *mask++;
1887         uint32_t s = *src++;
1888         uint32_t d = *dest;
1889         uint32_t sa = ALPHA_8 (s);
1890         uint32_t da = ALPHA_8 (~d);
1891
1892         UN8x4_MUL_UN8x4 (s, a);
1893         UN8x4_MUL_UN8 (a, sa);
1894         UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ~a, s, da);
1895
1896         *dest++ = d;
1897         width--;
1898     }
1899
1900     COMPUTE_SHIFT_MASKC (dest, src, mask);
1901
1902     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1903     for (i = width / 4; i > 0; i--)
1904     {
1905         LOAD_VECTORSC (dest, src, mask);
1906
1907         vdest = pix_add_mul (vdest,
1908                              negate (pix_multiply (vmask, splat_alpha (vsrc))),
1909                              pix_multiply (vsrc, vmask),
1910                              negate (splat_alpha (vdest)));
1911
1912         STORE_VECTOR (dest);
1913
1914         src += 4;
1915         dest += 4;
1916         mask += 4;
1917     }
1918
1919     for (i = width % 4; --i >= 0;)
1920     {
1921         uint32_t a = mask[i];
1922         uint32_t s = src[i];
1923         uint32_t d = dest[i];
1924         uint32_t sa = ALPHA_8 (s);
1925         uint32_t da = ALPHA_8 (~d);
1926
1927         UN8x4_MUL_UN8x4 (s, a);
1928         UN8x4_MUL_UN8 (a, sa);
1929         UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ~a, s, da);
1930
1931         dest[i] = d;
1932     }
1933 }
1934
1935 static void
1936 vmx_combine_add_ca (pixman_implementation_t *imp,
1937                     pixman_op_t              op,
1938                     uint32_t *               dest,
1939                     const uint32_t *         src,
1940                     const uint32_t *         mask,
1941                     int                      width)
1942 {
1943     int i;
1944     vector unsigned int vdest, vsrc, vmask;
1945     vector unsigned char tmp1, tmp2, mask_mask, src_mask;
1946
1947     while (width && ((uintptr_t)dest & 15))
1948     {
1949         uint32_t a = *mask++;
1950         uint32_t s = *src++;
1951         uint32_t d = *dest;
1952
1953         UN8x4_MUL_UN8x4 (s, a);
1954         UN8x4_ADD_UN8x4 (s, d);
1955
1956         *dest++ = s;
1957         width--;
1958     }
1959
1960     COMPUTE_SHIFT_MASKC (dest, src, mask);
1961
1962     /* printf ("%s\n",__PRETTY_FUNCTION__); */
1963     for (i = width / 4; i > 0; i--)
1964     {
1965         LOAD_VECTORSC (dest, src, mask);
1966
1967         vdest = pix_add (pix_multiply (vsrc, vmask), vdest);
1968
1969         STORE_VECTOR (dest);
1970
1971         src += 4;
1972         dest += 4;
1973         mask += 4;
1974     }
1975
1976     for (i = width % 4; --i >= 0;)
1977     {
1978         uint32_t a = mask[i];
1979         uint32_t s = src[i];
1980         uint32_t d = dest[i];
1981
1982         UN8x4_MUL_UN8x4 (s, a);
1983         UN8x4_ADD_UN8x4 (s, d);
1984
1985         dest[i] = s;
1986     }
1987 }
1988
1989 static const pixman_fast_path_t vmx_fast_paths[] =
1990 {
1991     {   PIXMAN_OP_NONE  },
1992 };
1993
1994 pixman_implementation_t *
1995 _pixman_implementation_create_vmx (pixman_implementation_t *fallback)
1996 {
1997     pixman_implementation_t *imp = _pixman_implementation_create (fallback, vmx_fast_paths);
1998
1999     /* Set up function pointers */
2000
2001     imp->combine_32[PIXMAN_OP_OVER] = vmx_combine_over_u;
2002     imp->combine_32[PIXMAN_OP_OVER_REVERSE] = vmx_combine_over_reverse_u;
2003     imp->combine_32[PIXMAN_OP_IN] = vmx_combine_in_u;
2004     imp->combine_32[PIXMAN_OP_IN_REVERSE] = vmx_combine_in_reverse_u;
2005     imp->combine_32[PIXMAN_OP_OUT] = vmx_combine_out_u;
2006     imp->combine_32[PIXMAN_OP_OUT_REVERSE] = vmx_combine_out_reverse_u;
2007     imp->combine_32[PIXMAN_OP_ATOP] = vmx_combine_atop_u;
2008     imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = vmx_combine_atop_reverse_u;
2009     imp->combine_32[PIXMAN_OP_XOR] = vmx_combine_xor_u;
2010
2011     imp->combine_32[PIXMAN_OP_ADD] = vmx_combine_add_u;
2012
2013     imp->combine_32_ca[PIXMAN_OP_SRC] = vmx_combine_src_ca;
2014     imp->combine_32_ca[PIXMAN_OP_OVER] = vmx_combine_over_ca;
2015     imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = vmx_combine_over_reverse_ca;
2016     imp->combine_32_ca[PIXMAN_OP_IN] = vmx_combine_in_ca;
2017     imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = vmx_combine_in_reverse_ca;
2018     imp->combine_32_ca[PIXMAN_OP_OUT] = vmx_combine_out_ca;
2019     imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = vmx_combine_out_reverse_ca;
2020     imp->combine_32_ca[PIXMAN_OP_ATOP] = vmx_combine_atop_ca;
2021     imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = vmx_combine_atop_reverse_ca;
2022     imp->combine_32_ca[PIXMAN_OP_XOR] = vmx_combine_xor_ca;
2023     imp->combine_32_ca[PIXMAN_OP_ADD] = vmx_combine_add_ca;
2024
2025     return imp;
2026 }