ppc: dsputil: Drop some unnecessary parentheses
[ffmpeg.git] / libavcodec / ppc / dsputil_altivec.c
1 /*
2  * Copyright (c) 2002 Brian Foley
3  * Copyright (c) 2002 Dieter Shirley
4  * Copyright (c) 2003-2004 Romain Dolbeau <romain@dolbeau.org>
5  *
6  * This file is part of Libav.
7  *
8  * Libav is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * Libav is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "config.h"
24 #if HAVE_ALTIVEC_H
25 #include <altivec.h>
26 #endif
27
28 #include "libavutil/attributes.h"
29 #include "libavutil/ppc/types_altivec.h"
30 #include "libavutil/ppc/util_altivec.h"
31 #include "libavcodec/avcodec.h"
32 #include "libavcodec/dsputil.h"
33 #include "dsputil_altivec.h"
34
35 static int sad16_x2_altivec(void *v, uint8_t *pix1, uint8_t *pix2,
36                             int line_size, int h)
37 {
38     int i;
39     int s;
40     const vector unsigned char zero =
41         (const vector unsigned char) vec_splat_u8(0);
42     vector unsigned char perm1 = vec_lvsl(0, pix2);
43     vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1));
44     vector unsigned char pix2l, pix2r;
45     vector unsigned char pix1v, pix2v, pix2iv, avgv, t5;
46     vector unsigned int sad;
47     vector signed int sumdiffs;
48
49     s = 0;
50     sad = (vector unsigned int) vec_splat_u32(0);
51     for (i = 0; i < h; i++) {
52         /* Read unaligned pixels into our vectors. The vectors are as follows:
53          * pix1v: pix1[0] - pix1[15]
54          * pix2v: pix2[0] - pix2[15]      pix2iv: pix2[1] - pix2[16] */
55         pix1v  = vec_ld(0,  pix1);
56         pix2l  = vec_ld(0,  pix2);
57         pix2r  = vec_ld(16, pix2);
58         pix2v  = vec_perm(pix2l, pix2r, perm1);
59         pix2iv = vec_perm(pix2l, pix2r, perm2);
60
61         /* Calculate the average vector. */
62         avgv = vec_avg(pix2v, pix2iv);
63
64         /* Calculate a sum of abs differences vector. */
65         t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv));
66
67         /* Add each 4 pixel group together and put 4 results into sad. */
68         sad = vec_sum4s(t5, sad);
69
70         pix1 += line_size;
71         pix2 += line_size;
72     }
73     /* Sum up the four partial sums, and put the result into s. */
74     sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
75     sumdiffs = vec_splat(sumdiffs, 3);
76     vec_ste(sumdiffs, 0, &s);
77
78     return s;
79 }
80
81 static int sad16_y2_altivec(void *v, uint8_t *pix1, uint8_t *pix2,
82                             int line_size, int h)
83 {
84     int i;
85     int s;
86     const vector unsigned char zero =
87         (const vector unsigned char) vec_splat_u8(0);
88     vector unsigned char perm = vec_lvsl(0, pix2);
89     vector unsigned char pix2l, pix2r;
90     vector unsigned char pix1v, pix2v, pix3v, avgv, t5;
91     vector unsigned int sad;
92     vector signed int sumdiffs;
93     uint8_t *pix3 = pix2 + line_size;
94
95     s = 0;
96     sad = (vector unsigned int) vec_splat_u32(0);
97
98     /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one
99      * iteration becomes pix2 in the next iteration. We can use this
100      * fact to avoid a potentially expensive unaligned read, each
101      * time around the loop.
102      * Read unaligned pixels into our vectors. The vectors are as follows:
103      * pix2v: pix2[0] - pix2[15]
104      * Split the pixel vectors into shorts. */
105     pix2l = vec_ld(0,  pix2);
106     pix2r = vec_ld(15, pix2);
107     pix2v = vec_perm(pix2l, pix2r, perm);
108
109     for (i = 0; i < h; i++) {
110         /* Read unaligned pixels into our vectors. The vectors are as follows:
111          * pix1v: pix1[0] - pix1[15]
112          * pix3v: pix3[0] - pix3[15] */
113         pix1v = vec_ld(0,  pix1);
114
115         pix2l = vec_ld(0,  pix3);
116         pix2r = vec_ld(15, pix3);
117         pix3v = vec_perm(pix2l, pix2r, perm);
118
119         /* Calculate the average vector. */
120         avgv = vec_avg(pix2v, pix3v);
121
122         /* Calculate a sum of abs differences vector. */
123         t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv));
124
125         /* Add each 4 pixel group together and put 4 results into sad. */
126         sad = vec_sum4s(t5, sad);
127
128         pix1 += line_size;
129         pix2v = pix3v;
130         pix3 += line_size;
131     }
132
133     /* Sum up the four partial sums, and put the result into s. */
134     sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
135     sumdiffs = vec_splat(sumdiffs, 3);
136     vec_ste(sumdiffs, 0, &s);
137     return s;
138 }
139
140 static int sad16_xy2_altivec(void *v, uint8_t *pix1, uint8_t *pix2,
141                              int line_size, int h)
142 {
143     int i;
144     int s;
145     uint8_t *pix3 = pix2 + line_size;
146     const vector unsigned char zero =
147         (const vector unsigned char) vec_splat_u8(0);
148     const vector unsigned short two =
149         (const vector unsigned short) vec_splat_u16(2);
150     vector unsigned char avgv, t5;
151     vector unsigned char perm1 = vec_lvsl(0, pix2);
152     vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1));
153     vector unsigned char pix2l, pix2r;
154     vector unsigned char pix1v, pix2v, pix3v, pix2iv, pix3iv;
155     vector unsigned short pix2lv, pix2hv, pix2ilv, pix2ihv;
156     vector unsigned short pix3lv, pix3hv, pix3ilv, pix3ihv;
157     vector unsigned short avghv, avglv;
158     vector unsigned short t1, t2, t3, t4;
159     vector unsigned int sad;
160     vector signed int sumdiffs;
161
162     sad = (vector unsigned int) vec_splat_u32(0);
163
164     s = 0;
165
166     /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one
167      * iteration becomes pix2 in the next iteration. We can use this
168      * fact to avoid a potentially expensive unaligned read, as well
169      * as some splitting, and vector addition each time around the loop.
170      * Read unaligned pixels into our vectors. The vectors are as follows:
171      * pix2v: pix2[0] - pix2[15]  pix2iv: pix2[1] - pix2[16]
172      * Split the pixel vectors into shorts. */
173     pix2l  = vec_ld(0,  pix2);
174     pix2r  = vec_ld(16, pix2);
175     pix2v  = vec_perm(pix2l, pix2r, perm1);
176     pix2iv = vec_perm(pix2l, pix2r, perm2);
177
178     pix2hv  = (vector unsigned short) vec_mergeh(zero, pix2v);
179     pix2lv  = (vector unsigned short) vec_mergel(zero, pix2v);
180     pix2ihv = (vector unsigned short) vec_mergeh(zero, pix2iv);
181     pix2ilv = (vector unsigned short) vec_mergel(zero, pix2iv);
182     t1      = vec_add(pix2hv, pix2ihv);
183     t2      = vec_add(pix2lv, pix2ilv);
184
185     for (i = 0; i < h; i++) {
186         /* Read unaligned pixels into our vectors. The vectors are as follows:
187          * pix1v: pix1[0] - pix1[15]
188          * pix3v: pix3[0] - pix3[15]      pix3iv: pix3[1] - pix3[16] */
189         pix1v  = vec_ld(0, pix1);
190
191         pix2l  = vec_ld(0, pix3);
192         pix2r  = vec_ld(16, pix3);
193         pix3v  = vec_perm(pix2l, pix2r, perm1);
194         pix3iv = vec_perm(pix2l, pix2r, perm2);
195
196         /* Note that AltiVec does have vec_avg, but this works on vector pairs
197          * and rounds up. We could do avg(avg(a, b), avg(c, d)), but the
198          * rounding would mean that, for example, avg(3, 0, 0, 1) = 2, when
199          * it should be 1. Instead, we have to split the pixel vectors into
200          * vectors of shorts and do the averaging by hand. */
201
202         /* Split the pixel vectors into shorts. */
203         pix3hv  = (vector unsigned short) vec_mergeh(zero, pix3v);
204         pix3lv  = (vector unsigned short) vec_mergel(zero, pix3v);
205         pix3ihv = (vector unsigned short) vec_mergeh(zero, pix3iv);
206         pix3ilv = (vector unsigned short) vec_mergel(zero, pix3iv);
207
208         /* Do the averaging on them. */
209         t3 = vec_add(pix3hv, pix3ihv);
210         t4 = vec_add(pix3lv, pix3ilv);
211
212         avghv = vec_sr(vec_add(vec_add(t1, t3), two), two);
213         avglv = vec_sr(vec_add(vec_add(t2, t4), two), two);
214
215         /* Pack the shorts back into a result. */
216         avgv = vec_pack(avghv, avglv);
217
218         /* Calculate a sum of abs differences vector. */
219         t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv));
220
221         /* Add each 4 pixel group together and put 4 results into sad. */
222         sad = vec_sum4s(t5, sad);
223
224         pix1 += line_size;
225         pix3 += line_size;
226         /* Transfer the calculated values for pix3 into pix2. */
227         t1 = t3;
228         t2 = t4;
229     }
230     /* Sum up the four partial sums, and put the result into s. */
231     sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
232     sumdiffs = vec_splat(sumdiffs, 3);
233     vec_ste(sumdiffs, 0, &s);
234
235     return s;
236 }
237
238 static int sad16_altivec(void *v, uint8_t *pix1, uint8_t *pix2,
239                          int line_size, int h)
240 {
241     int i;
242     int s;
243     const vector unsigned int zero =
244         (const vector unsigned int) vec_splat_u32(0);
245     vector unsigned char perm = vec_lvsl(0, pix2);
246     vector unsigned char t1, t2, t3, t4, t5;
247     vector unsigned int sad;
248     vector signed int sumdiffs;
249
250     sad = (vector unsigned int) vec_splat_u32(0);
251
252     for (i = 0; i < h; i++) {
253         /* Read potentially unaligned pixels into t1 and t2. */
254         vector unsigned char pix2l = vec_ld(0,  pix2);
255         vector unsigned char pix2r = vec_ld(15, pix2);
256         t1 = vec_ld(0, pix1);
257         t2 = vec_perm(pix2l, pix2r, perm);
258
259         /* Calculate a sum of abs differences vector. */
260         t3 = vec_max(t1, t2);
261         t4 = vec_min(t1, t2);
262         t5 = vec_sub(t3, t4);
263
264         /* Add each 4 pixel group together and put 4 results into sad. */
265         sad = vec_sum4s(t5, sad);
266
267         pix1 += line_size;
268         pix2 += line_size;
269     }
270
271     /* Sum up the four partial sums, and put the result into s. */
272     sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
273     sumdiffs = vec_splat(sumdiffs, 3);
274     vec_ste(sumdiffs, 0, &s);
275
276     return s;
277 }
278
279 static int sad8_altivec(void *v, uint8_t *pix1, uint8_t *pix2,
280                         int line_size, int h)
281 {
282     int i;
283     int s;
284     const vector unsigned int zero =
285         (const vector unsigned int) vec_splat_u32(0);
286     const vector unsigned char permclear =
287         (vector unsigned char)
288         { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0 };
289     vector unsigned char perm1 = vec_lvsl(0, pix1);
290     vector unsigned char perm2 = vec_lvsl(0, pix2);
291     vector unsigned char t1, t2, t3, t4, t5;
292     vector unsigned int sad;
293     vector signed int sumdiffs;
294
295     sad = (vector unsigned int) vec_splat_u32(0);
296
297     for (i = 0; i < h; i++) {
298         /* Read potentially unaligned pixels into t1 and t2.
299          * Since we're reading 16 pixels, and actually only want 8,
300          * mask out the last 8 pixels. The 0s don't change the sum. */
301         vector unsigned char pix1l = vec_ld(0, pix1);
302         vector unsigned char pix1r = vec_ld(7, pix1);
303         vector unsigned char pix2l = vec_ld(0, pix2);
304         vector unsigned char pix2r = vec_ld(7, pix2);
305         t1 = vec_and(vec_perm(pix1l, pix1r, perm1), permclear);
306         t2 = vec_and(vec_perm(pix2l, pix2r, perm2), permclear);
307
308         /* Calculate a sum of abs differences vector. */
309         t3 = vec_max(t1, t2);
310         t4 = vec_min(t1, t2);
311         t5 = vec_sub(t3, t4);
312
313         /* Add each 4 pixel group together and put 4 results into sad. */
314         sad = vec_sum4s(t5, sad);
315
316         pix1 += line_size;
317         pix2 += line_size;
318     }
319
320     /* Sum up the four partial sums, and put the result into s. */
321     sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
322     sumdiffs = vec_splat(sumdiffs, 3);
323     vec_ste(sumdiffs, 0, &s);
324
325     return s;
326 }
327
328 static int pix_norm1_altivec(uint8_t *pix, int line_size)
329 {
330     int i;
331     int s;
332     const vector unsigned int zero =
333         (const vector unsigned int) vec_splat_u32(0);
334     vector unsigned char perm = vec_lvsl(0, pix);
335     vector unsigned char pixv;
336     vector unsigned int sv;
337     vector signed int sum;
338
339     sv = (vector unsigned int) vec_splat_u32(0);
340
341     s = 0;
342     for (i = 0; i < 16; i++) {
343         /* Read the potentially unaligned pixels. */
344         vector unsigned char pixl = vec_ld(0,  pix);
345         vector unsigned char pixr = vec_ld(15, pix);
346         pixv = vec_perm(pixl, pixr, perm);
347
348         /* Square the values, and add them to our sum. */
349         sv = vec_msum(pixv, pixv, sv);
350
351         pix += line_size;
352     }
353     /* Sum up the four partial sums, and put the result into s. */
354     sum = vec_sums((vector signed int) sv, (vector signed int) zero);
355     sum = vec_splat(sum, 3);
356     vec_ste(sum, 0, &s);
357
358     return s;
359 }
360
361 /* Sum of Squared Errors for an 8x8 block, AltiVec-enhanced.
362  * It's the sad8_altivec code above w/ squaring added. */
363 static int sse8_altivec(void *v, uint8_t *pix1, uint8_t *pix2,
364                         int line_size, int h)
365 {
366     int i;
367     int s;
368     const vector unsigned int zero =
369         (const vector unsigned int) vec_splat_u32(0);
370     const vector unsigned char permclear =
371         (vector unsigned char)
372         { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0 };
373     vector unsigned char perm1 = vec_lvsl(0, pix1);
374     vector unsigned char perm2 = vec_lvsl(0, pix2);
375     vector unsigned char t1, t2, t3, t4, t5;
376     vector unsigned int sum;
377     vector signed int sumsqr;
378
379     sum = (vector unsigned int) vec_splat_u32(0);
380
381     for (i = 0; i < h; i++) {
382         /* Read potentially unaligned pixels into t1 and t2.
383          * Since we're reading 16 pixels, and actually only want 8,
384          * mask out the last 8 pixels. The 0s don't change the sum. */
385         vector unsigned char pix1l = vec_ld(0, pix1);
386         vector unsigned char pix1r = vec_ld(7, pix1);
387         vector unsigned char pix2l = vec_ld(0, pix2);
388         vector unsigned char pix2r = vec_ld(7, pix2);
389         t1 = vec_and(vec_perm(pix1l, pix1r, perm1), permclear);
390         t2 = vec_and(vec_perm(pix2l, pix2r, perm2), permclear);
391
392         /* Since we want to use unsigned chars, we can take advantage
393          * of the fact that abs(a - b) ^ 2 = (a - b) ^ 2. */
394
395         /* Calculate abs differences vector. */
396         t3 = vec_max(t1, t2);
397         t4 = vec_min(t1, t2);
398         t5 = vec_sub(t3, t4);
399
400         /* Square the values and add them to our sum. */
401         sum = vec_msum(t5, t5, sum);
402
403         pix1 += line_size;
404         pix2 += line_size;
405     }
406
407     /* Sum up the four partial sums, and put the result into s. */
408     sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero);
409     sumsqr = vec_splat(sumsqr, 3);
410     vec_ste(sumsqr, 0, &s);
411
412     return s;
413 }
414
415 /* Sum of Squared Errors for a 16x16 block, AltiVec-enhanced.
416  * It's the sad16_altivec code above w/ squaring added. */
417 static int sse16_altivec(void *v, uint8_t *pix1, uint8_t *pix2,
418                          int line_size, int h)
419 {
420     int i;
421     int s;
422     const vector unsigned int zero =
423         (const vector unsigned int) vec_splat_u32(0);
424     vector unsigned char perm = vec_lvsl(0, pix2);
425     vector unsigned char t1, t2, t3, t4, t5;
426     vector unsigned int sum;
427     vector signed int sumsqr;
428
429     sum = (vector unsigned int) vec_splat_u32(0);
430
431     for (i = 0; i < h; i++) {
432         /* Read potentially unaligned pixels into t1 and t2. */
433         vector unsigned char pix2l = vec_ld(0,  pix2);
434         vector unsigned char pix2r = vec_ld(15, pix2);
435         t1 = vec_ld(0, pix1);
436         t2 = vec_perm(pix2l, pix2r, perm);
437
438         /* Since we want to use unsigned chars, we can take advantage
439          * of the fact that abs(a - b) ^ 2 = (a - b) ^ 2. */
440
441         /* Calculate abs differences vector. */
442         t3 = vec_max(t1, t2);
443         t4 = vec_min(t1, t2);
444         t5 = vec_sub(t3, t4);
445
446         /* Square the values and add them to our sum. */
447         sum = vec_msum(t5, t5, sum);
448
449         pix1 += line_size;
450         pix2 += line_size;
451     }
452
453     /* Sum up the four partial sums, and put the result into s. */
454     sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero);
455     sumsqr = vec_splat(sumsqr, 3);
456     vec_ste(sumsqr, 0, &s);
457
458     return s;
459 }
460
461 static int pix_sum_altivec(uint8_t *pix, int line_size)
462 {
463     const vector unsigned int zero =
464         (const vector unsigned int) vec_splat_u32(0);
465     vector unsigned char perm = vec_lvsl(0, pix);
466     vector unsigned char t1;
467     vector unsigned int sad;
468     vector signed int sumdiffs;
469
470     int i;
471     int s;
472
473     sad = (vector unsigned int) vec_splat_u32(0);
474
475     for (i = 0; i < 16; i++) {
476         /* Read the potentially unaligned 16 pixels into t1. */
477         vector unsigned char pixl = vec_ld(0,  pix);
478         vector unsigned char pixr = vec_ld(15, pix);
479         t1 = vec_perm(pixl, pixr, perm);
480
481         /* Add each 4 pixel group together and put 4 results into sad. */
482         sad = vec_sum4s(t1, sad);
483
484         pix += line_size;
485     }
486
487     /* Sum up the four partial sums, and put the result into s. */
488     sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
489     sumdiffs = vec_splat(sumdiffs, 3);
490     vec_ste(sumdiffs, 0, &s);
491
492     return s;
493 }
494
495 static void get_pixels_altivec(int16_t *restrict block, const uint8_t *pixels,
496                                int line_size)
497 {
498     int i;
499     vector unsigned char perm = vec_lvsl(0, pixels);
500     vector unsigned char bytes;
501     const vector unsigned char zero =
502         (const vector unsigned char) vec_splat_u8(0);
503     vector signed short shorts;
504
505     for (i = 0; i < 8; i++) {
506         /* Read potentially unaligned pixels.
507          * We're reading 16 pixels, and actually only want 8,
508          * but we simply ignore the extras. */
509         vector unsigned char pixl = vec_ld(0, pixels);
510         vector unsigned char pixr = vec_ld(7, pixels);
511         bytes = vec_perm(pixl, pixr, perm);
512
513         // Convert the bytes into shorts.
514         shorts = (vector signed short) vec_mergeh(zero, bytes);
515
516         // Save the data to the block, we assume the block is 16-byte aligned.
517         vec_st(shorts, i * 16, (vector signed short *) block);
518
519         pixels += line_size;
520     }
521 }
522
523 static void diff_pixels_altivec(int16_t *restrict block, const uint8_t *s1,
524                                 const uint8_t *s2, int stride)
525 {
526     int i;
527     vector unsigned char perm1 = vec_lvsl(0, s1);
528     vector unsigned char perm2 = vec_lvsl(0, s2);
529     vector unsigned char bytes, pixl, pixr;
530     const vector unsigned char zero =
531         (const vector unsigned char) vec_splat_u8(0);
532     vector signed short shorts1, shorts2;
533
534     for (i = 0; i < 4; i++) {
535         /* Read potentially unaligned pixels.
536          * We're reading 16 pixels, and actually only want 8,
537          * but we simply ignore the extras. */
538         pixl  = vec_ld(0,  s1);
539         pixr  = vec_ld(15, s1);
540         bytes = vec_perm(pixl, pixr, perm1);
541
542         // Convert the bytes into shorts.
543         shorts1 = (vector signed short) vec_mergeh(zero, bytes);
544
545         // Do the same for the second block of pixels.
546         pixl  = vec_ld(0,  s2);
547         pixr  = vec_ld(15, s2);
548         bytes = vec_perm(pixl, pixr, perm2);
549
550         // Convert the bytes into shorts.
551         shorts2 = (vector signed short) vec_mergeh(zero, bytes);
552
553         // Do the subtraction.
554         shorts1 = vec_sub(shorts1, shorts2);
555
556         // Save the data to the block, we assume the block is 16-byte aligned.
557         vec_st(shorts1, 0, (vector signed short *) block);
558
559         s1    += stride;
560         s2    += stride;
561         block += 8;
562
563         /* The code below is a copy of the code above...
564          * This is a manual unroll. */
565
566         /* Read potentially unaligned pixels.
567          * We're reading 16 pixels, and actually only want 8,
568          * but we simply ignore the extras. */
569         pixl  = vec_ld(0,  s1);
570         pixr  = vec_ld(15, s1);
571         bytes = vec_perm(pixl, pixr, perm1);
572
573         // Convert the bytes into shorts.
574         shorts1 = (vector signed short) vec_mergeh(zero, bytes);
575
576         // Do the same for the second block of pixels.
577         pixl  = vec_ld(0,  s2);
578         pixr  = vec_ld(15, s2);
579         bytes = vec_perm(pixl, pixr, perm2);
580
581         // Convert the bytes into shorts.
582         shorts2 = (vector signed short) vec_mergeh(zero, bytes);
583
584         // Do the subtraction.
585         shorts1 = vec_sub(shorts1, shorts2);
586
587         // Save the data to the block, we assume the block is 16-byte aligned.
588         vec_st(shorts1, 0, (vector signed short *) block);
589
590         s1    += stride;
591         s2    += stride;
592         block += 8;
593     }
594 }
595
596 static void clear_block_altivec(int16_t *block)
597 {
598     LOAD_ZERO;
599     vec_st(zero_s16v,   0, block);
600     vec_st(zero_s16v,  16, block);
601     vec_st(zero_s16v,  32, block);
602     vec_st(zero_s16v,  48, block);
603     vec_st(zero_s16v,  64, block);
604     vec_st(zero_s16v,  80, block);
605     vec_st(zero_s16v,  96, block);
606     vec_st(zero_s16v, 112, block);
607 }
608
609 static void add_bytes_altivec(uint8_t *dst, uint8_t *src, int w)
610 {
611     register int i;
612     register vector unsigned char vdst, vsrc;
613
614     /* dst and src are 16 bytes-aligned (guaranteed). */
615     for (i = 0; i + 15 < w; i += 16) {
616         vdst = vec_ld(i, (unsigned char *) dst);
617         vsrc = vec_ld(i, (unsigned char *) src);
618         vdst = vec_add(vsrc, vdst);
619         vec_st(vdst, i, (unsigned char *) dst);
620     }
621     /* If w is not a multiple of 16. */
622     for (; i < w; i++)
623         dst[i] = src[i];
624 }
625
626 static int hadamard8_diff8x8_altivec(/* MpegEncContext */ void *s, uint8_t *dst,
627                                      uint8_t *src, int stride, int h)
628 {
629     int sum;
630     register const vector unsigned char vzero =
631         (const vector unsigned char) vec_splat_u8(0);
632     register vector signed short temp0, temp1, temp2, temp3, temp4,
633                                  temp5, temp6, temp7;
634     {
635         register const vector signed short vprod1 =
636             (const vector signed short) { 1, -1, 1, -1, 1, -1, 1, -1 };
637         register const vector signed short vprod2 =
638             (const vector signed short) { 1, 1, -1, -1, 1, 1, -1, -1 };
639         register const vector signed short vprod3 =
640             (const vector signed short) { 1, 1, 1, 1, -1, -1, -1, -1 };
641         register const vector unsigned char perm1 =
642             (const vector unsigned char)
643             { 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
644               0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D };
645         register const vector unsigned char perm2 =
646             (const vector unsigned char)
647             { 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03,
648               0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B };
649         register const vector unsigned char perm3 =
650             (const vector unsigned char)
651             { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
652               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
653
654 #define ONEITERBUTTERFLY(i, res)                                            \
655     {                                                                       \
656         register vector unsigned char src1, src2, srcO;                     \
657         register vector unsigned char dst1, dst2, dstO;                     \
658         register vector signed short srcV, dstV;                            \
659         register vector signed short but0, but1, but2, op1, op2, op3;       \
660         src1 = vec_ld(stride * i, src);                                     \
661         src2 = vec_ld(stride * i + 15, src);                                \
662         srcO = vec_perm(src1, src2, vec_lvsl(stride * i, src));             \
663         dst1 = vec_ld(stride * i, dst);                                     \
664         dst2 = vec_ld(stride * i + 15, dst);                                \
665         dstO = vec_perm(dst1, dst2, vec_lvsl(stride * i, dst));             \
666         /* Promote the unsigned chars to signed shorts. */                  \
667         /* We're in the 8x8 function, we only care for the first 8. */      \
668         srcV = (vector signed short) vec_mergeh((vector signed char) vzero, \
669                                                 (vector signed char) srcO); \
670         dstV = (vector signed short) vec_mergeh((vector signed char) vzero, \
671                                                 (vector signed char) dstO); \
672         /* subtractions inside the first butterfly */                       \
673         but0 = vec_sub(srcV, dstV);                                         \
674         op1  = vec_perm(but0, but0, perm1);                                 \
675         but1 = vec_mladd(but0, vprod1, op1);                                \
676         op2  = vec_perm(but1, but1, perm2);                                 \
677         but2 = vec_mladd(but1, vprod2, op2);                                \
678         op3  = vec_perm(but2, but2, perm3);                                 \
679         res  = vec_mladd(but2, vprod3, op3);                                \
680     }
681         ONEITERBUTTERFLY(0, temp0);
682         ONEITERBUTTERFLY(1, temp1);
683         ONEITERBUTTERFLY(2, temp2);
684         ONEITERBUTTERFLY(3, temp3);
685         ONEITERBUTTERFLY(4, temp4);
686         ONEITERBUTTERFLY(5, temp5);
687         ONEITERBUTTERFLY(6, temp6);
688         ONEITERBUTTERFLY(7, temp7);
689     }
690 #undef ONEITERBUTTERFLY
691     {
692         register vector signed int vsum;
693         register vector signed short line0  = vec_add(temp0, temp1);
694         register vector signed short line1  = vec_sub(temp0, temp1);
695         register vector signed short line2  = vec_add(temp2, temp3);
696         register vector signed short line3  = vec_sub(temp2, temp3);
697         register vector signed short line4  = vec_add(temp4, temp5);
698         register vector signed short line5  = vec_sub(temp4, temp5);
699         register vector signed short line6  = vec_add(temp6, temp7);
700         register vector signed short line7  = vec_sub(temp6, temp7);
701
702         register vector signed short line0B = vec_add(line0, line2);
703         register vector signed short line2B = vec_sub(line0, line2);
704         register vector signed short line1B = vec_add(line1, line3);
705         register vector signed short line3B = vec_sub(line1, line3);
706         register vector signed short line4B = vec_add(line4, line6);
707         register vector signed short line6B = vec_sub(line4, line6);
708         register vector signed short line5B = vec_add(line5, line7);
709         register vector signed short line7B = vec_sub(line5, line7);
710
711         register vector signed short line0C = vec_add(line0B, line4B);
712         register vector signed short line4C = vec_sub(line0B, line4B);
713         register vector signed short line1C = vec_add(line1B, line5B);
714         register vector signed short line5C = vec_sub(line1B, line5B);
715         register vector signed short line2C = vec_add(line2B, line6B);
716         register vector signed short line6C = vec_sub(line2B, line6B);
717         register vector signed short line3C = vec_add(line3B, line7B);
718         register vector signed short line7C = vec_sub(line3B, line7B);
719
720         vsum = vec_sum4s(vec_abs(line0C), vec_splat_s32(0));
721         vsum = vec_sum4s(vec_abs(line1C), vsum);
722         vsum = vec_sum4s(vec_abs(line2C), vsum);
723         vsum = vec_sum4s(vec_abs(line3C), vsum);
724         vsum = vec_sum4s(vec_abs(line4C), vsum);
725         vsum = vec_sum4s(vec_abs(line5C), vsum);
726         vsum = vec_sum4s(vec_abs(line6C), vsum);
727         vsum = vec_sum4s(vec_abs(line7C), vsum);
728         vsum = vec_sums(vsum, (vector signed int) vzero);
729         vsum = vec_splat(vsum, 3);
730         vec_ste(vsum, 0, &sum);
731     }
732     return sum;
733 }
734
735 /*
736  * 16x8 works with 16 elements; it allows to avoid replicating loads, and
737  * gives the compiler more room for scheduling. It's only used from
738  * inside hadamard8_diff16_altivec.
739  *
740  * Unfortunately, it seems gcc-3.3 is a bit dumb, and the compiled code has
741  * a LOT of spill code, it seems gcc (unlike xlc) cannot keep everything in
742  * registers by itself. The following code includes hand-made register
743  * allocation. It's not clean, but on a 7450 the resulting code is much faster
744  * (best case falls from 700+ cycles to 550).
745  *
746  * xlc doesn't add spill code, but it doesn't know how to schedule for the
747  * 7450, and its code isn't much faster than gcc-3.3 on the 7450 (but uses
748  * 25% fewer instructions...)
749  *
750  * On the 970, the hand-made RA is still a win (around 690 vs. around 780),
751  * but xlc goes to around 660 on the regular C code...
752  */
753 static int hadamard8_diff16x8_altivec(/* MpegEncContext */ void *s, uint8_t *dst,
754                                       uint8_t *src, int stride, int h)
755 {
756     int sum;
757     register vector signed short
758         temp0 __asm__ ("v0"),
759         temp1 __asm__ ("v1"),
760         temp2 __asm__ ("v2"),
761         temp3 __asm__ ("v3"),
762         temp4 __asm__ ("v4"),
763         temp5 __asm__ ("v5"),
764         temp6 __asm__ ("v6"),
765         temp7 __asm__ ("v7");
766     register vector signed short
767         temp0S __asm__ ("v8"),
768         temp1S __asm__ ("v9"),
769         temp2S __asm__ ("v10"),
770         temp3S __asm__ ("v11"),
771         temp4S __asm__ ("v12"),
772         temp5S __asm__ ("v13"),
773         temp6S __asm__ ("v14"),
774         temp7S __asm__ ("v15");
775     register const vector unsigned char vzero __asm__ ("v31") =
776         (const vector unsigned char) vec_splat_u8(0);
777     {
778         register const vector signed short vprod1 __asm__ ("v16") =
779             (const vector signed short) { 1, -1, 1, -1, 1, -1, 1, -1 };
780
781         register const vector signed short vprod2 __asm__ ("v17") =
782             (const vector signed short) { 1, 1, -1, -1, 1, 1, -1, -1 };
783
784         register const vector signed short vprod3 __asm__ ("v18") =
785             (const vector signed short) { 1, 1, 1, 1, -1, -1, -1, -1 };
786
787         register const vector unsigned char perm1 __asm__ ("v19") =
788             (const vector unsigned char)
789             { 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
790               0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D };
791
792         register const vector unsigned char perm2 __asm__ ("v20") =
793             (const vector unsigned char)
794             { 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03,
795               0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B };
796
797         register const vector unsigned char perm3 __asm__ ("v21") =
798             (const vector unsigned char)
799             { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
800               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
801
802 #define ONEITERBUTTERFLY(i, res1, res2)                                     \
803     {                                                                       \
804         register vector unsigned char                                       \
805             src1 __asm__ ("v22"),                                           \
806             src2 __asm__ ("v23"),                                           \
807             dst1 __asm__ ("v24"),                                           \
808             dst2 __asm__ ("v25"),                                           \
809             srcO __asm__ ("v22"),                                           \
810             dstO __asm__ ("v23");                                           \
811                                                                             \
812         register vector signed short                                        \
813             srcV  __asm__ ("v24"),                                          \
814             dstV  __asm__ ("v25"),                                          \
815             srcW  __asm__ ("v26"),                                          \
816             dstW  __asm__ ("v27"),                                          \
817             but0  __asm__ ("v28"),                                          \
818             but0S __asm__ ("v29"),                                          \
819             op1   __asm__ ("v30"),                                          \
820             but1  __asm__ ("v22"),                                          \
821             op1S  __asm__ ("v23"),                                          \
822             but1S __asm__ ("v24"),                                          \
823             op2   __asm__ ("v25"),                                          \
824             but2  __asm__ ("v26"),                                          \
825             op2S  __asm__ ("v27"),                                          \
826             but2S __asm__ ("v28"),                                          \
827             op3   __asm__ ("v29"),                                          \
828             op3S  __asm__ ("v30");                                          \
829                                                                             \
830         src1 = vec_ld(stride * i, src);                                     \
831         src2 = vec_ld(stride * i + 16, src);                                \
832         srcO = vec_perm(src1, src2, vec_lvsl(stride * i, src));             \
833         dst1 = vec_ld(stride * i, dst);                                     \
834         dst2 = vec_ld(stride * i + 16, dst);                                \
835         dstO = vec_perm(dst1, dst2, vec_lvsl(stride * i, dst));             \
836         /* Promote the unsigned chars to signed shorts. */                  \
837         srcV = (vector signed short) vec_mergeh((vector signed char) vzero, \
838                                                 (vector signed char) srcO); \
839         dstV = (vector signed short) vec_mergeh((vector signed char) vzero, \
840                                                 (vector signed char) dstO); \
841         srcW = (vector signed short) vec_mergel((vector signed char) vzero, \
842                                                 (vector signed char) srcO); \
843         dstW = (vector signed short) vec_mergel((vector signed char) vzero, \
844                                                 (vector signed char) dstO); \
845         /* subtractions inside the first butterfly */                       \
846         but0  = vec_sub(srcV, dstV);                                        \
847         but0S = vec_sub(srcW, dstW);                                        \
848         op1   = vec_perm(but0, but0, perm1);                                \
849         but1  = vec_mladd(but0, vprod1, op1);                               \
850         op1S  = vec_perm(but0S, but0S, perm1);                              \
851         but1S = vec_mladd(but0S, vprod1, op1S);                             \
852         op2   = vec_perm(but1, but1, perm2);                                \
853         but2  = vec_mladd(but1, vprod2, op2);                               \
854         op2S  = vec_perm(but1S, but1S, perm2);                              \
855         but2S = vec_mladd(but1S, vprod2, op2S);                             \
856         op3   = vec_perm(but2, but2, perm3);                                \
857         res1  = vec_mladd(but2, vprod3, op3);                               \
858         op3S  = vec_perm(but2S, but2S, perm3);                              \
859         res2  = vec_mladd(but2S, vprod3, op3S);                             \
860     }
861         ONEITERBUTTERFLY(0, temp0, temp0S);
862         ONEITERBUTTERFLY(1, temp1, temp1S);
863         ONEITERBUTTERFLY(2, temp2, temp2S);
864         ONEITERBUTTERFLY(3, temp3, temp3S);
865         ONEITERBUTTERFLY(4, temp4, temp4S);
866         ONEITERBUTTERFLY(5, temp5, temp5S);
867         ONEITERBUTTERFLY(6, temp6, temp6S);
868         ONEITERBUTTERFLY(7, temp7, temp7S);
869     }
870 #undef ONEITERBUTTERFLY
871     {
872         register vector signed int vsum;
873         register vector signed short line0S, line1S, line2S, line3S, line4S,
874                                      line5S, line6S, line7S, line0BS, line2BS,
875                                      line1BS, line3BS, line4BS, line6BS, line5BS,
876                                      line7BS, line0CS, line4CS, line1CS, line5CS,
877                                      line2CS, line6CS, line3CS, line7CS;
878
879         register vector signed short line0  = vec_add(temp0, temp1);
880         register vector signed short line1  = vec_sub(temp0, temp1);
881         register vector signed short line2  = vec_add(temp2, temp3);
882         register vector signed short line3  = vec_sub(temp2, temp3);
883         register vector signed short line4  = vec_add(temp4, temp5);
884         register vector signed short line5  = vec_sub(temp4, temp5);
885         register vector signed short line6  = vec_add(temp6, temp7);
886         register vector signed short line7  = vec_sub(temp6, temp7);
887
888         register vector signed short line0B = vec_add(line0, line2);
889         register vector signed short line2B = vec_sub(line0, line2);
890         register vector signed short line1B = vec_add(line1, line3);
891         register vector signed short line3B = vec_sub(line1, line3);
892         register vector signed short line4B = vec_add(line4, line6);
893         register vector signed short line6B = vec_sub(line4, line6);
894         register vector signed short line5B = vec_add(line5, line7);
895         register vector signed short line7B = vec_sub(line5, line7);
896
897         register vector signed short line0C = vec_add(line0B, line4B);
898         register vector signed short line4C = vec_sub(line0B, line4B);
899         register vector signed short line1C = vec_add(line1B, line5B);
900         register vector signed short line5C = vec_sub(line1B, line5B);
901         register vector signed short line2C = vec_add(line2B, line6B);
902         register vector signed short line6C = vec_sub(line2B, line6B);
903         register vector signed short line3C = vec_add(line3B, line7B);
904         register vector signed short line7C = vec_sub(line3B, line7B);
905
906         vsum = vec_sum4s(vec_abs(line0C), vec_splat_s32(0));
907         vsum = vec_sum4s(vec_abs(line1C), vsum);
908         vsum = vec_sum4s(vec_abs(line2C), vsum);
909         vsum = vec_sum4s(vec_abs(line3C), vsum);
910         vsum = vec_sum4s(vec_abs(line4C), vsum);
911         vsum = vec_sum4s(vec_abs(line5C), vsum);
912         vsum = vec_sum4s(vec_abs(line6C), vsum);
913         vsum = vec_sum4s(vec_abs(line7C), vsum);
914
915         line0S = vec_add(temp0S, temp1S);
916         line1S = vec_sub(temp0S, temp1S);
917         line2S = vec_add(temp2S, temp3S);
918         line3S = vec_sub(temp2S, temp3S);
919         line4S = vec_add(temp4S, temp5S);
920         line5S = vec_sub(temp4S, temp5S);
921         line6S = vec_add(temp6S, temp7S);
922         line7S = vec_sub(temp6S, temp7S);
923
924         line0BS = vec_add(line0S, line2S);
925         line2BS = vec_sub(line0S, line2S);
926         line1BS = vec_add(line1S, line3S);
927         line3BS = vec_sub(line1S, line3S);
928         line4BS = vec_add(line4S, line6S);
929         line6BS = vec_sub(line4S, line6S);
930         line5BS = vec_add(line5S, line7S);
931         line7BS = vec_sub(line5S, line7S);
932
933         line0CS = vec_add(line0BS, line4BS);
934         line4CS = vec_sub(line0BS, line4BS);
935         line1CS = vec_add(line1BS, line5BS);
936         line5CS = vec_sub(line1BS, line5BS);
937         line2CS = vec_add(line2BS, line6BS);
938         line6CS = vec_sub(line2BS, line6BS);
939         line3CS = vec_add(line3BS, line7BS);
940         line7CS = vec_sub(line3BS, line7BS);
941
942         vsum = vec_sum4s(vec_abs(line0CS), vsum);
943         vsum = vec_sum4s(vec_abs(line1CS), vsum);
944         vsum = vec_sum4s(vec_abs(line2CS), vsum);
945         vsum = vec_sum4s(vec_abs(line3CS), vsum);
946         vsum = vec_sum4s(vec_abs(line4CS), vsum);
947         vsum = vec_sum4s(vec_abs(line5CS), vsum);
948         vsum = vec_sum4s(vec_abs(line6CS), vsum);
949         vsum = vec_sum4s(vec_abs(line7CS), vsum);
950         vsum = vec_sums(vsum, (vector signed int) vzero);
951         vsum = vec_splat(vsum, 3);
952         vec_ste(vsum, 0, &sum);
953     }
954     return sum;
955 }
956
957 static int hadamard8_diff16_altivec(/* MpegEncContext */ void *s, uint8_t *dst,
958                                     uint8_t *src, int stride, int h)
959 {
960     int score;
961     score = hadamard8_diff16x8_altivec(s, dst, src, stride, 8);
962     if (h == 16) {
963         dst   += 8 * stride;
964         src   += 8 * stride;
965         score += hadamard8_diff16x8_altivec(s, dst, src, stride, 8);
966     }
967     return score;
968 }
969
970 av_cold void ff_dsputil_init_altivec(DSPContext *c, AVCodecContext *avctx)
971 {
972     const int high_bit_depth = avctx->bits_per_raw_sample > 8;
973
974     c->pix_abs[0][1] = sad16_x2_altivec;
975     c->pix_abs[0][2] = sad16_y2_altivec;
976     c->pix_abs[0][3] = sad16_xy2_altivec;
977     c->pix_abs[0][0] = sad16_altivec;
978     c->pix_abs[1][0] = sad8_altivec;
979
980     c->sad[0] = sad16_altivec;
981     c->sad[1] = sad8_altivec;
982     c->sse[0] = sse16_altivec;
983     c->sse[1] = sse8_altivec;
984
985     c->pix_norm1 = pix_norm1_altivec;
986     c->pix_sum   = pix_sum_altivec;
987
988     c->diff_pixels = diff_pixels_altivec;
989     c->add_bytes   = add_bytes_altivec;
990
991     if (!high_bit_depth) {
992         c->get_pixels = get_pixels_altivec;
993         c->clear_block = clear_block_altivec;
994     }
995
996     c->hadamard8_diff[0] = hadamard8_diff16_altivec;
997     c->hadamard8_diff[1] = hadamard8_diff8x8_altivec;
998 }