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