]> git.sesse.net Git - ffmpeg/blob - libavcodec/ppc/h264_template_altivec.c
cosmetics: Fix indentation after last commit.
[ffmpeg] / libavcodec / ppc / h264_template_altivec.c
1 /*
2  * Copyright (c) 2004 Romain Dolbeau <romain@dolbeau.org>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 //#define DEBUG_ALIGNMENT
22 #ifdef DEBUG_ALIGNMENT
23 #define ASSERT_ALIGNED(ptr) assert(((unsigned long)ptr&0x0000000F));
24 #else
25 #define ASSERT_ALIGNED(ptr) ;
26 #endif
27
28 /* this code assume that stride % 16 == 0 */
29 void PREFIX_h264_chroma_mc8_altivec(uint8_t * dst, uint8_t * src, int stride, int h, int x, int y) {
30   POWERPC_PERF_DECLARE(PREFIX_h264_chroma_mc8_num, 1);
31     DECLARE_ALIGNED_16(signed int, ABCD[4]) =
32                         {((8 - x) * (8 - y)),
33                           ((x) * (8 - y)),
34                           ((8 - x) * (y)),
35                           ((x) * (y))};
36     register int i;
37     vec_u8_t fperm;
38     const vec_s32_t vABCD = vec_ld(0, ABCD);
39     const vec_s16_t vA = vec_splat((vec_s16_t)vABCD, 1);
40     const vec_s16_t vB = vec_splat((vec_s16_t)vABCD, 3);
41     const vec_s16_t vC = vec_splat((vec_s16_t)vABCD, 5);
42     const vec_s16_t vD = vec_splat((vec_s16_t)vABCD, 7);
43     LOAD_ZERO;
44     const vec_s16_t v32ss = vec_sl(vec_splat_s16(1),vec_splat_u16(5));
45     const vec_u16_t v6us = vec_splat_u16(6);
46     register int loadSecond = (((unsigned long)src) % 16) <= 7 ? 0 : 1;
47     register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0;
48
49     vec_u8_t vsrcAuc, vsrcBuc, vsrcperm0, vsrcperm1;
50     vec_u8_t vsrc0uc, vsrc1uc;
51     vec_s16_t vsrc0ssH, vsrc1ssH;
52     vec_u8_t vsrcCuc, vsrc2uc, vsrc3uc;
53     vec_s16_t vsrc2ssH, vsrc3ssH, psum;
54     vec_u8_t vdst, ppsum, vfdst, fsum;
55
56   POWERPC_PERF_START_COUNT(PREFIX_h264_chroma_mc8_num, 1);
57
58     if (((unsigned long)dst) % 16 == 0) {
59       fperm = (vec_u8_t)AVV(0x10, 0x11, 0x12, 0x13,
60                             0x14, 0x15, 0x16, 0x17,
61                             0x08, 0x09, 0x0A, 0x0B,
62                             0x0C, 0x0D, 0x0E, 0x0F);
63     } else {
64       fperm = (vec_u8_t)AVV(0x00, 0x01, 0x02, 0x03,
65                             0x04, 0x05, 0x06, 0x07,
66                             0x18, 0x19, 0x1A, 0x1B,
67                             0x1C, 0x1D, 0x1E, 0x1F);
68     }
69
70     vsrcAuc = vec_ld(0, src);
71
72     if (loadSecond)
73       vsrcBuc = vec_ld(16, src);
74     vsrcperm0 = vec_lvsl(0, src);
75     vsrcperm1 = vec_lvsl(1, src);
76
77     vsrc0uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm0);
78     if (reallyBadAlign)
79       vsrc1uc = vsrcBuc;
80     else
81       vsrc1uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm1);
82
83     vsrc0ssH = (vec_s16_t)vec_mergeh(zero_u8v,(vec_u8_t)vsrc0uc);
84     vsrc1ssH = (vec_s16_t)vec_mergeh(zero_u8v,(vec_u8_t)vsrc1uc);
85
86     if (!loadSecond) {// -> !reallyBadAlign
87       for (i = 0 ; i < h ; i++) {
88
89
90         vsrcCuc = vec_ld(stride + 0, src);
91
92         vsrc2uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0);
93         vsrc3uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1);
94
95         vsrc2ssH = (vec_s16_t)vec_mergeh(zero_u8v,(vec_u8_t)vsrc2uc);
96         vsrc3ssH = (vec_s16_t)vec_mergeh(zero_u8v,(vec_u8_t)vsrc3uc);
97
98         psum = vec_mladd(vA, vsrc0ssH, vec_splat_s16(0));
99         psum = vec_mladd(vB, vsrc1ssH, psum);
100         psum = vec_mladd(vC, vsrc2ssH, psum);
101         psum = vec_mladd(vD, vsrc3ssH, psum);
102         psum = vec_add(v32ss, psum);
103         psum = vec_sra(psum, v6us);
104
105         vdst = vec_ld(0, dst);
106         ppsum = (vec_u8_t)vec_packsu(psum, psum);
107         vfdst = vec_perm(vdst, ppsum, fperm);
108
109         OP_U8_ALTIVEC(fsum, vfdst, vdst);
110
111         vec_st(fsum, 0, dst);
112
113         vsrc0ssH = vsrc2ssH;
114         vsrc1ssH = vsrc3ssH;
115
116         dst += stride;
117         src += stride;
118       }
119     } else {
120         vec_u8_t vsrcDuc;
121       for (i = 0 ; i < h ; i++) {
122         vsrcCuc = vec_ld(stride + 0, src);
123         vsrcDuc = vec_ld(stride + 16, src);
124
125         vsrc2uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0);
126         if (reallyBadAlign)
127           vsrc3uc = vsrcDuc;
128         else
129           vsrc3uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1);
130
131         vsrc2ssH = (vec_s16_t)vec_mergeh(zero_u8v,(vec_u8_t)vsrc2uc);
132         vsrc3ssH = (vec_s16_t)vec_mergeh(zero_u8v,(vec_u8_t)vsrc3uc);
133
134         psum = vec_mladd(vA, vsrc0ssH, vec_splat_s16(0));
135         psum = vec_mladd(vB, vsrc1ssH, psum);
136         psum = vec_mladd(vC, vsrc2ssH, psum);
137         psum = vec_mladd(vD, vsrc3ssH, psum);
138         psum = vec_add(v32ss, psum);
139         psum = vec_sr(psum, v6us);
140
141         vdst = vec_ld(0, dst);
142         ppsum = (vec_u8_t)vec_pack(psum, psum);
143         vfdst = vec_perm(vdst, ppsum, fperm);
144
145         OP_U8_ALTIVEC(fsum, vfdst, vdst);
146
147         vec_st(fsum, 0, dst);
148
149         vsrc0ssH = vsrc2ssH;
150         vsrc1ssH = vsrc3ssH;
151
152         dst += stride;
153         src += stride;
154       }
155     }
156     POWERPC_PERF_STOP_COUNT(PREFIX_h264_chroma_mc8_num, 1);
157 }
158
159 /* this code assume stride % 16 == 0 */
160 static void PREFIX_h264_qpel16_h_lowpass_altivec(uint8_t * dst, uint8_t * src, int dstStride, int srcStride) {
161   POWERPC_PERF_DECLARE(PREFIX_h264_qpel16_h_lowpass_num, 1);
162   register int i;
163
164   LOAD_ZERO;
165   const vec_u8_t permM2 = vec_lvsl(-2, src);
166   const vec_u8_t permM1 = vec_lvsl(-1, src);
167   const vec_u8_t permP0 = vec_lvsl(+0, src);
168   const vec_u8_t permP1 = vec_lvsl(+1, src);
169   const vec_u8_t permP2 = vec_lvsl(+2, src);
170   const vec_u8_t permP3 = vec_lvsl(+3, src);
171   const vec_s16_t v5ss = vec_splat_s16(5);
172   const vec_u16_t v5us = vec_splat_u16(5);
173   const vec_s16_t v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2));
174   const vec_s16_t v16ss = vec_sl(vec_splat_s16(1),vec_splat_u16(4));
175
176   vec_u8_t srcM2, srcM1, srcP0, srcP1, srcP2, srcP3;
177
178   register int align = ((((unsigned long)src) - 2) % 16);
179
180   vec_s16_t srcP0A, srcP0B, srcP1A, srcP1B,
181                       srcP2A, srcP2B, srcP3A, srcP3B,
182                       srcM1A, srcM1B, srcM2A, srcM2B,
183                       sum1A, sum1B, sum2A, sum2B, sum3A, sum3B,
184                       pp1A, pp1B, pp2A, pp2B, pp3A, pp3B,
185                       psumA, psumB, sumA, sumB;
186
187   vec_u8_t sum, vdst, fsum;
188
189   POWERPC_PERF_START_COUNT(PREFIX_h264_qpel16_h_lowpass_num, 1);
190
191   for (i = 0 ; i < 16 ; i ++) {
192     vec_u8_t srcR1 = vec_ld(-2, src);
193     vec_u8_t srcR2 = vec_ld(14, src);
194
195     switch (align) {
196     default: {
197       srcM2 = vec_perm(srcR1, srcR2, permM2);
198       srcM1 = vec_perm(srcR1, srcR2, permM1);
199       srcP0 = vec_perm(srcR1, srcR2, permP0);
200       srcP1 = vec_perm(srcR1, srcR2, permP1);
201       srcP2 = vec_perm(srcR1, srcR2, permP2);
202       srcP3 = vec_perm(srcR1, srcR2, permP3);
203     } break;
204     case 11: {
205       srcM2 = vec_perm(srcR1, srcR2, permM2);
206       srcM1 = vec_perm(srcR1, srcR2, permM1);
207       srcP0 = vec_perm(srcR1, srcR2, permP0);
208       srcP1 = vec_perm(srcR1, srcR2, permP1);
209       srcP2 = vec_perm(srcR1, srcR2, permP2);
210       srcP3 = srcR2;
211     } break;
212     case 12: {
213       vec_u8_t srcR3 = vec_ld(30, src);
214       srcM2 = vec_perm(srcR1, srcR2, permM2);
215       srcM1 = vec_perm(srcR1, srcR2, permM1);
216       srcP0 = vec_perm(srcR1, srcR2, permP0);
217       srcP1 = vec_perm(srcR1, srcR2, permP1);
218       srcP2 = srcR2;
219       srcP3 = vec_perm(srcR2, srcR3, permP3);
220     } break;
221     case 13: {
222       vec_u8_t srcR3 = vec_ld(30, src);
223       srcM2 = vec_perm(srcR1, srcR2, permM2);
224       srcM1 = vec_perm(srcR1, srcR2, permM1);
225       srcP0 = vec_perm(srcR1, srcR2, permP0);
226       srcP1 = srcR2;
227       srcP2 = vec_perm(srcR2, srcR3, permP2);
228       srcP3 = vec_perm(srcR2, srcR3, permP3);
229     } break;
230     case 14: {
231       vec_u8_t srcR3 = vec_ld(30, src);
232       srcM2 = vec_perm(srcR1, srcR2, permM2);
233       srcM1 = vec_perm(srcR1, srcR2, permM1);
234       srcP0 = srcR2;
235       srcP1 = vec_perm(srcR2, srcR3, permP1);
236       srcP2 = vec_perm(srcR2, srcR3, permP2);
237       srcP3 = vec_perm(srcR2, srcR3, permP3);
238     } break;
239     case 15: {
240       vec_u8_t srcR3 = vec_ld(30, src);
241       srcM2 = vec_perm(srcR1, srcR2, permM2);
242       srcM1 = srcR2;
243       srcP0 = vec_perm(srcR2, srcR3, permP0);
244       srcP1 = vec_perm(srcR2, srcR3, permP1);
245       srcP2 = vec_perm(srcR2, srcR3, permP2);
246       srcP3 = vec_perm(srcR2, srcR3, permP3);
247     } break;
248     }
249
250     srcP0A = (vec_s16_t) vec_mergeh(zero_u8v, srcP0);
251     srcP0B = (vec_s16_t) vec_mergel(zero_u8v, srcP0);
252     srcP1A = (vec_s16_t) vec_mergeh(zero_u8v, srcP1);
253     srcP1B = (vec_s16_t) vec_mergel(zero_u8v, srcP1);
254
255     srcP2A = (vec_s16_t) vec_mergeh(zero_u8v, srcP2);
256     srcP2B = (vec_s16_t) vec_mergel(zero_u8v, srcP2);
257     srcP3A = (vec_s16_t) vec_mergeh(zero_u8v, srcP3);
258     srcP3B = (vec_s16_t) vec_mergel(zero_u8v, srcP3);
259
260     srcM1A = (vec_s16_t) vec_mergeh(zero_u8v, srcM1);
261     srcM1B = (vec_s16_t) vec_mergel(zero_u8v, srcM1);
262     srcM2A = (vec_s16_t) vec_mergeh(zero_u8v, srcM2);
263     srcM2B = (vec_s16_t) vec_mergel(zero_u8v, srcM2);
264
265     sum1A = vec_adds(srcP0A, srcP1A);
266     sum1B = vec_adds(srcP0B, srcP1B);
267     sum2A = vec_adds(srcM1A, srcP2A);
268     sum2B = vec_adds(srcM1B, srcP2B);
269     sum3A = vec_adds(srcM2A, srcP3A);
270     sum3B = vec_adds(srcM2B, srcP3B);
271
272     pp1A = vec_mladd(sum1A, v20ss, v16ss);
273     pp1B = vec_mladd(sum1B, v20ss, v16ss);
274
275     pp2A = vec_mladd(sum2A, v5ss, zero_s16v);
276     pp2B = vec_mladd(sum2B, v5ss, zero_s16v);
277
278     pp3A = vec_add(sum3A, pp1A);
279     pp3B = vec_add(sum3B, pp1B);
280
281     psumA = vec_sub(pp3A, pp2A);
282     psumB = vec_sub(pp3B, pp2B);
283
284     sumA = vec_sra(psumA, v5us);
285     sumB = vec_sra(psumB, v5us);
286
287     sum = vec_packsu(sumA, sumB);
288
289     ASSERT_ALIGNED(dst);
290     vdst = vec_ld(0, dst);
291
292     OP_U8_ALTIVEC(fsum, sum, vdst);
293
294     vec_st(fsum, 0, dst);
295
296     src += srcStride;
297     dst += dstStride;
298   }
299 POWERPC_PERF_STOP_COUNT(PREFIX_h264_qpel16_h_lowpass_num, 1);
300 }
301
302 /* this code assume stride % 16 == 0 */
303 static void PREFIX_h264_qpel16_v_lowpass_altivec(uint8_t * dst, uint8_t * src, int dstStride, int srcStride) {
304   POWERPC_PERF_DECLARE(PREFIX_h264_qpel16_v_lowpass_num, 1);
305
306   register int i;
307
308   LOAD_ZERO;
309   const vec_u8_t perm = vec_lvsl(0, src);
310   const vec_s16_t v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2));
311   const vec_u16_t v5us = vec_splat_u16(5);
312   const vec_s16_t v5ss = vec_splat_s16(5);
313   const vec_s16_t v16ss = vec_sl(vec_splat_s16(1),vec_splat_u16(4));
314
315   uint8_t *srcbis = src - (srcStride * 2);
316
317   const vec_u8_t srcM2a = vec_ld(0, srcbis);
318   const vec_u8_t srcM2b = vec_ld(16, srcbis);
319   const vec_u8_t srcM2 = vec_perm(srcM2a, srcM2b, perm);
320 //  srcbis += srcStride;
321   const vec_u8_t srcM1a = vec_ld(0, srcbis += srcStride);
322   const vec_u8_t srcM1b = vec_ld(16, srcbis);
323   const vec_u8_t srcM1 = vec_perm(srcM1a, srcM1b, perm);
324 //  srcbis += srcStride;
325   const vec_u8_t srcP0a = vec_ld(0, srcbis += srcStride);
326   const vec_u8_t srcP0b = vec_ld(16, srcbis);
327   const vec_u8_t srcP0 = vec_perm(srcP0a, srcP0b, perm);
328 //  srcbis += srcStride;
329   const vec_u8_t srcP1a = vec_ld(0, srcbis += srcStride);
330   const vec_u8_t srcP1b = vec_ld(16, srcbis);
331   const vec_u8_t srcP1 = vec_perm(srcP1a, srcP1b, perm);
332 //  srcbis += srcStride;
333   const vec_u8_t srcP2a = vec_ld(0, srcbis += srcStride);
334   const vec_u8_t srcP2b = vec_ld(16, srcbis);
335   const vec_u8_t srcP2 = vec_perm(srcP2a, srcP2b, perm);
336 //  srcbis += srcStride;
337
338   vec_s16_t srcM2ssA = (vec_s16_t) vec_mergeh(zero_u8v, srcM2);
339   vec_s16_t srcM2ssB = (vec_s16_t) vec_mergel(zero_u8v, srcM2);
340   vec_s16_t srcM1ssA = (vec_s16_t) vec_mergeh(zero_u8v, srcM1);
341   vec_s16_t srcM1ssB = (vec_s16_t) vec_mergel(zero_u8v, srcM1);
342   vec_s16_t srcP0ssA = (vec_s16_t) vec_mergeh(zero_u8v, srcP0);
343   vec_s16_t srcP0ssB = (vec_s16_t) vec_mergel(zero_u8v, srcP0);
344   vec_s16_t srcP1ssA = (vec_s16_t) vec_mergeh(zero_u8v, srcP1);
345   vec_s16_t srcP1ssB = (vec_s16_t) vec_mergel(zero_u8v, srcP1);
346   vec_s16_t srcP2ssA = (vec_s16_t) vec_mergeh(zero_u8v, srcP2);
347   vec_s16_t srcP2ssB = (vec_s16_t) vec_mergel(zero_u8v, srcP2);
348
349   vec_s16_t pp1A, pp1B, pp2A, pp2B, pp3A, pp3B,
350                       psumA, psumB, sumA, sumB,
351                       srcP3ssA, srcP3ssB,
352                       sum1A, sum1B, sum2A, sum2B, sum3A, sum3B;
353
354   vec_u8_t sum, vdst, fsum, srcP3a, srcP3b, srcP3;
355
356   POWERPC_PERF_START_COUNT(PREFIX_h264_qpel16_v_lowpass_num, 1);
357
358   for (i = 0 ; i < 16 ; i++) {
359     srcP3a = vec_ld(0, srcbis += srcStride);
360     srcP3b = vec_ld(16, srcbis);
361     srcP3 = vec_perm(srcP3a, srcP3b, perm);
362     srcP3ssA = (vec_s16_t) vec_mergeh(zero_u8v, srcP3);
363     srcP3ssB = (vec_s16_t) vec_mergel(zero_u8v, srcP3);
364 //    srcbis += srcStride;
365
366     sum1A = vec_adds(srcP0ssA, srcP1ssA);
367     sum1B = vec_adds(srcP0ssB, srcP1ssB);
368     sum2A = vec_adds(srcM1ssA, srcP2ssA);
369     sum2B = vec_adds(srcM1ssB, srcP2ssB);
370     sum3A = vec_adds(srcM2ssA, srcP3ssA);
371     sum3B = vec_adds(srcM2ssB, srcP3ssB);
372
373     srcM2ssA = srcM1ssA;
374     srcM2ssB = srcM1ssB;
375     srcM1ssA = srcP0ssA;
376     srcM1ssB = srcP0ssB;
377     srcP0ssA = srcP1ssA;
378     srcP0ssB = srcP1ssB;
379     srcP1ssA = srcP2ssA;
380     srcP1ssB = srcP2ssB;
381     srcP2ssA = srcP3ssA;
382     srcP2ssB = srcP3ssB;
383
384     pp1A = vec_mladd(sum1A, v20ss, v16ss);
385     pp1B = vec_mladd(sum1B, v20ss, v16ss);
386
387     pp2A = vec_mladd(sum2A, v5ss, zero_s16v);
388     pp2B = vec_mladd(sum2B, v5ss, zero_s16v);
389
390     pp3A = vec_add(sum3A, pp1A);
391     pp3B = vec_add(sum3B, pp1B);
392
393     psumA = vec_sub(pp3A, pp2A);
394     psumB = vec_sub(pp3B, pp2B);
395
396     sumA = vec_sra(psumA, v5us);
397     sumB = vec_sra(psumB, v5us);
398
399     sum = vec_packsu(sumA, sumB);
400
401     ASSERT_ALIGNED(dst);
402     vdst = vec_ld(0, dst);
403
404     OP_U8_ALTIVEC(fsum, sum, vdst);
405
406     vec_st(fsum, 0, dst);
407
408     dst += dstStride;
409   }
410   POWERPC_PERF_STOP_COUNT(PREFIX_h264_qpel16_v_lowpass_num, 1);
411 }
412
413 /* this code assume stride % 16 == 0 *and* tmp is properly aligned */
414 static void PREFIX_h264_qpel16_hv_lowpass_altivec(uint8_t * dst, int16_t * tmp, uint8_t * src, int dstStride, int tmpStride, int srcStride) {
415   POWERPC_PERF_DECLARE(PREFIX_h264_qpel16_hv_lowpass_num, 1);
416   register int i;
417   LOAD_ZERO;
418   const vec_u8_t permM2 = vec_lvsl(-2, src);
419   const vec_u8_t permM1 = vec_lvsl(-1, src);
420   const vec_u8_t permP0 = vec_lvsl(+0, src);
421   const vec_u8_t permP1 = vec_lvsl(+1, src);
422   const vec_u8_t permP2 = vec_lvsl(+2, src);
423   const vec_u8_t permP3 = vec_lvsl(+3, src);
424   const vec_s16_t v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2));
425   const vec_u32_t v10ui = vec_splat_u32(10);
426   const vec_s16_t v5ss = vec_splat_s16(5);
427   const vec_s16_t v1ss = vec_splat_s16(1);
428   const vec_s32_t v512si = vec_sl(vec_splat_s32(1),vec_splat_u32(9));
429   const vec_u32_t v16ui = vec_sl(vec_splat_u32(1),vec_splat_u32(4));
430
431   register int align = ((((unsigned long)src) - 2) % 16);
432
433   vec_s16_t srcP0A, srcP0B, srcP1A, srcP1B,
434                       srcP2A, srcP2B, srcP3A, srcP3B,
435                       srcM1A, srcM1B, srcM2A, srcM2B,
436                       sum1A, sum1B, sum2A, sum2B, sum3A, sum3B,
437                       pp1A, pp1B, pp2A, pp2B, psumA, psumB;
438
439   const vec_u8_t mperm = (const vec_u8_t)
440     AVV(0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B,
441         0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F);
442   int16_t *tmpbis = tmp;
443
444   vec_s16_t tmpM1ssA, tmpM1ssB, tmpM2ssA, tmpM2ssB,
445                       tmpP0ssA, tmpP0ssB, tmpP1ssA, tmpP1ssB,
446                       tmpP2ssA, tmpP2ssB;
447
448   vec_s32_t pp1Ae, pp1Ao, pp1Be, pp1Bo, pp2Ae, pp2Ao, pp2Be, pp2Bo,
449                     pp3Ae, pp3Ao, pp3Be, pp3Bo, pp1cAe, pp1cAo, pp1cBe, pp1cBo,
450                     pp32Ae, pp32Ao, pp32Be, pp32Bo, sumAe, sumAo, sumBe, sumBo,
451                     ssumAe, ssumAo, ssumBe, ssumBo;
452   vec_u8_t fsum, sumv, sum, vdst;
453   vec_s16_t ssume, ssumo;
454
455   POWERPC_PERF_START_COUNT(PREFIX_h264_qpel16_hv_lowpass_num, 1);
456   src -= (2 * srcStride);
457   for (i = 0 ; i < 21 ; i ++) {
458     vec_u8_t srcM2, srcM1, srcP0, srcP1, srcP2, srcP3;
459     vec_u8_t srcR1 = vec_ld(-2, src);
460     vec_u8_t srcR2 = vec_ld(14, src);
461
462     switch (align) {
463     default: {
464       srcM2 = vec_perm(srcR1, srcR2, permM2);
465       srcM1 = vec_perm(srcR1, srcR2, permM1);
466       srcP0 = vec_perm(srcR1, srcR2, permP0);
467       srcP1 = vec_perm(srcR1, srcR2, permP1);
468       srcP2 = vec_perm(srcR1, srcR2, permP2);
469       srcP3 = vec_perm(srcR1, srcR2, permP3);
470     } break;
471     case 11: {
472       srcM2 = vec_perm(srcR1, srcR2, permM2);
473       srcM1 = vec_perm(srcR1, srcR2, permM1);
474       srcP0 = vec_perm(srcR1, srcR2, permP0);
475       srcP1 = vec_perm(srcR1, srcR2, permP1);
476       srcP2 = vec_perm(srcR1, srcR2, permP2);
477       srcP3 = srcR2;
478     } break;
479     case 12: {
480       vec_u8_t srcR3 = vec_ld(30, src);
481       srcM2 = vec_perm(srcR1, srcR2, permM2);
482       srcM1 = vec_perm(srcR1, srcR2, permM1);
483       srcP0 = vec_perm(srcR1, srcR2, permP0);
484       srcP1 = vec_perm(srcR1, srcR2, permP1);
485       srcP2 = srcR2;
486       srcP3 = vec_perm(srcR2, srcR3, permP3);
487     } break;
488     case 13: {
489       vec_u8_t srcR3 = vec_ld(30, src);
490       srcM2 = vec_perm(srcR1, srcR2, permM2);
491       srcM1 = vec_perm(srcR1, srcR2, permM1);
492       srcP0 = vec_perm(srcR1, srcR2, permP0);
493       srcP1 = srcR2;
494       srcP2 = vec_perm(srcR2, srcR3, permP2);
495       srcP3 = vec_perm(srcR2, srcR3, permP3);
496     } break;
497     case 14: {
498       vec_u8_t srcR3 = vec_ld(30, src);
499       srcM2 = vec_perm(srcR1, srcR2, permM2);
500       srcM1 = vec_perm(srcR1, srcR2, permM1);
501       srcP0 = srcR2;
502       srcP1 = vec_perm(srcR2, srcR3, permP1);
503       srcP2 = vec_perm(srcR2, srcR3, permP2);
504       srcP3 = vec_perm(srcR2, srcR3, permP3);
505     } break;
506     case 15: {
507       vec_u8_t srcR3 = vec_ld(30, src);
508       srcM2 = vec_perm(srcR1, srcR2, permM2);
509       srcM1 = srcR2;
510       srcP0 = vec_perm(srcR2, srcR3, permP0);
511       srcP1 = vec_perm(srcR2, srcR3, permP1);
512       srcP2 = vec_perm(srcR2, srcR3, permP2);
513       srcP3 = vec_perm(srcR2, srcR3, permP3);
514     } break;
515     }
516
517     srcP0A = (vec_s16_t) vec_mergeh(zero_u8v, srcP0);
518     srcP0B = (vec_s16_t) vec_mergel(zero_u8v, srcP0);
519     srcP1A = (vec_s16_t) vec_mergeh(zero_u8v, srcP1);
520     srcP1B = (vec_s16_t) vec_mergel(zero_u8v, srcP1);
521
522     srcP2A = (vec_s16_t) vec_mergeh(zero_u8v, srcP2);
523     srcP2B = (vec_s16_t) vec_mergel(zero_u8v, srcP2);
524     srcP3A = (vec_s16_t) vec_mergeh(zero_u8v, srcP3);
525     srcP3B = (vec_s16_t) vec_mergel(zero_u8v, srcP3);
526
527     srcM1A = (vec_s16_t) vec_mergeh(zero_u8v, srcM1);
528     srcM1B = (vec_s16_t) vec_mergel(zero_u8v, srcM1);
529     srcM2A = (vec_s16_t) vec_mergeh(zero_u8v, srcM2);
530     srcM2B = (vec_s16_t) vec_mergel(zero_u8v, srcM2);
531
532     sum1A = vec_adds(srcP0A, srcP1A);
533     sum1B = vec_adds(srcP0B, srcP1B);
534     sum2A = vec_adds(srcM1A, srcP2A);
535     sum2B = vec_adds(srcM1B, srcP2B);
536     sum3A = vec_adds(srcM2A, srcP3A);
537     sum3B = vec_adds(srcM2B, srcP3B);
538
539     pp1A = vec_mladd(sum1A, v20ss, sum3A);
540     pp1B = vec_mladd(sum1B, v20ss, sum3B);
541
542     pp2A = vec_mladd(sum2A, v5ss, zero_s16v);
543     pp2B = vec_mladd(sum2B, v5ss, zero_s16v);
544
545     psumA = vec_sub(pp1A, pp2A);
546     psumB = vec_sub(pp1B, pp2B);
547
548     vec_st(psumA, 0, tmp);
549     vec_st(psumB, 16, tmp);
550
551     src += srcStride;
552     tmp += tmpStride; /* int16_t*, and stride is 16, so it's OK here */
553   }
554
555   tmpM2ssA = vec_ld(0, tmpbis);
556   tmpM2ssB = vec_ld(16, tmpbis);
557   tmpbis += tmpStride;
558   tmpM1ssA = vec_ld(0, tmpbis);
559   tmpM1ssB = vec_ld(16, tmpbis);
560   tmpbis += tmpStride;
561   tmpP0ssA = vec_ld(0, tmpbis);
562   tmpP0ssB = vec_ld(16, tmpbis);
563   tmpbis += tmpStride;
564   tmpP1ssA = vec_ld(0, tmpbis);
565   tmpP1ssB = vec_ld(16, tmpbis);
566   tmpbis += tmpStride;
567   tmpP2ssA = vec_ld(0, tmpbis);
568   tmpP2ssB = vec_ld(16, tmpbis);
569   tmpbis += tmpStride;
570
571   for (i = 0 ; i < 16 ; i++) {
572     const vec_s16_t tmpP3ssA = vec_ld(0, tmpbis);
573     const vec_s16_t tmpP3ssB = vec_ld(16, tmpbis);
574
575     const vec_s16_t sum1A = vec_adds(tmpP0ssA, tmpP1ssA);
576     const vec_s16_t sum1B = vec_adds(tmpP0ssB, tmpP1ssB);
577     const vec_s16_t sum2A = vec_adds(tmpM1ssA, tmpP2ssA);
578     const vec_s16_t sum2B = vec_adds(tmpM1ssB, tmpP2ssB);
579     const vec_s16_t sum3A = vec_adds(tmpM2ssA, tmpP3ssA);
580     const vec_s16_t sum3B = vec_adds(tmpM2ssB, tmpP3ssB);
581
582     tmpbis += tmpStride;
583
584     tmpM2ssA = tmpM1ssA;
585     tmpM2ssB = tmpM1ssB;
586     tmpM1ssA = tmpP0ssA;
587     tmpM1ssB = tmpP0ssB;
588     tmpP0ssA = tmpP1ssA;
589     tmpP0ssB = tmpP1ssB;
590     tmpP1ssA = tmpP2ssA;
591     tmpP1ssB = tmpP2ssB;
592     tmpP2ssA = tmpP3ssA;
593     tmpP2ssB = tmpP3ssB;
594
595     pp1Ae = vec_mule(sum1A, v20ss);
596     pp1Ao = vec_mulo(sum1A, v20ss);
597     pp1Be = vec_mule(sum1B, v20ss);
598     pp1Bo = vec_mulo(sum1B, v20ss);
599
600     pp2Ae = vec_mule(sum2A, v5ss);
601     pp2Ao = vec_mulo(sum2A, v5ss);
602     pp2Be = vec_mule(sum2B, v5ss);
603     pp2Bo = vec_mulo(sum2B, v5ss);
604
605     pp3Ae = vec_sra((vec_s32_t)sum3A, v16ui);
606     pp3Ao = vec_mulo(sum3A, v1ss);
607     pp3Be = vec_sra((vec_s32_t)sum3B, v16ui);
608     pp3Bo = vec_mulo(sum3B, v1ss);
609
610     pp1cAe = vec_add(pp1Ae, v512si);
611     pp1cAo = vec_add(pp1Ao, v512si);
612     pp1cBe = vec_add(pp1Be, v512si);
613     pp1cBo = vec_add(pp1Bo, v512si);
614
615     pp32Ae = vec_sub(pp3Ae, pp2Ae);
616     pp32Ao = vec_sub(pp3Ao, pp2Ao);
617     pp32Be = vec_sub(pp3Be, pp2Be);
618     pp32Bo = vec_sub(pp3Bo, pp2Bo);
619
620     sumAe = vec_add(pp1cAe, pp32Ae);
621     sumAo = vec_add(pp1cAo, pp32Ao);
622     sumBe = vec_add(pp1cBe, pp32Be);
623     sumBo = vec_add(pp1cBo, pp32Bo);
624
625     ssumAe = vec_sra(sumAe, v10ui);
626     ssumAo = vec_sra(sumAo, v10ui);
627     ssumBe = vec_sra(sumBe, v10ui);
628     ssumBo = vec_sra(sumBo, v10ui);
629
630     ssume = vec_packs(ssumAe, ssumBe);
631     ssumo = vec_packs(ssumAo, ssumBo);
632
633     sumv = vec_packsu(ssume, ssumo);
634     sum = vec_perm(sumv, sumv, mperm);
635
636     ASSERT_ALIGNED(dst);
637     vdst = vec_ld(0, dst);
638
639     OP_U8_ALTIVEC(fsum, sum, vdst);
640
641     vec_st(fsum, 0, dst);
642
643     dst += dstStride;
644   }
645   POWERPC_PERF_STOP_COUNT(PREFIX_h264_qpel16_hv_lowpass_num, 1);
646 }