1 /* Return the largest absolute value of a vector of signed shorts 2 3 * This is the Altivec SIMD version. 4 5 * Copyright 2004 Phil Karn, KA9Q 6 * May be used under the terms of the GNU Lesser General Public License (LGPL) 7 */ 8 9 #include "fec.h" 10 11 signed short peakval_av(signed short *in,int cnt){ 12 vector signed short x; 13 int pad; 14 union { vector signed char cv; vector signed short hv; signed short s[8]; signed char c[16];} s; 15 vector signed short smallest,largest; 16 17 smallest = (vector signed short)(0); 18 largest = (vector signed short)(0); 19 if((pad = (int)in & 15)!=0){ 20 /* Load unaligned leading word */ 21 x = vec_perm(vec_ld(0,in),(vector signed short)(0),vec_lvsl(0,in)); 22 if(cnt < 8){ /* Shift right to chop stuff beyond end of short block */ 23 s.c[15] = (8-cnt)<<4; 24 x = vec_sro(x,s.cv); 25 } 26 smallest = vec_min(smallest,x); 27 largest = vec_max(largest,x); 28 in += 8-pad/2; 29 cnt -= 8-pad/2; 30 } 31 /* Everything is now aligned, rip through most of the block */ 32 while(cnt >= 8){ 33 x = vec_ld(0,in); 34 smallest = vec_min(smallest,x); 35 largest = vec_max(largest,x); 36 in += 8; 37 cnt -= 8; 38 } 39 /* Handle trailing fragment, if any */ 40 if(cnt > 0){ 41 x = vec_ld(0,in); 42 s.c[15] = (8-cnt)<<4; 43 x = vec_sro(x,s.cv); 44 smallest = vec_min(smallest,x); 45 largest = vec_max(largest,x); 46 } 47 /* Combine and extract result */ 48 largest = vec_max(largest,vec_abs(smallest)); 49 50 s.c[15] = 64; /* Shift right four 16-bit words */ 51 largest = vec_max(largest,vec_sro(largest,s.cv)); 52 53 s.c[15] = 32; /* Shift right two 16-bit words */ 54 largest = vec_max(largest,vec_sro(largest,s.cv)); 55 56 s.c[15] = 16; /* Shift right one 16-bit word */ 57 largest = vec_max(largest,vec_sro(largest,s.cv)); 58 59 s.hv = largest; 60 return s.s[7]; 61 } 62