1 /* Vectorized routines for PowerPC, using Altivec/VMX.
2  */
3 #ifndef eslVMX_INCLUDED
4 #define eslVMX_INCLUDED
5 
6 #include "esl_config.h"
7 #ifdef eslENABLE_VMX
8 
9 #include "easel.h"
10 
11 #include <stdio.h>
12 #include <altivec.h>
13 
14 
15 extern vector float esl_vmx_logf(vector float x);
16 extern vector float esl_vmx_expf(vector float x);
17 extern void         esl_vmx_dump_vecfloat(FILE *fp, vector float v);
18 
19 /* Function:  esl_vmx_set_float()
20  * Synopsis:  Fills float vector with x.
21  *
22  * Purpose:   Sets all elements in the vector <float> to x.
23  */
24 static inline vector float
esl_vmx_set_float(float x)25 esl_vmx_set_float(float x)
26 {
27   vector float v;
28 //  vector unsigned char p;
29 
30   v = vec_splats(x);
31 /*  v = vec_lde(0, &x);
32   p = vec_lvsl(0, &x);
33   v = vec_perm(v, v, p);
34   v = vec_splat(v, 0); */
35   return v;
36 }
37 
38 /* Function:  esl_vmx_set_s16()
39  * Synopsis:  Fills short vector with x.
40  *
41  * Purpose:   Sets all elements in the vector <signed short> to x.
42  */
43 static inline vector signed short
esl_vmx_set_s16(signed short x)44 esl_vmx_set_s16(signed short x)
45 {
46   vector signed short v;
47   //vector unsigned char p;
48   v = vec_splats(x);
49   /*v = vec_lde(0, &x);
50   p = vec_lvsl(0, &x);
51   v = vec_perm(v, v, p);
52   v = vec_splat(v, 0); */
53   return v;
54 }
55 
56 /* Function:  esl_vmx_set_u8()
57  * Synopsis:  Fills byte vector with x.
58  *
59  * Purpose:   Sets all elements in the vector <unsigned char> to x.
60  */
61 static inline vector unsigned char
esl_vmx_set_u8(unsigned char x)62 esl_vmx_set_u8(unsigned char x)
63 {
64   vector unsigned char v;
65   //vector unsigned char p;
66   v = vec_splats(x);
67 
68   /*v = vec_lde(0, &x);
69   p = vec_lvsl(0, &x);
70   v = vec_perm(v, v, p);
71   v = vec_splat(v, 0);*/
72   return v;
73 }
74 
75 /* Function:  esl_vmx_hsum_float()
76  * Synopsis:  Returns sum of all floats.
77  *
78  * Purpose:   Resturns the sum of all elements in the vector <float>.
79  */
80 static inline float
esl_vmx_hsum_float(vector float v)81 esl_vmx_hsum_float(vector float v)
82 {
83   float f;
84 
85   v = vec_add(v, vec_sld(v, v, 4));
86   v = vec_add(v, vec_sld(v, v, 8));
87   vec_ste(v, 0, &f);
88 
89   return f;
90 }
91 
92 /* Function:  esl_vmx_hsum_s16()
93  * Synopsis:  Returns sum of all shorts.
94  *
95  * Purpose:   Resturns the sum of all elements in the vector <signed short>.
96  */
97 static inline signed short
esl_vmx_hsum_s16(vector signed short v)98 esl_vmx_hsum_s16(vector signed short v)
99 {
100   signed short s;
101 
102   v = vec_add(v, vec_sld(v, v, 2));
103   v = vec_add(v, vec_sld(v, v, 4));
104   v = vec_add(v, vec_sld(v, v, 8));
105   vec_ste(v, 0, &s);
106 
107   return s;
108 }
109 
110 /* Function:  esl_vmx_hmax_float()
111  * Synopsis:  Returns max of all floats.
112  *
113  * Purpose:   Resturns the maximum element in the vector <float>.
114  */
115 static inline float
esl_vmx_hmax_float(vector float v)116 esl_vmx_hmax_float(vector float v)
117 {
118   float f;
119 
120   v = vec_max(v, vec_sld(v, v, 4));
121   v = vec_max(v, vec_sld(v, v, 8));
122   vec_ste(v, 0, &f);
123 
124   return f;
125 }
126 
127 /* Function:  esl_vmx_hmax_s16()
128  * Synopsis:  Returns max of all shorts.
129  *
130  * Purpose:   Resturns the maximum element in the vector <signed short>.
131  */
132 static inline signed short
esl_vmx_hmax_s16(vector signed short v)133 esl_vmx_hmax_s16(vector signed short v)
134 {
135   signed short s;
136 
137   v = vec_max(v, vec_sld(v, v, 2));
138   v = vec_max(v, vec_sld(v, v, 4));
139   v = vec_max(v, vec_sld(v, v, 8));
140   vec_ste(v, 0, &s);
141 
142   return s;
143 }
144 
145 /* Function:  esl_vmx_hmax_u8()
146  * Synopsis:  Returns max of all bytes.
147  *
148  * Purpose:   Resturns the maximum element in the vector <unsigned char>.
149  */
150 static inline unsigned char
esl_vmx_hmax_s8(vector signed char v)151 esl_vmx_hmax_s8(vector signed char v)
152 {
153   signed char s;
154 
155   v = vec_vmaxsb(v, vec_sld(v, v, 1));
156   v = vec_vmaxsb(v, vec_sld(v, v, 2));
157   v = vec_vmaxsb(v, vec_sld(v, v, 4));
158   v = vec_vmaxsb(v, vec_sld(v, v, 8));
159   vec_ste(v, 0, &s);
160 
161   return s;
162 }
163 
164 /* Function:  esl_vmx_rightshift_int8()
165  * Synopsis:  Shift int8 vector elements to the right, shifting -inf on
166  * Incept:    NPC, Thurs Jun  15  2017
167  *
168  * Purpose:   Given an int8 vector <{ a0 .. a16}>, and a mask <{-inf,
169  *            0*15 }> with the desired value of -inf in slot 0
170  *            (and zeros elsewhere), return <{ -inf, a0..a14 }>;
171  *            i.e. shift the values in <a> to the right, while
172  *            shifting $-\infty$ on.
173  *
174  *            By our convention, "right" and "left" refer to memory
175  *            order (low addresses on the left). On a little-endian
176  *            (x86) architecture, this is a left shift in the hardware
177  *            register.
178  *
179  *            This can be used both for signed (epi8) and unsigned
180  *            (epu8) int8 vectors.
181  *
182  * Xref:      HMMER's simdvec.md: on our left/right convention.
183  */
184 static inline vector signed char
esl_vmx_rightshift_int8(vector signed char a,vector signed char neginfmask)185 esl_vmx_rightshift_int8(vector signed char a, vector signed char neginfmask)
186 {
187   vector signed char v2 = vec_sld(a, neginfmask, 1);
188   return v2;
189 }
190 
191 
192 /* Function:  esl_vmx_rightshift_int16()
193  * Synopsis:  Shift int16 vector elements to the right, shifting -inf on
194  * Incept:    NPC, Thurs Jun  15  2017
195  *
196  * Purpose:   Same as <esl_vmx_rightshift_int8()> but for int16.
197  */
198 static inline vector short
esl_vmx_rightshift_int16(vector short a,vector short neginfmask)199 esl_vmx_rightshift_int16(vector short a, vector short neginfmask)
200 {
201   vector short v2 = vec_sld(a, neginfmask, 2);
202   return v2;
203 }
204 
205 /* Function:  esl_sse_rightshiftz_float()
206  * Synopsis:  Shift float vector elements to the right, shifting zero on.
207  *
208  * Purpose:   Same as <esl_sse_rightshift_int8()> but for floats,
209  *            and the value that is shifted on is a zero.
210  */
211 static inline vector float
esl_vmx_rightshiftz_float(vector float a)212 esl_vmx_rightshiftz_float(vector float a)
213 {
214   vector float v = {0.0, 0.0, 0.0, 0.0};
215   vector float v2 = vec_sld(a, v, 4);
216   return v2;
217 }
218 
219 /* Function:  esl_sse_leftshiftz_float()
220  * Synopsis:  Shift float vector elements to the left, shifting zero on.
221  *
222  * Purpose:   Same as <esl_sse_rightshift_float()> but leftwise: <[ a0 a1 a2
223  *            a3 ]> becomes <[ a1 a2 a3 0 ]>. Used in Backwards.
224  */
225 static inline vector float
esl_vmx_leftshiftz_float(vector float a)226 esl_vmx_leftshiftz_float(vector float a)
227 {
228    vector float v = {0.0, 0.0, 0.0, 0.0};
229   vector float v2 = vec_sld(v, a, 12);  // left-shifting the three high elements of a into a vector of zeroes
230   // gives the same result as right-shifting a by one element
231   return v2;
232 }
233 
234 
235 #endif /* eslENABLE_VMX */
236 #endif /*eslVMX_INCLUDED*/
237 
238