PPC fixes & clean-up patch by (Romain Dolbeau <dolbeau at irisa dot fr>)
[libav.git] / libavcodec / ppc / dsputil_altivec.c
1 /*
2 * Copyright (c) 2002 Brian Foley
3 * Copyright (c) 2002 Dieter Shirley
4 * Copyright (c) 2003 Romain Dolbeau <romain@dolbeau.org>
5 *
6 * This library 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 of the License, or (at your option) any later version.
10 *
11 * This library 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 this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "../dsputil.h"
22
23 #include "gcc_fixes.h"
24
25 #include "dsputil_altivec.h"
26
27 #ifdef CONFIG_DARWIN
28 #include <sys/sysctl.h>
29 #else /* CONFIG_DARWIN */
30 #include <signal.h>
31 #include <setjmp.h>
32
33 static sigjmp_buf jmpbuf;
34 static volatile sig_atomic_t canjump = 0;
35
36 static void sigill_handler (int sig)
37 {
38 if (!canjump) {
39 signal (sig, SIG_DFL);
40 raise (sig);
41 }
42
43 canjump = 0;
44 siglongjmp (jmpbuf, 1);
45 }
46 #endif /* CONFIG_DARWIN */
47
48 int pix_abs16x16_x2_altivec(uint8_t *pix1, uint8_t *pix2, int line_size)
49 {
50 int i;
51 int s __attribute__((aligned(16)));
52 const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0);
53 vector unsigned char *tv;
54 vector unsigned char pix1v, pix2v, pix2iv, avgv, t5;
55 vector unsigned int sad;
56 vector signed int sumdiffs;
57
58 s = 0;
59 sad = (vector unsigned int)vec_splat_u32(0);
60 for(i=0;i<16;i++) {
61 /*
62 Read unaligned pixels into our vectors. The vectors are as follows:
63 pix1v: pix1[0]-pix1[15]
64 pix2v: pix2[0]-pix2[15] pix2iv: pix2[1]-pix2[16]
65 */
66 tv = (vector unsigned char *) pix1;
67 pix1v = vec_perm(tv[0], tv[1], vec_lvsl(0, pix1));
68
69 tv = (vector unsigned char *) &pix2[0];
70 pix2v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[0]));
71
72 tv = (vector unsigned char *) &pix2[1];
73 pix2iv = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[1]));
74
75 /* Calculate the average vector */
76 avgv = vec_avg(pix2v, pix2iv);
77
78 /* Calculate a sum of abs differences vector */
79 t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv));
80
81 /* Add each 4 pixel group together and put 4 results into sad */
82 sad = vec_sum4s(t5, sad);
83
84 pix1 += line_size;
85 pix2 += line_size;
86 }
87 /* Sum up the four partial sums, and put the result into s */
88 sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
89 sumdiffs = vec_splat(sumdiffs, 3);
90 vec_ste(sumdiffs, 0, &s);
91
92 return s;
93 }
94
95 int pix_abs16x16_y2_altivec(uint8_t *pix1, uint8_t *pix2, int line_size)
96 {
97 int i;
98 int s __attribute__((aligned(16)));
99 const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0);
100 vector unsigned char *tv;
101 vector unsigned char pix1v, pix2v, pix3v, avgv, t5;
102 vector unsigned int sad;
103 vector signed int sumdiffs;
104 uint8_t *pix3 = pix2 + line_size;
105
106 s = 0;
107 sad = (vector unsigned int)vec_splat_u32(0);
108
109 /*
110 Due to the fact that pix3 = pix2 + line_size, the pix3 of one
111 iteration becomes pix2 in the next iteration. We can use this
112 fact to avoid a potentially expensive unaligned read, each
113 time around the loop.
114 Read unaligned pixels into our vectors. The vectors are as follows:
115 pix2v: pix2[0]-pix2[15]
116 Split the pixel vectors into shorts
117 */
118 tv = (vector unsigned char *) &pix2[0];
119 pix2v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[0]));
120
121 for(i=0;i<16;i++) {
122 /*
123 Read unaligned pixels into our vectors. The vectors are as follows:
124 pix1v: pix1[0]-pix1[15]
125 pix3v: pix3[0]-pix3[15]
126 */
127 tv = (vector unsigned char *) pix1;
128 pix1v = vec_perm(tv[0], tv[1], vec_lvsl(0, pix1));
129
130 tv = (vector unsigned char *) &pix3[0];
131 pix3v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix3[0]));
132
133 /* Calculate the average vector */
134 avgv = vec_avg(pix2v, pix3v);
135
136 /* Calculate a sum of abs differences vector */
137 t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv));
138
139 /* Add each 4 pixel group together and put 4 results into sad */
140 sad = vec_sum4s(t5, sad);
141
142 pix1 += line_size;
143 pix2v = pix3v;
144 pix3 += line_size;
145
146 }
147
148 /* Sum up the four partial sums, and put the result into s */
149 sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
150 sumdiffs = vec_splat(sumdiffs, 3);
151 vec_ste(sumdiffs, 0, &s);
152 return s;
153 }
154
155 int pix_abs16x16_xy2_altivec(uint8_t *pix1, uint8_t *pix2, int line_size)
156 {
157 int i;
158 int s __attribute__((aligned(16)));
159 uint8_t *pix3 = pix2 + line_size;
160 const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0);
161 const vector unsigned short two = (const vector unsigned short)vec_splat_u16(2);
162 vector unsigned char *tv, avgv, t5;
163 vector unsigned char pix1v, pix2v, pix3v, pix2iv, pix3iv;
164 vector unsigned short pix2lv, pix2hv, pix2ilv, pix2ihv;
165 vector unsigned short pix3lv, pix3hv, pix3ilv, pix3ihv;
166 vector unsigned short avghv, avglv;
167 vector unsigned short t1, t2, t3, t4;
168 vector unsigned int sad;
169 vector signed int sumdiffs;
170
171 sad = (vector unsigned int)vec_splat_u32(0);
172
173 s = 0;
174
175 /*
176 Due to the fact that pix3 = pix2 + line_size, the pix3 of one
177 iteration becomes pix2 in the next iteration. We can use this
178 fact to avoid a potentially expensive unaligned read, as well
179 as some splitting, and vector addition each time around the loop.
180 Read unaligned pixels into our vectors. The vectors are as follows:
181 pix2v: pix2[0]-pix2[15] pix2iv: pix2[1]-pix2[16]
182 Split the pixel vectors into shorts
183 */
184 tv = (vector unsigned char *) &pix2[0];
185 pix2v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[0]));
186
187 tv = (vector unsigned char *) &pix2[1];
188 pix2iv = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[1]));
189
190 pix2hv = (vector unsigned short) vec_mergeh(zero, pix2v);
191 pix2lv = (vector unsigned short) vec_mergel(zero, pix2v);
192 pix2ihv = (vector unsigned short) vec_mergeh(zero, pix2iv);
193 pix2ilv = (vector unsigned short) vec_mergel(zero, pix2iv);
194 t1 = vec_add(pix2hv, pix2ihv);
195 t2 = vec_add(pix2lv, pix2ilv);
196
197 for(i=0;i<16;i++) {
198 /*
199 Read unaligned pixels into our vectors. The vectors are as follows:
200 pix1v: pix1[0]-pix1[15]
201 pix3v: pix3[0]-pix3[15] pix3iv: pix3[1]-pix3[16]
202 */
203 tv = (vector unsigned char *) pix1;
204 pix1v = vec_perm(tv[0], tv[1], vec_lvsl(0, pix1));
205
206 tv = (vector unsigned char *) &pix3[0];
207 pix3v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix3[0]));
208
209 tv = (vector unsigned char *) &pix3[1];
210 pix3iv = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix3[1]));
211
212 /*
213 Note that Altivec does have vec_avg, but this works on vector pairs
214 and rounds up. We could do avg(avg(a,b),avg(c,d)), but the rounding
215 would mean that, for example, avg(3,0,0,1) = 2, when it should be 1.
216 Instead, we have to split the pixel vectors into vectors of shorts,
217 and do the averaging by hand.
218 */
219
220 /* Split the pixel vectors into shorts */
221 pix3hv = (vector unsigned short) vec_mergeh(zero, pix3v);
222 pix3lv = (vector unsigned short) vec_mergel(zero, pix3v);
223 pix3ihv = (vector unsigned short) vec_mergeh(zero, pix3iv);
224 pix3ilv = (vector unsigned short) vec_mergel(zero, pix3iv);
225
226 /* Do the averaging on them */
227 t3 = vec_add(pix3hv, pix3ihv);
228 t4 = vec_add(pix3lv, pix3ilv);
229
230 avghv = vec_sr(vec_add(vec_add(t1, t3), two), two);
231 avglv = vec_sr(vec_add(vec_add(t2, t4), two), two);
232
233 /* Pack the shorts back into a result */
234 avgv = vec_pack(avghv, avglv);
235
236 /* Calculate a sum of abs differences vector */
237 t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv));
238
239 /* Add each 4 pixel group together and put 4 results into sad */
240 sad = vec_sum4s(t5, sad);
241
242 pix1 += line_size;
243 pix3 += line_size;
244 /* Transfer the calculated values for pix3 into pix2 */
245 t1 = t3;
246 t2 = t4;
247 }
248 /* Sum up the four partial sums, and put the result into s */
249 sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
250 sumdiffs = vec_splat(sumdiffs, 3);
251 vec_ste(sumdiffs, 0, &s);
252
253 return s;
254 }
255
256 int pix_abs16x16_altivec(uint8_t *pix1, uint8_t *pix2, int line_size)
257 {
258 int i;
259 int s __attribute__((aligned(16)));
260 const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0);
261 vector unsigned char perm1, perm2, *pix1v, *pix2v;
262 vector unsigned char t1, t2, t3,t4, t5;
263 vector unsigned int sad;
264 vector signed int sumdiffs;
265
266 sad = (vector unsigned int)vec_splat_u32(0);
267
268
269 for(i=0;i<16;i++) {
270 /* Read potentially unaligned pixels into t1 and t2 */
271 perm1 = vec_lvsl(0, pix1);
272 pix1v = (vector unsigned char *) pix1;
273 perm2 = vec_lvsl(0, pix2);
274 pix2v = (vector unsigned char *) pix2;
275 t1 = vec_perm(pix1v[0], pix1v[1], perm1);
276 t2 = vec_perm(pix2v[0], pix2v[1], perm2);
277
278 /* Calculate a sum of abs differences vector */
279 t3 = vec_max(t1, t2);
280 t4 = vec_min(t1, t2);
281 t5 = vec_sub(t3, t4);
282
283 /* Add each 4 pixel group together and put 4 results into sad */
284 sad = vec_sum4s(t5, sad);
285
286 pix1 += line_size;
287 pix2 += line_size;
288 }
289
290 /* Sum up the four partial sums, and put the result into s */
291 sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
292 sumdiffs = vec_splat(sumdiffs, 3);
293 vec_ste(sumdiffs, 0, &s);
294
295 return s;
296 }
297
298 int pix_abs8x8_altivec(uint8_t *pix1, uint8_t *pix2, int line_size)
299 {
300 int i;
301 int s __attribute__((aligned(16)));
302 const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0);
303 vector unsigned char perm1, perm2, permclear, *pix1v, *pix2v;
304 vector unsigned char t1, t2, t3,t4, t5;
305 vector unsigned int sad;
306 vector signed int sumdiffs;
307
308 sad = (vector unsigned int)vec_splat_u32(0);
309
310 permclear = (vector unsigned char)AVV(255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0);
311
312 for(i=0;i<8;i++) {
313 /* Read potentially unaligned pixels into t1 and t2
314 Since we're reading 16 pixels, and actually only want 8,
315 mask out the last 8 pixels. The 0s don't change the sum. */
316 perm1 = vec_lvsl(0, pix1);
317 pix1v = (vector unsigned char *) pix1;
318 perm2 = vec_lvsl(0, pix2);
319 pix2v = (vector unsigned char *) pix2;
320 t1 = vec_and(vec_perm(pix1v[0], pix1v[1], perm1), permclear);
321 t2 = vec_and(vec_perm(pix2v[0], pix2v[1], perm2), permclear);
322
323 /* Calculate a sum of abs differences vector */
324 t3 = vec_max(t1, t2);
325 t4 = vec_min(t1, t2);
326 t5 = vec_sub(t3, t4);
327
328 /* Add each 4 pixel group together and put 4 results into sad */
329 sad = vec_sum4s(t5, sad);
330
331 pix1 += line_size;
332 pix2 += line_size;
333 }
334
335 /* Sum up the four partial sums, and put the result into s */
336 sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
337 sumdiffs = vec_splat(sumdiffs, 3);
338 vec_ste(sumdiffs, 0, &s);
339
340 return s;
341 }
342
343 int pix_norm1_altivec(uint8_t *pix, int line_size)
344 {
345 int i;
346 int s __attribute__((aligned(16)));
347 const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0);
348 vector unsigned char *tv;
349 vector unsigned char pixv;
350 vector unsigned int sv;
351 vector signed int sum;
352
353 sv = (vector unsigned int)vec_splat_u32(0);
354
355 s = 0;
356 for (i = 0; i < 16; i++) {
357 /* Read in the potentially unaligned pixels */
358 tv = (vector unsigned char *) pix;
359 pixv = vec_perm(tv[0], tv[1], vec_lvsl(0, pix));
360
361 /* Square the values, and add them to our sum */
362 sv = vec_msum(pixv, pixv, sv);
363
364 pix += line_size;
365 }
366 /* Sum up the four partial sums, and put the result into s */
367 sum = vec_sums((vector signed int) sv, (vector signed int) zero);
368 sum = vec_splat(sum, 3);
369 vec_ste(sum, 0, &s);
370
371 return s;
372 }
373
374 /**
375 * Sum of Squared Errors for a 8x8 block.
376 * AltiVec-enhanced.
377 * It's the pix_abs8x8_altivec code above w/ squaring added.
378 */
379 int sse8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size)
380 {
381 int i;
382 int s __attribute__((aligned(16)));
383 const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0);
384 vector unsigned char perm1, perm2, permclear, *pix1v, *pix2v;
385 vector unsigned char t1, t2, t3,t4, t5;
386 vector unsigned int sum;
387 vector signed int sumsqr;
388
389 sum = (vector unsigned int)vec_splat_u32(0);
390
391 permclear = (vector unsigned char)AVV(255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0);
392
393
394 for(i=0;i<8;i++) {
395 /* Read potentially unaligned pixels into t1 and t2
396 Since we're reading 16 pixels, and actually only want 8,
397 mask out the last 8 pixels. The 0s don't change the sum. */
398 perm1 = vec_lvsl(0, pix1);
399 pix1v = (vector unsigned char *) pix1;
400 perm2 = vec_lvsl(0, pix2);
401 pix2v = (vector unsigned char *) pix2;
402 t1 = vec_and(vec_perm(pix1v[0], pix1v[1], perm1), permclear);
403 t2 = vec_and(vec_perm(pix2v[0], pix2v[1], perm2), permclear);
404
405 /*
406 Since we want to use unsigned chars, we can take advantage
407 of the fact that abs(a-b)^2 = (a-b)^2.
408 */
409
410 /* Calculate abs differences vector */
411 t3 = vec_max(t1, t2);
412 t4 = vec_min(t1, t2);
413 t5 = vec_sub(t3, t4);
414
415 /* Square the values and add them to our sum */
416 sum = vec_msum(t5, t5, sum);
417
418 pix1 += line_size;
419 pix2 += line_size;
420 }
421
422 /* Sum up the four partial sums, and put the result into s */
423 sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero);
424 sumsqr = vec_splat(sumsqr, 3);
425 vec_ste(sumsqr, 0, &s);
426
427 return s;
428 }
429
430 /**
431 * Sum of Squared Errors for a 16x16 block.
432 * AltiVec-enhanced.
433 * It's the pix_abs16x16_altivec code above w/ squaring added.
434 */
435 int sse16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size)
436 {
437 int i;
438 int s __attribute__((aligned(16)));
439 const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0);
440 vector unsigned char perm1, perm2, *pix1v, *pix2v;
441 vector unsigned char t1, t2, t3,t4, t5;
442 vector unsigned int sum;
443 vector signed int sumsqr;
444
445 sum = (vector unsigned int)vec_splat_u32(0);
446
447 for(i=0;i<16;i++) {
448 /* Read potentially unaligned pixels into t1 and t2 */
449 perm1 = vec_lvsl(0, pix1);
450 pix1v = (vector unsigned char *) pix1;
451 perm2 = vec_lvsl(0, pix2);
452 pix2v = (vector unsigned char *) pix2;
453 t1 = vec_perm(pix1v[0], pix1v[1], perm1);
454 t2 = vec_perm(pix2v[0], pix2v[1], perm2);
455
456 /*
457 Since we want to use unsigned chars, we can take advantage
458 of the fact that abs(a-b)^2 = (a-b)^2.
459 */
460
461 /* Calculate abs differences vector */
462 t3 = vec_max(t1, t2);
463 t4 = vec_min(t1, t2);
464 t5 = vec_sub(t3, t4);
465
466 /* Square the values and add them to our sum */
467 sum = vec_msum(t5, t5, sum);
468
469 pix1 += line_size;
470 pix2 += line_size;
471 }
472
473 /* Sum up the four partial sums, and put the result into s */
474 sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero);
475 sumsqr = vec_splat(sumsqr, 3);
476 vec_ste(sumsqr, 0, &s);
477
478 return s;
479 }
480
481 int pix_sum_altivec(uint8_t * pix, int line_size)
482 {
483 const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0);
484 vector unsigned char perm, *pixv;
485 vector unsigned char t1;
486 vector unsigned int sad;
487 vector signed int sumdiffs;
488
489 int i;
490 int s __attribute__((aligned(16)));
491
492 sad = (vector unsigned int)vec_splat_u32(0);
493
494 for (i = 0; i < 16; i++) {
495 /* Read the potentially unaligned 16 pixels into t1 */
496 perm = vec_lvsl(0, pix);
497 pixv = (vector unsigned char *) pix;
498 t1 = vec_perm(pixv[0], pixv[1], perm);
499
500 /* Add each 4 pixel group together and put 4 results into sad */
501 sad = vec_sum4s(t1, sad);
502
503 pix += line_size;
504 }
505
506 /* Sum up the four partial sums, and put the result into s */
507 sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
508 sumdiffs = vec_splat(sumdiffs, 3);
509 vec_ste(sumdiffs, 0, &s);
510
511 return s;
512 }
513
514 void get_pixels_altivec(DCTELEM *restrict block, const uint8_t *pixels, int line_size)
515 {
516 int i;
517 vector unsigned char perm, bytes, *pixv;
518 const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0);
519 vector signed short shorts;
520
521 for(i=0;i<8;i++)
522 {
523 // Read potentially unaligned pixels.
524 // We're reading 16 pixels, and actually only want 8,
525 // but we simply ignore the extras.
526 perm = vec_lvsl(0, pixels);
527 pixv = (vector unsigned char *) pixels;
528 bytes = vec_perm(pixv[0], pixv[1], perm);
529
530 // convert the bytes into shorts
531 shorts = (vector signed short)vec_mergeh(zero, bytes);
532
533 // save the data to the block, we assume the block is 16-byte aligned
534 vec_st(shorts, i*16, (vector signed short*)block);
535
536 pixels += line_size;
537 }
538 }
539
540 void diff_pixels_altivec(DCTELEM *restrict block, const uint8_t *s1,
541 const uint8_t *s2, int stride)
542 {
543 int i;
544 vector unsigned char perm, bytes, *pixv;
545 const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0);
546 vector signed short shorts1, shorts2;
547
548 for(i=0;i<4;i++)
549 {
550 // Read potentially unaligned pixels
551 // We're reading 16 pixels, and actually only want 8,
552 // but we simply ignore the extras.
553 perm = vec_lvsl(0, s1);
554 pixv = (vector unsigned char *) s1;
555 bytes = vec_perm(pixv[0], pixv[1], perm);
556
557 // convert the bytes into shorts
558 shorts1 = (vector signed short)vec_mergeh(zero, bytes);
559
560 // Do the same for the second block of pixels
561 perm = vec_lvsl(0, s2);
562 pixv = (vector unsigned char *) s2;
563 bytes = vec_perm(pixv[0], pixv[1], perm);
564
565 // convert the bytes into shorts
566 shorts2 = (vector signed short)vec_mergeh(zero, bytes);
567
568 // Do the subtraction
569 shorts1 = vec_sub(shorts1, shorts2);
570
571 // save the data to the block, we assume the block is 16-byte aligned
572 vec_st(shorts1, 0, (vector signed short*)block);
573
574 s1 += stride;
575 s2 += stride;
576 block += 8;
577
578
579 // The code below is a copy of the code above... This is a manual
580 // unroll.
581
582 // Read potentially unaligned pixels
583 // We're reading 16 pixels, and actually only want 8,
584 // but we simply ignore the extras.
585 perm = vec_lvsl(0, s1);
586 pixv = (vector unsigned char *) s1;
587 bytes = vec_perm(pixv[0], pixv[1], perm);
588
589 // convert the bytes into shorts
590 shorts1 = (vector signed short)vec_mergeh(zero, bytes);
591
592 // Do the same for the second block of pixels
593 perm = vec_lvsl(0, s2);
594 pixv = (vector unsigned char *) s2;
595 bytes = vec_perm(pixv[0], pixv[1], perm);
596
597 // convert the bytes into shorts
598 shorts2 = (vector signed short)vec_mergeh(zero, bytes);
599
600 // Do the subtraction
601 shorts1 = vec_sub(shorts1, shorts2);
602
603 // save the data to the block, we assume the block is 16-byte aligned
604 vec_st(shorts1, 0, (vector signed short*)block);
605
606 s1 += stride;
607 s2 += stride;
608 block += 8;
609 }
610 }
611
612 int sad16x16_altivec(void *s, uint8_t *a, uint8_t *b, int stride) {
613 return pix_abs16x16_altivec(a,b,stride);
614 }
615
616 int sad8x8_altivec(void *s, uint8_t *a, uint8_t *b, int stride) {
617 return pix_abs8x8_altivec(a,b,stride);
618 }
619
620 void add_bytes_altivec(uint8_t *dst, uint8_t *src, int w) {
621 #ifdef ALTIVEC_USE_REFERENCE_C_CODE
622 int i;
623 for(i=0; i+7<w; i++){
624 dst[i+0] += src[i+0];
625 dst[i+1] += src[i+1];
626 dst[i+2] += src[i+2];
627 dst[i+3] += src[i+3];
628 dst[i+4] += src[i+4];
629 dst[i+5] += src[i+5];
630 dst[i+6] += src[i+6];
631 dst[i+7] += src[i+7];
632 }
633 for(; i<w; i++)
634 dst[i+0] += src[i+0];
635 #else /* ALTIVEC_USE_REFERENCE_C_CODE */
636 register int i;
637 register vector unsigned char vdst, vsrc;
638
639 /* dst and src are 16 bytes-aligned (guaranteed) */
640 for(i = 0 ; (i + 15) < w ; i++)
641 {
642 vdst = vec_ld(i << 4, (unsigned char*)dst);
643 vsrc = vec_ld(i << 4, (unsigned char*)src);
644 vdst = vec_add(vsrc, vdst);
645 vec_st(vdst, i << 4, (unsigned char*)dst);
646 }
647 /* if w is not a multiple of 16 */
648 for (; (i < w) ; i++)
649 {
650 dst[i] = src[i];
651 }
652 #endif /* ALTIVEC_USE_REFERENCE_C_CODE */
653 }
654
655 /* next one assumes that ((line_size % 16) == 0) */
656 void put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h)
657 {
658 POWERPC_TBL_DECLARE(altivec_put_pixels16_num, 1);
659 #ifdef ALTIVEC_USE_REFERENCE_C_CODE
660 int i;
661
662 POWERPC_TBL_START_COUNT(altivec_put_pixels16_num, 1);
663
664 for(i=0; i<h; i++) {
665 *((uint32_t*)(block )) = (((const struct unaligned_32 *) (pixels))->l);
666 *((uint32_t*)(block+4)) = (((const struct unaligned_32 *) (pixels+4))->l);
667 *((uint32_t*)(block+8)) = (((const struct unaligned_32 *) (pixels+8))->l);
668 *((uint32_t*)(block+12)) = (((const struct unaligned_32 *) (pixels+12))->l);
669 pixels+=line_size;
670 block +=line_size;
671 }
672
673 POWERPC_TBL_STOP_COUNT(altivec_put_pixels16_num, 1);
674
675 #else /* ALTIVEC_USE_REFERENCE_C_CODE */
676 register vector unsigned char pixelsv1, pixelsv2;
677 register vector unsigned char perm = vec_lvsl(0, pixels);
678 int i;
679
680 POWERPC_TBL_START_COUNT(altivec_put_pixels16_num, 1);
681
682 for(i=0; i<h; i++) {
683 pixelsv1 = vec_ld(0, (unsigned char*)pixels);
684 pixelsv2 = vec_ld(16, (unsigned char*)pixels);
685 vec_st(vec_perm(pixelsv1, pixelsv2, perm),
686 0, (unsigned char*)block);
687 pixels+=line_size;
688 block +=line_size;
689 }
690
691 POWERPC_TBL_STOP_COUNT(altivec_put_pixels16_num, 1);
692
693 #endif /* ALTIVEC_USE_REFERENCE_C_CODE */
694 }
695
696 /* next one assumes that ((line_size % 16) == 0) */
697 #define op_avg(a,b) a = ( ((a)|(b)) - ((((a)^(b))&0xFEFEFEFEUL)>>1) )
698 void avg_pixels16_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h)
699 {
700 POWERPC_TBL_DECLARE(altivec_avg_pixels16_num, 1);
701 #ifdef ALTIVEC_USE_REFERENCE_C_CODE
702 int i;
703
704 POWERPC_TBL_START_COUNT(altivec_avg_pixels16_num, 1);
705
706 for(i=0; i<h; i++) {
707 op_avg(*((uint32_t*)(block)),(((const struct unaligned_32 *)(pixels))->l));
708 op_avg(*((uint32_t*)(block+4)),(((const struct unaligned_32 *)(pixels+4))->l));
709 op_avg(*((uint32_t*)(block+8)),(((const struct unaligned_32 *)(pixels+8))->l));
710 op_avg(*((uint32_t*)(block+12)),(((const struct unaligned_32 *)(pixels+12))->l));
711 pixels+=line_size;
712 block +=line_size;
713 }
714
715 POWERPC_TBL_STOP_COUNT(altivec_avg_pixels16_num, 1);
716
717 #else /* ALTIVEC_USE_REFERENCE_C_CODE */
718 register vector unsigned char pixelsv1, pixelsv2, pixelsv, blockv;
719 register vector unsigned char perm = vec_lvsl(0, pixels);
720 int i;
721
722 POWERPC_TBL_START_COUNT(altivec_avg_pixels16_num, 1);
723
724 for(i=0; i<h; i++) {
725 pixelsv1 = vec_ld(0, (unsigned char*)pixels);
726 pixelsv2 = vec_ld(16, (unsigned char*)pixels);
727 blockv = vec_ld(0, block);
728 pixelsv = vec_perm(pixelsv1, pixelsv2, perm);
729 blockv = vec_avg(blockv,pixelsv);
730 vec_st(blockv, 0, (unsigned char*)block);
731 pixels+=line_size;
732 block +=line_size;
733 }
734
735 POWERPC_TBL_STOP_COUNT(altivec_avg_pixels16_num, 1);
736
737 #endif /* ALTIVEC_USE_REFERENCE_C_CODE */
738 }
739
740 /* next one assumes that ((line_size % 8) == 0) */
741 void avg_pixels8_altivec(uint8_t * block, const uint8_t * pixels, int line_size, int h)
742 {
743 POWERPC_TBL_DECLARE(altivec_avg_pixels8_num, 1);
744 #ifdef ALTIVEC_USE_REFERENCE_C_CODE
745 int i;
746 POWERPC_TBL_START_COUNT(altivec_avg_pixels8_num, 1);
747 for (i = 0; i < h; i++) {
748 *((uint32_t *) (block)) =
749 (((*((uint32_t *) (block))) |
750 ((((const struct unaligned_32 *) (pixels))->l))) -
751 ((((*((uint32_t *) (block))) ^
752 ((((const struct unaligned_32 *) (pixels))->
753 l))) & 0xFEFEFEFEUL) >> 1));
754 *((uint32_t *) (block + 4)) =
755 (((*((uint32_t *) (block + 4))) |
756 ((((const struct unaligned_32 *) (pixels + 4))->l))) -
757 ((((*((uint32_t *) (block + 4))) ^
758 ((((const struct unaligned_32 *) (pixels +
759 4))->
760 l))) & 0xFEFEFEFEUL) >> 1));
761 pixels += line_size;
762 block += line_size;
763 }
764 POWERPC_TBL_STOP_COUNT(altivec_avg_pixels8_num, 1);
765
766 #else /* ALTIVEC_USE_REFERENCE_C_CODE */
767 register vector unsigned char pixelsv1, pixelsv2, pixelsv, blockv;
768 int i;
769
770 POWERPC_TBL_START_COUNT(altivec_avg_pixels8_num, 1);
771
772 for (i = 0; i < h; i++) {
773 /*
774 block is 8 bytes-aligned, so we're either in the
775 left block (16 bytes-aligned) or in the right block (not)
776 */
777 int rightside = ((unsigned long)block & 0x0000000F);
778
779 blockv = vec_ld(0, block);
780 pixelsv1 = vec_ld(0, (unsigned char*)pixels);
781 pixelsv2 = vec_ld(16, (unsigned char*)pixels);
782 pixelsv = vec_perm(pixelsv1, pixelsv2, vec_lvsl(0, pixels));
783
784 if (rightside)
785 {
786 pixelsv = vec_perm(blockv, pixelsv, vcprm(0,1,s0,s1));
787 }
788 else
789 {
790 pixelsv = vec_perm(blockv, pixelsv, vcprm(s0,s1,2,3));
791 }
792
793 blockv = vec_avg(blockv, pixelsv);
794
795 vec_st(blockv, 0, block);
796
797 pixels += line_size;
798 block += line_size;
799 }
800
801 POWERPC_TBL_STOP_COUNT(altivec_avg_pixels8_num, 1);
802
803 #endif /* ALTIVEC_USE_REFERENCE_C_CODE */
804 }
805
806 /* next one assumes that ((line_size % 8) == 0) */
807 void put_pixels8_xy2_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h)
808 {
809 POWERPC_TBL_DECLARE(altivec_put_pixels8_xy2_num, 1);
810 #ifdef ALTIVEC_USE_REFERENCE_C_CODE
811 int j;
812 POWERPC_TBL_START_COUNT(altivec_put_pixels8_xy2_num, 1);
813 for (j = 0; j < 2; j++) {
814 int i;
815 const uint32_t a = (((const struct unaligned_32 *) (pixels))->l);
816 const uint32_t b =
817 (((const struct unaligned_32 *) (pixels + 1))->l);
818 uint32_t l0 =
819 (a & 0x03030303UL) + (b & 0x03030303UL) + 0x02020202UL;
820 uint32_t h0 =
821 ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
822 uint32_t l1, h1;
823 pixels += line_size;
824 for (i = 0; i < h; i += 2) {
825 uint32_t a = (((const struct unaligned_32 *) (pixels))->l);
826 uint32_t b = (((const struct unaligned_32 *) (pixels + 1))->l);
827 l1 = (a & 0x03030303UL) + (b & 0x03030303UL);
828 h1 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
829 *((uint32_t *) block) =
830 h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
831 pixels += line_size;
832 block += line_size;
833 a = (((const struct unaligned_32 *) (pixels))->l);
834 b = (((const struct unaligned_32 *) (pixels + 1))->l);
835 l0 = (a & 0x03030303UL) + (b & 0x03030303UL) + 0x02020202UL;
836 h0 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
837 *((uint32_t *) block) =
838 h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
839 pixels += line_size;
840 block += line_size;
841 } pixels += 4 - line_size * (h + 1);
842 block += 4 - line_size * h;
843 }
844
845 POWERPC_TBL_STOP_COUNT(altivec_put_pixels8_xy2_num, 1);
846
847 #else /* ALTIVEC_USE_REFERENCE_C_CODE */
848 register int i;
849 register vector unsigned char
850 pixelsv1, pixelsv2,
851 pixelsavg;
852 register vector unsigned char
853 blockv, temp1, temp2;
854 register vector unsigned short
855 pixelssum1, pixelssum2, temp3;
856 register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0);
857 register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2);
858
859 temp1 = vec_ld(0, pixels);
860 temp2 = vec_ld(16, pixels);
861 pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels));
862 if ((((unsigned long)pixels) & 0x0000000F) == 0x0000000F)
863 {
864 pixelsv2 = temp2;
865 }
866 else
867 {
868 pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels));
869 }
870 pixelsv1 = vec_mergeh(vczero, pixelsv1);
871 pixelsv2 = vec_mergeh(vczero, pixelsv2);
872 pixelssum1 = vec_add((vector unsigned short)pixelsv1,
873 (vector unsigned short)pixelsv2);
874 pixelssum1 = vec_add(pixelssum1, vctwo);
875
876 POWERPC_TBL_START_COUNT(altivec_put_pixels8_xy2_num, 1);
877 for (i = 0; i < h ; i++) {
878 int rightside = ((unsigned long)block & 0x0000000F);
879 blockv = vec_ld(0, block);
880
881 temp1 = vec_ld(line_size, pixels);
882 temp2 = vec_ld(line_size + 16, pixels);
883 pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels));
884 if (((((unsigned long)pixels) + line_size) & 0x0000000F) == 0x0000000F)
885 {
886 pixelsv2 = temp2;
887 }
888 else
889 {
890 pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels));
891 }
892
893 pixelsv1 = vec_mergeh(vczero, pixelsv1);
894 pixelsv2 = vec_mergeh(vczero, pixelsv2);
895 pixelssum2 = vec_add((vector unsigned short)pixelsv1,
896 (vector unsigned short)pixelsv2);
897 temp3 = vec_add(pixelssum1, pixelssum2);
898 temp3 = vec_sra(temp3, vctwo);
899 pixelssum1 = vec_add(pixelssum2, vctwo);
900 pixelsavg = vec_packsu(temp3, (vector unsigned short) vczero);
901
902 if (rightside)
903 {
904 blockv = vec_perm(blockv, pixelsavg, vcprm(0, 1, s0, s1));
905 }
906 else
907 {
908 blockv = vec_perm(blockv, pixelsavg, vcprm(s0, s1, 2, 3));
909 }
910
911 vec_st(blockv, 0, block);
912
913 block += line_size;
914 pixels += line_size;
915 }
916
917 POWERPC_TBL_STOP_COUNT(altivec_put_pixels8_xy2_num, 1);
918 #endif /* ALTIVEC_USE_REFERENCE_C_CODE */
919 }
920
921 /* next one assumes that ((line_size % 8) == 0) */
922 void put_no_rnd_pixels8_xy2_altivec(uint8_t *block, const uint8_t *pixels, int line_size, int h)
923 {
924 POWERPC_TBL_DECLARE(altivec_put_no_rnd_pixels8_xy2_num, 1);
925 #ifdef ALTIVEC_USE_REFERENCE_C_CODE
926 int j;
927 POWERPC_TBL_START_COUNT(altivec_put_no_rnd_pixels8_xy2_num, 1);
928 for (j = 0; j < 2; j++) {
929 int i;
930 const uint32_t a = (((const struct unaligned_32 *) (pixels))->l);
931 const uint32_t b =
932 (((const struct unaligned_32 *) (pixels + 1))->l);
933 uint32_t l0 =
934 (a & 0x03030303UL) + (b & 0x03030303UL) + 0x01010101UL;
935 uint32_t h0 =
936 ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
937 uint32_t l1, h1;
938 pixels += line_size;
939 for (i = 0; i < h; i += 2) {
940 uint32_t a = (((const struct unaligned_32 *) (pixels))->l);
941 uint32_t b = (((const struct unaligned_32 *) (pixels + 1))->l);
942 l1 = (a & 0x03030303UL) + (b & 0x03030303UL);
943 h1 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
944 *((uint32_t *) block) =
945 h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
946 pixels += line_size;
947 block += line_size;
948 a = (((const struct unaligned_32 *) (pixels))->l);
949 b = (((const struct unaligned_32 *) (pixels + 1))->l);
950 l0 = (a & 0x03030303UL) + (b & 0x03030303UL) + 0x01010101UL;
951 h0 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
952 *((uint32_t *) block) =
953 h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
954 pixels += line_size;
955 block += line_size;
956 } pixels += 4 - line_size * (h + 1);
957 block += 4 - line_size * h;
958 }
959
960 POWERPC_TBL_STOP_COUNT(altivec_put_no_rnd_pixels8_xy2_num, 1);
961
962 #else /* ALTIVEC_USE_REFERENCE_C_CODE */
963 register int i;
964 register vector unsigned char
965 pixelsv1, pixelsv2,
966 pixelsavg;
967 register vector unsigned char
968 blockv, temp1, temp2;
969 register vector unsigned short
970 pixelssum1, pixelssum2, temp3;
971 register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0);
972 register const vector unsigned short vcone = (const vector unsigned short)vec_splat_u16(1);
973 register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2);
974
975 temp1 = vec_ld(0, pixels);
976 temp2 = vec_ld(16, pixels);
977 pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels));
978 if ((((unsigned long)pixels) & 0x0000000F) == 0x0000000F)
979 {
980 pixelsv2 = temp2;
981 }
982 else
983 {
984 pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels));
985 }
986 pixelsv1 = vec_mergeh(vczero, pixelsv1);
987 pixelsv2 = vec_mergeh(vczero, pixelsv2);
988 pixelssum1 = vec_add((vector unsigned short)pixelsv1,
989 (vector unsigned short)pixelsv2);
990 pixelssum1 = vec_add(pixelssum1, vcone);
991
992 POWERPC_TBL_START_COUNT(altivec_put_no_rnd_pixels8_xy2_num, 1);
993 for (i = 0; i < h ; i++) {
994 int rightside = ((unsigned long)block & 0x0000000F);
995 blockv = vec_ld(0, block);
996
997 temp1 = vec_ld(line_size, pixels);
998 temp2 = vec_ld(line_size + 16, pixels);
999 pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels));
1000 if (((((unsigned long)pixels) + line_size) & 0x0000000F) == 0x0000000F)
1001 {
1002 pixelsv2 = temp2;
1003 }
1004 else
1005 {
1006 pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels));
1007 }
1008
1009 pixelsv1 = vec_mergeh(vczero, pixelsv1);
1010 pixelsv2 = vec_mergeh(vczero, pixelsv2);
1011 pixelssum2 = vec_add((vector unsigned short)pixelsv1,
1012 (vector unsigned short)pixelsv2);
1013 temp3 = vec_add(pixelssum1, pixelssum2);
1014 temp3 = vec_sra(temp3, vctwo);
1015 pixelssum1 = vec_add(pixelssum2, vcone);
1016 pixelsavg = vec_packsu(temp3, (vector unsigned short) vczero);
1017
1018 if (rightside)
1019 {
1020 blockv = vec_perm(blockv, pixelsavg, vcprm(0, 1, s0, s1));
1021 }
1022 else
1023 {
1024 blockv = vec_perm(blockv, pixelsavg, vcprm(s0, s1, 2, 3));
1025 }
1026
1027 vec_st(blockv, 0, block);
1028
1029 block += line_size;
1030 pixels += line_size;
1031 }
1032
1033 POWERPC_TBL_STOP_COUNT(altivec_put_no_rnd_pixels8_xy2_num, 1);
1034 #endif /* ALTIVEC_USE_REFERENCE_C_CODE */
1035 }
1036
1037 /* next one assumes that ((line_size % 16) == 0) */
1038 void put_pixels16_xy2_altivec(uint8_t * block, const uint8_t * pixels, int line_size, int h)
1039 {
1040 POWERPC_TBL_DECLARE(altivec_put_pixels16_xy2_num, 1);
1041 #ifdef ALTIVEC_USE_REFERENCE_C_CODE
1042 int j;
1043 POWERPC_TBL_START_COUNT(altivec_put_pixels16_xy2_num, 1);
1044 for (j = 0; j < 4; j++) {
1045 int i;
1046 const uint32_t a = (((const struct unaligned_32 *) (pixels))->l);
1047 const uint32_t b =
1048 (((const struct unaligned_32 *) (pixels + 1))->l);
1049 uint32_t l0 =
1050 (a & 0x03030303UL) + (b & 0x03030303UL) + 0x02020202UL;
1051 uint32_t h0 =
1052 ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
1053 uint32_t l1, h1;
1054 pixels += line_size;
1055 for (i = 0; i < h; i += 2) {
1056 uint32_t a = (((const struct unaligned_32 *) (pixels))->l);
1057 uint32_t b = (((const struct unaligned_32 *) (pixels + 1))->l);
1058 l1 = (a & 0x03030303UL) + (b & 0x03030303UL);
1059 h1 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
1060 *((uint32_t *) block) =
1061 h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
1062 pixels += line_size;
1063 block += line_size;
1064 a = (((const struct unaligned_32 *) (pixels))->l);
1065 b = (((const struct unaligned_32 *) (pixels + 1))->l);
1066 l0 = (a & 0x03030303UL) + (b & 0x03030303UL) + 0x02020202UL;
1067 h0 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
1068 *((uint32_t *) block) =
1069 h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
1070 pixels += line_size;
1071 block += line_size;
1072 } pixels += 4 - line_size * (h + 1);
1073 block += 4 - line_size * h;
1074 }
1075
1076 POWERPC_TBL_STOP_COUNT(altivec_put_pixels16_xy2_num, 1);
1077
1078 #else /* ALTIVEC_USE_REFERENCE_C_CODE */
1079 register int i;
1080 register vector unsigned char
1081 pixelsv1, pixelsv2, pixelsv3, pixelsv4;
1082 register vector unsigned char
1083 blockv, temp1, temp2;
1084 register vector unsigned short
1085 pixelssum1, pixelssum2, temp3,
1086 pixelssum3, pixelssum4, temp4;
1087 register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0);
1088 register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2);
1089
1090 POWERPC_TBL_START_COUNT(altivec_put_pixels16_xy2_num, 1);
1091
1092 temp1 = vec_ld(0, pixels);
1093 temp2 = vec_ld(16, pixels);
1094 pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels));
1095 if ((((unsigned long)pixels) & 0x0000000F) == 0x0000000F)
1096 {
1097 pixelsv2 = temp2;
1098 }
1099 else
1100 {
1101 pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels));
1102 }
1103 pixelsv3 = vec_mergel(vczero, pixelsv1);
1104 pixelsv4 = vec_mergel(vczero, pixelsv2);
1105 pixelsv1 = vec_mergeh(vczero, pixelsv1);
1106 pixelsv2 = vec_mergeh(vczero, pixelsv2);
1107 pixelssum3 = vec_add((vector unsigned short)pixelsv3,
1108 (vector unsigned short)pixelsv4);
1109 pixelssum3 = vec_add(pixelssum3, vctwo);
1110 pixelssum1 = vec_add((vector unsigned short)pixelsv1,
1111 (vector unsigned short)pixelsv2);
1112 pixelssum1 = vec_add(pixelssum1, vctwo);
1113
1114 for (i = 0; i < h ; i++) {
1115 blockv = vec_ld(0, block);
1116
1117 temp1 = vec_ld(line_size, pixels);
1118 temp2 = vec_ld(line_size + 16, pixels);
1119 pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels));
1120 if (((((unsigned long)pixels) + line_size) & 0x0000000F) == 0x0000000F)
1121 {
1122 pixelsv2 = temp2;
1123 }
1124 else
1125 {
1126 pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels));
1127 }
1128
1129 pixelsv3 = vec_mergel(vczero, pixelsv1);
1130 pixelsv4 = vec_mergel(vczero, pixelsv2);
1131 pixelsv1 = vec_mergeh(vczero, pixelsv1);
1132 pixelsv2 = vec_mergeh(vczero, pixelsv2);
1133
1134 pixelssum4 = vec_add((vector unsigned short)pixelsv3,
1135 (vector unsigned short)pixelsv4);
1136 pixelssum2 = vec_add((vector unsigned short)pixelsv1,
1137 (vector unsigned short)pixelsv2);
1138 temp4 = vec_add(pixelssum3, pixelssum4);
1139 temp4 = vec_sra(temp4, vctwo);
1140 temp3 = vec_add(pixelssum1, pixelssum2);
1141 temp3 = vec_sra(temp3, vctwo);
1142
1143 pixelssum3 = vec_add(pixelssum4, vctwo);
1144 pixelssum1 = vec_add(pixelssum2, vctwo);
1145
1146 blockv = vec_packsu(temp3, temp4);
1147
1148 vec_st(blockv, 0, block);
1149
1150 block += line_size;
1151 pixels += line_size;
1152 }
1153
1154 POWERPC_TBL_STOP_COUNT(altivec_put_pixels16_xy2_num, 1);
1155 #endif /* ALTIVEC_USE_REFERENCE_C_CODE */
1156 }
1157
1158 /* next one assumes that ((line_size % 16) == 0) */
1159 void put_no_rnd_pixels16_xy2_altivec(uint8_t * block, const uint8_t * pixels, int line_size, int h)
1160 {
1161 POWERPC_TBL_DECLARE(altivec_put_no_rnd_pixels16_xy2_num, 1);
1162 #ifdef ALTIVEC_USE_REFERENCE_C_CODE
1163 int j;
1164 POWERPC_TBL_START_COUNT(altivec_put_no_rnd_pixels16_xy2_num, 1);
1165 for (j = 0; j < 4; j++) {
1166 int i;
1167 const uint32_t a = (((const struct unaligned_32 *) (pixels))->l);
1168 const uint32_t b =
1169 (((const struct unaligned_32 *) (pixels + 1))->l);
1170 uint32_t l0 =
1171 (a & 0x03030303UL) + (b & 0x03030303UL) + 0x01010101UL;
1172 uint32_t h0 =
1173 ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
1174 uint32_t l1, h1;
1175 pixels += line_size;
1176 for (i = 0; i < h; i += 2) {
1177 uint32_t a = (((const struct unaligned_32 *) (pixels))->l);
1178 uint32_t b = (((const struct unaligned_32 *) (pixels + 1))->l);
1179 l1 = (a & 0x03030303UL) + (b & 0x03030303UL);
1180 h1 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
1181 *((uint32_t *) block) =
1182 h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
1183 pixels += line_size;
1184 block += line_size;
1185 a = (((const struct unaligned_32 *) (pixels))->l);
1186 b = (((const struct unaligned_32 *) (pixels + 1))->l);
1187 l0 = (a & 0x03030303UL) + (b & 0x03030303UL) + 0x01010101UL;
1188 h0 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
1189 *((uint32_t *) block) =
1190 h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
1191 pixels += line_size;
1192 block += line_size;
1193 } pixels += 4 - line_size * (h + 1);
1194 block += 4 - line_size * h;
1195 }
1196
1197 POWERPC_TBL_STOP_COUNT(altivec_put_no_rnd_pixels16_xy2_num, 1);
1198
1199 #else /* ALTIVEC_USE_REFERENCE_C_CODE */
1200 register int i;
1201 register vector unsigned char
1202 pixelsv1, pixelsv2, pixelsv3, pixelsv4;
1203 register vector unsigned char
1204 blockv, temp1, temp2;
1205 register vector unsigned short
1206 pixelssum1, pixelssum2, temp3,
1207 pixelssum3, pixelssum4, temp4;
1208 register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0);
1209 register const vector unsigned short vcone = (const vector unsigned short)vec_splat_u16(1);
1210 register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2);
1211
1212 POWERPC_TBL_START_COUNT(altivec_put_no_rnd_pixels16_xy2_num, 1);
1213
1214 temp1 = vec_ld(0, pixels);
1215 temp2 = vec_ld(16, pixels);
1216 pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels));
1217 if ((((unsigned long)pixels) & 0x0000000F) == 0x0000000F)
1218 {
1219 pixelsv2 = temp2;
1220 }
1221 else
1222 {
1223 pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels));
1224 }
1225 pixelsv3 = vec_mergel(vczero, pixelsv1);
1226 pixelsv4 = vec_mergel(vczero, pixelsv2);
1227 pixelsv1 = vec_mergeh(vczero, pixelsv1);
1228 pixelsv2 = vec_mergeh(vczero, pixelsv2);
1229 pixelssum3 = vec_add((vector unsigned short)pixelsv3,
1230 (vector unsigned short)pixelsv4);
1231 pixelssum3 = vec_add(pixelssum3, vcone);
1232 pixelssum1 = vec_add((vector unsigned short)pixelsv1,
1233 (vector unsigned short)pixelsv2);
1234 pixelssum1 = vec_add(pixelssum1, vcone);
1235
1236 for (i = 0; i < h ; i++) {
1237 blockv = vec_ld(0, block);
1238
1239 temp1 = vec_ld(line_size, pixels);
1240 temp2 = vec_ld(line_size + 16, pixels);
1241 pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels));
1242 if (((((unsigned long)pixels) + line_size) & 0x0000000F) == 0x0000000F)
1243 {
1244 pixelsv2 = temp2;
1245 }
1246 else
1247 {
1248 pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels));
1249 }
1250
1251 pixelsv3 = vec_mergel(vczero, pixelsv1);
1252 pixelsv4 = vec_mergel(vczero, pixelsv2);
1253 pixelsv1 = vec_mergeh(vczero, pixelsv1);
1254 pixelsv2 = vec_mergeh(vczero, pixelsv2);
1255
1256 pixelssum4 = vec_add((vector unsigned short)pixelsv3,
1257 (vector unsigned short)pixelsv4);
1258 pixelssum2 = vec_add((vector unsigned short)pixelsv1,
1259 (vector unsigned short)pixelsv2);
1260 temp4 = vec_add(pixelssum3, pixelssum4);
1261 temp4 = vec_sra(temp4, vctwo);
1262 temp3 = vec_add(pixelssum1, pixelssum2);
1263 temp3 = vec_sra(temp3, vctwo);
1264
1265 pixelssum3 = vec_add(pixelssum4, vcone);
1266 pixelssum1 = vec_add(pixelssum2, vcone);
1267
1268 blockv = vec_packsu(temp3, temp4);
1269
1270 vec_st(blockv, 0, block);
1271
1272 block += line_size;
1273 pixels += line_size;
1274 }
1275
1276 POWERPC_TBL_STOP_COUNT(altivec_put_no_rnd_pixels16_xy2_num, 1);
1277 #endif /* ALTIVEC_USE_REFERENCE_C_CODE */
1278 }
1279
1280 int has_altivec(void)
1281 {
1282 #ifdef CONFIG_DARWIN
1283 int sels[2] = {CTL_HW, HW_VECTORUNIT};
1284 int has_vu = 0;
1285 size_t len = sizeof(has_vu);
1286 int err;
1287
1288 err = sysctl(sels, 2, &has_vu, &len, NULL, 0);
1289
1290 if (err == 0) return (has_vu != 0);
1291 #else /* CONFIG_DARWIN */
1292 /* no Darwin, do it the brute-force way */
1293 /* this is borrowed from the libmpeg2 library */
1294 {
1295 signal (SIGILL, sigill_handler);
1296 if (sigsetjmp (jmpbuf, 1)) {
1297 signal (SIGILL, SIG_DFL);
1298 } else {
1299 canjump = 1;
1300
1301 asm volatile ("mtspr 256, %0\n\t"
1302 "vand %%v0, %%v0, %%v0"
1303 :
1304 : "r" (-1));
1305
1306 signal (SIGILL, SIG_DFL);
1307 return 1;
1308 }
1309 }
1310 #endif /* CONFIG_DARWIN */
1311 return 0;
1312 }