1 /* GStreamer
2 * Copyright (C) <2016> Wim Taymans <wim.taymans@gmail.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 static inline void
inner_product_gint16_full_1_neon(gint16 * o,const gint16 * a,const gint16 * b,gint len,const gint16 * icoeff,gint bstride)21 inner_product_gint16_full_1_neon (gint16 * o, const gint16 * a,
22 const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
23 {
24 uint32_t remainder = len % 16;
25 len = len - remainder;
26
27 asm volatile (" vmov.s32 q0, #0\n"
28 " cmp %[len], #0\n"
29 " beq 2f\n"
30 " vmov.s32 q1, #0\n"
31 "1:"
32 " vld1.16 {d16, d17, d18, d19}, [%[b]]!\n"
33 " vld1.16 {d20, d21, d22, d23}, [%[a]]!\n"
34 " subs %[len], %[len], #16\n"
35 " vmlal.s16 q0, d16, d20\n"
36 " vmlal.s16 q1, d17, d21\n"
37 " vmlal.s16 q0, d18, d22\n"
38 " vmlal.s16 q1, d19, d23\n"
39 " bne 1b\n"
40 " vadd.s32 q0, q0, q1\n"
41 "2:"
42 " cmp %[remainder], #0\n"
43 " beq 4f\n"
44 "3:"
45 " vld1.16 {d16}, [%[b]]!\n"
46 " vld1.16 {d20}, [%[a]]!\n"
47 " subs %[remainder], %[remainder], #4\n"
48 " vmlal.s16 q0, d16, d20\n"
49 " bgt 3b\n"
50 "4:"
51 " vadd.s32 d0, d0, d1\n"
52 " vpadd.s32 d0, d0, d0\n"
53 " vqrshrn.s32 d0, q0, #15\n"
54 " vst1.16 d0[0], [%[o]]\n"
55 : [a] "+r" (a), [b] "+r" (b),
56 [len] "+r" (len), [remainder] "+r" (remainder)
57 : [o] "r" (o)
58 : "cc", "q0", "q1",
59 "d16", "d17", "d18", "d19",
60 "d20", "d21", "d22", "d23");
61 }
62
63 static inline void
inner_product_gint16_linear_1_neon(gint16 * o,const gint16 * a,const gint16 * b,gint len,const gint16 * icoeff,gint bstride)64 inner_product_gint16_linear_1_neon (gint16 * o, const gint16 * a,
65 const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
66 {
67 uint32_t remainder = len % 16;
68 const gint16 *c[2] = {(gint16*)((gint8*)b + 0*bstride),
69 (gint16*)((gint8*)b + 1*bstride)};
70 len = len - remainder;
71
72 asm volatile (" vmov.s16 q0, #0\n"
73 " vmov.s16 q1, #0\n"
74 " cmp %[len], #0\n"
75 " beq 2f\n"
76 "1:"
77 " vld1.16 {d16, d17, d18, d19}, [%[c0]]!\n"
78 " vld1.16 {d20, d21, d22, d23}, [%[c1]]!\n"
79 " vld1.16 {d24, d25, d26, d27}, [%[a]]!\n"
80 " subs %[len], %[len], #16\n"
81 " vmlal.s16 q0, d16, d24\n"
82 " vmlal.s16 q1, d20, d24\n"
83 " vmlal.s16 q0, d17, d25\n"
84 " vmlal.s16 q1, d21, d25\n"
85 " vmlal.s16 q0, d18, d26\n"
86 " vmlal.s16 q1, d22, d26\n"
87 " vmlal.s16 q0, d19, d27\n"
88 " vmlal.s16 q1, d23, d27\n"
89 " bne 1b\n"
90 "2:"
91 " cmp %[remainder], #0\n"
92 " beq 4f\n"
93 "3:"
94 " vld1.16 {d16}, [%[c0]]!\n"
95 " vld1.16 {d20}, [%[c1]]!\n"
96 " vld1.16 {d24}, [%[a]]!\n"
97 " subs %[remainder], %[remainder], #4\n"
98 " vmlal.s16 q0, d16, d24\n"
99 " vmlal.s16 q1, d20, d24\n"
100 " bgt 3b\n"
101 "4:"
102 " vld2.16 {d20[], d21[]}, [%[ic]]\n"
103 " vshrn.s32 d0, q0, #15\n"
104 " vshrn.s32 d2, q1, #15\n"
105 " vmull.s16 q0, d0, d20\n"
106 " vmlal.s16 q0, d2, d21\n"
107 " vadd.s32 d0, d0, d1\n"
108 " vpadd.s32 d0, d0, d0\n"
109 " vqrshrn.s32 d0, q0, #15\n"
110 " vst1.16 d0[0], [%[o]]\n"
111 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
112 [len] "+r" (len), [remainder] "+r" (remainder)
113 : [o] "r" (o), [ic] "r" (icoeff)
114 : "cc", "q0", "q1",
115 "d16", "d17", "d18", "d19",
116 "d20", "d21", "d22", "d23",
117 "d24", "d25", "d26", "d27", "memory");
118 }
119
120 static inline void
inner_product_gint16_cubic_1_neon(gint16 * o,const gint16 * a,const gint16 * b,gint len,const gint16 * icoeff,gint bstride)121 inner_product_gint16_cubic_1_neon (gint16 * o, const gint16 * a,
122 const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
123 {
124 const gint16 *c[4] = {(gint16*)((gint8*)b + 0*bstride),
125 (gint16*)((gint8*)b + 1*bstride),
126 (gint16*)((gint8*)b + 2*bstride),
127 (gint16*)((gint8*)b + 3*bstride)};
128
129 asm volatile (" vmov.s32 q0, #0\n"
130 " vmov.s32 q1, #0\n"
131 " vmov.s32 q2, #0\n"
132 " vmov.s32 q3, #0\n"
133 " cmp %[len], #0\n"
134 " beq 2f\n"
135 "1:"
136 " vld1.16 {d16, d17}, [%[c0]]!\n"
137 " vld1.16 {d18, d19}, [%[c1]]!\n"
138 " vld1.16 {d20, d21}, [%[c2]]!\n"
139 " vld1.16 {d22, d23}, [%[c3]]!\n"
140 " vld1.16 {d24, d25}, [%[a]]!\n"
141 " subs %[len], %[len], #8\n"
142 " vmlal.s16 q0, d16, d24\n"
143 " vmlal.s16 q1, d18, d24\n"
144 " vmlal.s16 q2, d20, d24\n"
145 " vmlal.s16 q3, d22, d24\n"
146 " vmlal.s16 q0, d17, d25\n"
147 " vmlal.s16 q1, d19, d25\n"
148 " vmlal.s16 q2, d21, d25\n"
149 " vmlal.s16 q3, d23, d25\n"
150 " bne 1b\n"
151 "2:"
152 " vld4.16 {d20[], d21[], d22[], d23[]}, [%[ic]]\n"
153 " vshrn.s32 d0, q0, #15\n"
154 " vshrn.s32 d2, q1, #15\n"
155 " vshrn.s32 d4, q2, #15\n"
156 " vshrn.s32 d6, q3, #15\n"
157 " vmull.s16 q0, d0, d20\n"
158 " vmlal.s16 q0, d2, d21\n"
159 " vmlal.s16 q0, d4, d22\n"
160 " vmlal.s16 q0, d6, d23\n"
161 " vadd.s32 d0, d0, d1\n"
162 " vpadd.s32 d0, d0, d0\n"
163 " vqrshrn.s32 d0, q0, #15\n"
164 " vst1.16 d0[0], [%[o]]\n"
165 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
166 [c2] "+r" (c[2]), [c3] "+r" (c[3]), [len] "+r" (len)
167 : [o] "r" (o), [ic] "r" (icoeff)
168 : "cc", "q0", "q1", "q2", "q3",
169 "d16", "d17", "d18", "d19",
170 "d20", "d21", "d22", "d23",
171 "d24", "d25", "memory");
172 }
173
174 static inline void
interpolate_gint16_linear_neon(gpointer op,const gpointer ap,gint len,const gpointer icp,gint astride)175 interpolate_gint16_linear_neon (gpointer op, const gpointer ap,
176 gint len, const gpointer icp, gint astride)
177 {
178 gint16 *o = op, *a = ap, *ic = icp;
179 const gint16 *c[2] = {(gint16*)((gint8*)a + 0*astride),
180 (gint16*)((gint8*)a + 1*astride)};
181
182 asm volatile (" cmp %[len], #0\n"
183 " beq 2f\n"
184 " vld2.16 {d20[], d21[]}, [%[ic]]\n"
185 "1:"
186 " vld1.16 {d16, d17}, [%[c0]]!\n"
187 " vld1.16 {d18, d19}, [%[c1]]!\n"
188 " subs %[len], %[len], #8\n"
189 " vmull.s16 q0, d16, d20\n"
190 " vmull.s16 q1, d17, d20\n"
191 " vmlal.s16 q0, d18, d21\n"
192 " vmlal.s16 q1, d19, d21\n"
193 " vqrshrn.s32 d0, q0, #15\n"
194 " vqrshrn.s32 d1, q1, #15\n"
195 " vst1.16 {d0, d1}, [%[o]]!\n"
196 " bne 1b\n"
197 "2:"
198 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
199 [len] "+r" (len), [o] "+r" (o)
200 : [ic] "r" (ic)
201 : "cc", "q0", "q1",
202 "d16", "d17", "d18", "d19", "d20", "d21", "memory");
203 }
204
205 static inline void
interpolate_gint16_cubic_neon(gpointer op,const gpointer ap,gint len,const gpointer icp,gint astride)206 interpolate_gint16_cubic_neon (gpointer op, const gpointer ap,
207 gint len, const gpointer icp, gint astride)
208 {
209 gint16 *o = op, *a = ap, *ic = icp;
210 const gint16 *c[4] = {(gint16*)((gint8*)a + 0*astride),
211 (gint16*)((gint8*)a + 1*astride),
212 (gint16*)((gint8*)a + 2*astride),
213 (gint16*)((gint8*)a + 3*astride)};
214
215 asm volatile (" cmp %[len], #0\n"
216 " beq 2f\n"
217 " vld4.16 {d24[], d25[], d26[], d27[]}, [%[ic]]\n"
218 "1:"
219 " vld1.16 {d16, d17}, [%[c0]]!\n"
220 " vld1.16 {d18, d19}, [%[c1]]!\n"
221 " vld1.16 {d20, d21}, [%[c2]]!\n"
222 " vld1.16 {d22, d23}, [%[c3]]!\n"
223 " subs %[len], %[len], #8\n"
224 " vmull.s16 q0, d16, d24\n"
225 " vmull.s16 q1, d17, d24\n"
226 " vmlal.s16 q0, d18, d25\n"
227 " vmlal.s16 q1, d19, d25\n"
228 " vmlal.s16 q0, d20, d26\n"
229 " vmlal.s16 q1, d21, d26\n"
230 " vmlal.s16 q0, d22, d27\n"
231 " vmlal.s16 q1, d23, d27\n"
232 " vqrshrn.s32 d0, q0, #15\n"
233 " vqrshrn.s32 d1, q1, #15\n"
234 " vst1.16 {d0, d1}, [%[o]]!\n"
235 " bne 1b\n"
236 "2:"
237 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]), [c2] "+r" (c[2]), [c3] "+r" (c[3]),
238 [len] "+r" (len), [o] "+r" (o)
239 : [ic] "r" (ic)
240 : "cc", "q0", "q1",
241 "d16", "d17", "d18", "d19", "d20", "d21", "d22",
242 "d23", "d24", "d25", "d26", "d27", "memory");
243 }
244
245 static inline void
inner_product_gint32_full_1_neon(gint32 * o,const gint32 * a,const gint32 * b,gint len,const gint32 * icoeff,gint bstride)246 inner_product_gint32_full_1_neon (gint32 * o, const gint32 * a,
247 const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
248 {
249 uint32_t remainder = len % 8;
250 len = len - remainder;
251
252 asm volatile (" vmov.s64 q0, #0\n"
253 " cmp %[len], #0\n"
254 " beq 2f\n"
255 " vmov.s64 q1, #0\n"
256 "1:"
257 " vld1.32 {d16, d17, d18, d19}, [%[b]]!\n"
258 " vld1.32 {d20, d21, d22, d23}, [%[a]]!\n"
259 " subs %[len], %[len], #8\n"
260 " vmlal.s32 q0, d16, d20\n"
261 " vmlal.s32 q1, d17, d21\n"
262 " vmlal.s32 q0, d18, d22\n"
263 " vmlal.s32 q1, d19, d23\n"
264 " bne 1b\n"
265 " vadd.s64 q0, q0, q1\n"
266 "2:"
267 " cmp %[remainder], #0\n"
268 " beq 4f\n"
269 "3:"
270 " vld1.32 {d16, d17}, [%[b]]!\n"
271 " vld1.32 {d20, d21}, [%[a]]!\n"
272 " subs %[remainder], %[remainder], #4\n"
273 " vmlal.s32 q0, d16, d20\n"
274 " vmlal.s32 q0, d17, d21\n"
275 " bgt 3b\n"
276 "4:"
277 " vadd.s64 d0, d0, d1\n"
278 " vqrshrn.s64 d0, q0, #31\n"
279 " vst1.32 d0[0], [%[o]]\n"
280 : [a] "+r" (a), [b] "+r" (b),
281 [len] "+r" (len), [remainder] "+r" (remainder)
282 : [o] "r" (o)
283 : "cc", "q0", "q1",
284 "d16", "d17", "d18", "d19",
285 "d20", "d21", "d22", "d23");
286 }
287
288 static inline void
inner_product_gint32_linear_1_neon(gint32 * o,const gint32 * a,const gint32 * b,gint len,const gint32 * icoeff,gint bstride)289 inner_product_gint32_linear_1_neon (gint32 * o, const gint32 * a,
290 const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
291 {
292 const gint32 *c[2] = {(gint32*)((gint8*)b + 0*bstride),
293 (gint32*)((gint8*)b + 1*bstride)};
294
295 asm volatile (" vmov.s64 q0, #0\n"
296 " vmov.s64 q1, #0\n"
297 " cmp %[len], #0\n"
298 " beq 2f\n"
299 "1:"
300 " vld1.32 {d16, d17, d18, d19}, [%[c0]]!\n"
301 " vld1.32 {d20, d21, d22, d23}, [%[c1]]!\n"
302 " vld1.32 {d24, d25, d26, d27}, [%[a]]!\n"
303 " subs %[len], %[len], #8\n"
304 " vmlal.s32 q0, d16, d24\n"
305 " vmlal.s32 q1, d20, d24\n"
306 " vmlal.s32 q0, d17, d25\n"
307 " vmlal.s32 q1, d21, d25\n"
308 " vmlal.s32 q0, d18, d26\n"
309 " vmlal.s32 q1, d22, d26\n"
310 " vmlal.s32 q0, d19, d27\n"
311 " vmlal.s32 q1, d23, d27\n"
312 " bne 1b\n"
313 "2:"
314 " vld2.32 {d20[], d21[]}, [%[ic]]\n"
315 " vshrn.s64 d0, q0, #31\n"
316 " vshrn.s64 d2, q1, #31\n"
317 " vmull.s32 q0, d0, d20\n"
318 " vmlal.s32 q0, d2, d21\n"
319 " vadd.s64 d0, d0, d1\n"
320 " vqrshrn.s64 d0, q0, #31\n"
321 " vst1.32 d0[0], [%[o]]\n"
322 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
323 [len] "+r" (len)
324 : [o] "r" (o), [ic] "r" (icoeff)
325 : "cc", "q0", "q1",
326 "d16", "d17", "d18", "d19",
327 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "memory");
328 }
329
330 static inline void
inner_product_gint32_cubic_1_neon(gint32 * o,const gint32 * a,const gint32 * b,gint len,const gint32 * icoeff,gint bstride)331 inner_product_gint32_cubic_1_neon (gint32 * o, const gint32 * a,
332 const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
333 {
334 const gint32 *c[4] = {(gint32*)((gint8*)b + 0*bstride),
335 (gint32*)((gint8*)b + 1*bstride),
336 (gint32*)((gint8*)b + 2*bstride),
337 (gint32*)((gint8*)b + 3*bstride)};
338
339 asm volatile (" vmov.s64 q0, #0\n"
340 " vmov.s64 q1, #0\n"
341 " vmov.s64 q2, #0\n"
342 " vmov.s64 q3, #0\n"
343 " cmp %[len], #0\n"
344 " beq 2f\n"
345 "1:"
346 " vld1.32 {d16, d17}, [%[c0]]!\n"
347 " vld1.32 {d18, d19}, [%[c1]]!\n"
348 " vld1.32 {d20, d21}, [%[c2]]!\n"
349 " vld1.32 {d22, d23}, [%[c3]]!\n"
350 " vld1.32 {d24, d25}, [%[a]]!\n"
351 " subs %[len], %[len], #4\n"
352 " vmlal.s32 q0, d16, d24\n"
353 " vmlal.s32 q1, d18, d24\n"
354 " vmlal.s32 q2, d20, d24\n"
355 " vmlal.s32 q3, d22, d24\n"
356 " vmlal.s32 q0, d17, d25\n"
357 " vmlal.s32 q1, d19, d25\n"
358 " vmlal.s32 q2, d21, d25\n"
359 " vmlal.s32 q3, d23, d25\n"
360 " bne 1b\n"
361 "2:"
362 " vld4.32 {d20[], d21[], d22[], d23[]}, [%[ic]]\n"
363 " vshrn.s64 d0, q0, #31\n"
364 " vshrn.s64 d2, q1, #31\n"
365 " vshrn.s64 d4, q2, #31\n"
366 " vshrn.s64 d6, q3, #31\n"
367 " vmull.s32 q0, d0, d20\n"
368 " vmlal.s32 q0, d2, d21\n"
369 " vmlal.s32 q0, d4, d22\n"
370 " vmlal.s32 q0, d6, d23\n"
371 " vadd.s64 d0, d0, d1\n"
372 " vqrshrn.s64 d0, q0, #31\n"
373 " vst1.32 d0[0], [%[o]]\n"
374 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
375 [c2] "+r" (c[2]), [c3] "+r" (c[3]), [len] "+r" (len)
376 : [o] "r" (o), [ic] "r" (icoeff)
377 : "cc", "q0", "q1", "q2", "q3",
378 "d16", "d17", "d18", "d19",
379 "d20", "d21", "d22", "d23", "d24", "d25", "memory");
380 }
381
382 static inline void
interpolate_gint32_linear_neon(gpointer op,const gpointer ap,gint len,const gpointer icp,gint astride)383 interpolate_gint32_linear_neon (gpointer op, const gpointer ap,
384 gint len, const gpointer icp, gint astride)
385 {
386 gint32 *o = op, *a = ap, *ic = icp;
387 const gint32 *c[2] = {(gint32*)((gint8*)a + 0*astride),
388 (gint32*)((gint8*)a + 1*astride)};
389
390 asm volatile (" cmp %[len], #0\n"
391 " beq 2f\n"
392 " vld2.32 {d24[], d25[]}, [%[ic]]!\n"
393 "1:"
394 " vld1.32 {d16, d17, d18, d19}, [%[c0]]!\n"
395 " vld1.32 {d20, d21, d22, d23}, [%[c1]]!\n"
396 " subs %[len], %[len], #8\n"
397 " vmull.s32 q0, d16, d24\n"
398 " vmull.s32 q1, d17, d24\n"
399 " vmull.s32 q2, d18, d24\n"
400 " vmull.s32 q3, d19, d24\n"
401 " vmlal.s32 q0, d20, d25\n"
402 " vmlal.s32 q1, d21, d25\n"
403 " vmlal.s32 q2, d22, d25\n"
404 " vmlal.s32 q3, d23, d25\n"
405 " vqrshrn.s64 d0, q0, #31\n"
406 " vqrshrn.s64 d1, q1, #31\n"
407 " vqrshrn.s64 d2, q2, #31\n"
408 " vqrshrn.s64 d3, q3, #31\n"
409 " vst1.32 {d0, d1, d2, d3}, [%[o]]!\n"
410 " bne 1b\n"
411 "2:"
412 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
413 [len] "+r" (len), [o] "+r" (o)
414 : [ic] "r" (ic)
415 : "cc", "q0", "q1", "q2", "q3",
416 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "memory");
417 }
418
419 static inline void
interpolate_gint32_cubic_neon(gpointer op,const gpointer ap,gint len,const gpointer icp,gint astride)420 interpolate_gint32_cubic_neon (gpointer op, const gpointer ap,
421 gint len, const gpointer icp, gint astride)
422 {
423 gint32 *o = op, *a = ap, *ic = icp;
424 const gint32 *c[4] = {(gint32*)((gint8*)a + 0*astride),
425 (gint32*)((gint8*)a + 1*astride),
426 (gint32*)((gint8*)a + 2*astride),
427 (gint32*)((gint8*)a + 3*astride)};
428
429 asm volatile (" cmp %[len], #0\n"
430 " beq 2f\n"
431 " vld4.32 {d24[], d25[], d26[], d27[]}, [%[ic]]!\n"
432 "1:"
433 " vld1.32 {d16, d17}, [%[c0]]!\n"
434 " vld1.32 {d18, d19}, [%[c1]]!\n"
435 " vld1.32 {d20, d21}, [%[c2]]!\n"
436 " vld1.32 {d22, d23}, [%[c3]]!\n"
437 " subs %[len], %[len], #4\n"
438 " vmull.s32 q0, d16, d24\n"
439 " vmull.s32 q1, d17, d24\n"
440 " vmlal.s32 q0, d18, d25\n"
441 " vmlal.s32 q1, d19, d25\n"
442 " vmlal.s32 q0, d20, d26\n"
443 " vmlal.s32 q1, d21, d26\n"
444 " vmlal.s32 q0, d22, d27\n"
445 " vmlal.s32 q1, d23, d27\n"
446 " vqrshrn.s64 d0, q0, #31\n"
447 " vqrshrn.s64 d1, q1, #31\n"
448 " vst1.32 {d0, d1}, [%[o]]!\n"
449 " bne 1b\n"
450 "2:"
451 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
452 [c2] "+r" (c[2]), [c3] "+r" (c[3]), [len] "+r" (len), [o] "+r" (o)
453 : [ic] "r" (ic)
454 : "cc", "q0", "q1",
455 "d16", "d17", "d18", "d19", "d20",
456 "d21", "d22", "d23", "d24", "d25", "d26", "d27", "memory");
457 }
458
459 static inline void
inner_product_gfloat_full_1_neon(gfloat * o,const gfloat * a,const gfloat * b,gint len,const gfloat * icoeff,gint bstride)460 inner_product_gfloat_full_1_neon (gfloat * o, const gfloat * a,
461 const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
462 {
463 uint32_t remainder = len % 16;
464 len = len - remainder;
465
466 asm volatile (" vmov.f32 q0, #0.0\n"
467 " cmp %[len], #0\n"
468 " beq 2f\n"
469 " vmov.f32 q1, #0.0\n"
470 "1:"
471 " vld1.32 {q4, q5}, [%[b]]!\n"
472 " vld1.32 {q8, q9}, [%[a]]!\n"
473 " vld1.32 {q6, q7}, [%[b]]!\n"
474 " vld1.32 {q10, q11}, [%[a]]!\n"
475 " subs %[len], %[len], #16\n"
476 " vmla.f32 q0, q4, q8\n"
477 " vmla.f32 q1, q5, q9\n"
478 " vmla.f32 q0, q6, q10\n"
479 " vmla.f32 q1, q7, q11\n"
480 " bne 1b\n"
481 " vadd.f32 q0, q0, q1\n"
482 "2:"
483 " cmp %[remainder], #0\n"
484 " beq 4f\n"
485 "3:"
486 " vld1.32 {q6}, [%[b]]!\n"
487 " vld1.32 {q10}, [%[a]]!\n"
488 " subs %[remainder], %[remainder], #4\n"
489 " vmla.f32 q0, q6, q10\n"
490 " bgt 3b\n"
491 "4:"
492 " vadd.f32 d0, d0, d1\n"
493 " vpadd.f32 d0, d0, d0\n"
494 " vst1.32 d0[0], [%[o]]\n"
495 : [a] "+r" (a), [b] "+r" (b),
496 [len] "+r" (len), [remainder] "+r" (remainder)
497 : [o] "r" (o)
498 : "cc", "q0", "q1", "q4", "q5", "q6", "q7", "q8",
499 "q9", "q10", "q11");
500 }
501
502 static inline void
inner_product_gfloat_linear_1_neon(gfloat * o,const gfloat * a,const gfloat * b,gint len,const gfloat * icoeff,gint bstride)503 inner_product_gfloat_linear_1_neon (gfloat * o, const gfloat * a,
504 const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
505 {
506 const gfloat *c[2] = {(gfloat*)((gint8*)b + 0*bstride),
507 (gfloat*)((gint8*)b + 1*bstride)};
508
509 asm volatile (" vmov.f32 q0, #0.0\n"
510 " vmov.f32 q1, #0.0\n"
511 " cmp %[len], #0\n"
512 " beq 2f\n"
513 "1:"
514 " vld1.32 {q8, q9}, [%[c0]]!\n"
515 " vld1.32 {q10, q11}, [%[c1]]!\n"
516 " vld1.32 {q12, q13}, [%[a]]!\n"
517 " subs %[len], %[len], #8\n"
518 " vmla.f32 q0, q8, q12\n"
519 " vmla.f32 q1, q10, q12\n"
520 " vmla.f32 q0, q9, q13\n"
521 " vmla.f32 q1, q11, q13\n"
522 " bne 1b\n"
523 "2:"
524 " vld2.32 {d20[], d21[]}, [%[ic]]\n"
525 " vmul.f32 d0, d0, d20\n"
526 " vmla.f32 d0, d1, d20\n"
527 " vmla.f32 d0, d2, d21\n"
528 " vmla.f32 d0, d3, d21\n"
529 " vpadd.f32 d0, d0, d0\n"
530 " vst1.32 d0[0], [%[o]]\n"
531 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
532 [len] "+r" (len)
533 : [o] "r" (o), [ic] "r" (icoeff)
534 : "cc", "q0", "q1",
535 "q8", "q9", "q10", "q11", "q12", "q13", "memory");
536 }
537
538 static inline void
inner_product_gfloat_cubic_1_neon(gfloat * o,const gfloat * a,const gfloat * b,gint len,const gfloat * icoeff,gint bstride)539 inner_product_gfloat_cubic_1_neon (gfloat * o, const gfloat * a,
540 const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
541 {
542 const gfloat *c[4] = {(gfloat*)((gint8*)b + 0*bstride),
543 (gfloat*)((gint8*)b + 1*bstride),
544 (gfloat*)((gint8*)b + 2*bstride),
545 (gfloat*)((gint8*)b + 3*bstride)};
546
547 asm volatile (" vmov.f32 q0, #0.0\n"
548 " vmov.f32 q1, #0.0\n"
549 " vmov.f32 q2, #0.0\n"
550 " vmov.f32 q3, #0.0\n"
551 " cmp %[len], #0\n"
552 " beq 2f\n"
553 "1:"
554 " vld1.32 {q8}, [%[c0]]!\n"
555 " vld1.32 {q9}, [%[c1]]!\n"
556 " vld1.32 {q10}, [%[c2]]!\n"
557 " vld1.32 {q11}, [%[c3]]!\n"
558 " vld1.32 {q12}, [%[a]]!\n"
559 " subs %[len], %[len], #4\n"
560 " vmla.f32 q0, q8, q12\n"
561 " vmla.f32 q1, q9, q12\n"
562 " vmla.f32 q2, q10, q12\n"
563 " vmla.f32 q3, q11, q12\n"
564 " bne 1b\n"
565 "2:"
566 " vld4.32 {d20[], d21[], d22[], d23[]}, [%[ic]]\n"
567 " vmul.f32 d0, d0, d20\n"
568 " vmla.f32 d0, d1, d20\n"
569 " vmla.f32 d0, d2, d21\n"
570 " vmla.f32 d0, d3, d21\n"
571 " vmla.f32 d0, d4, d22\n"
572 " vmla.f32 d0, d5, d22\n"
573 " vmla.f32 d0, d6, d23\n"
574 " vmla.f32 d0, d7, d23\n"
575 " vpadd.f32 d0, d0, d0\n"
576 " vst1.32 d0[0], [%[o]]\n"
577 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
578 [c2] "+r" (c[2]), [c3] "+r" (c[3]), [len] "+r" (len), [o] "+r" (o)
579 : [ic] "r" (icoeff)
580 : "cc", "q0", "q1", "q2", "q3",
581 "q8", "q9", "q10", "q11", "q12", "memory");
582 }
583
584 static inline void
interpolate_gfloat_linear_neon(gpointer op,const gpointer ap,gint len,const gpointer icp,gint astride)585 interpolate_gfloat_linear_neon (gpointer op, const gpointer ap,
586 gint len, const gpointer icp, gint astride)
587 {
588 gfloat *o = op, *a = ap, *ic = icp;
589 const gfloat *c[2] = {(gfloat*)((gint8*)a + 0*astride),
590 (gfloat*)((gint8*)a + 1*astride)};
591
592 asm volatile (" cmp %[len], #0\n"
593 " beq 2f\n"
594 " vld2.32 {d24[], d26[]}, [%[ic]]!\n"
595 " vmov.32 d25, d24\n"
596 " vmov.32 d27, d26\n"
597 "1:"
598 " vld1.32 {q8, q9}, [%[c0]]!\n"
599 " vld1.32 {q10, q11}, [%[c1]]!\n"
600 " subs %[len], %[len], #8\n"
601 " vmul.f32 q0, q8, q12\n"
602 " vmul.f32 q1, q9, q12\n"
603 " vmla.f32 q0, q10, q13\n"
604 " vmla.f32 q1, q11, q13\n"
605 " vst1.32 {q0, q1}, [%[o]]!\n"
606 " bne 1b\n"
607 "2:"
608 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
609 [len] "+r" (len), [o] "+r" (o)
610 : [ic] "r" (ic)
611 : "cc", "q0", "q1", "q8", "q9",
612 "q10", "q11", "q12", "q13", "memory");
613 }
614
615 static inline void
interpolate_gfloat_cubic_neon(gpointer op,const gpointer ap,gint len,const gpointer icp,gint astride)616 interpolate_gfloat_cubic_neon (gpointer op, const gpointer ap,
617 gint len, const gpointer icp, gint astride)
618 {
619 gfloat *o = op, *a = ap, *ic = icp;
620 const gfloat *c[4] = {(gfloat*)((gint8*)a + 0*astride),
621 (gfloat*)((gint8*)a + 1*astride),
622 (gfloat*)((gint8*)a + 2*astride),
623 (gfloat*)((gint8*)a + 3*astride)};
624
625 asm volatile (" cmp %[len], #0\n"
626 " beq 2f\n"
627 " vld4.32 {d24[], d26[], d28[], d30[]}, [%[ic]]!\n"
628 " vmov.32 d25, d24\n"
629 " vmov.32 d27, d26\n"
630 " vmov.32 d29, d28\n"
631 " vmov.32 d31, d30\n"
632 "1:"
633 " vld1.32 {q8}, [%[c0]]!\n"
634 " vld1.32 {q9}, [%[c1]]!\n"
635 " vld1.32 {q10}, [%[c2]]!\n"
636 " vld1.32 {q11}, [%[c3]]!\n"
637 " subs %[len], %[len], #4\n"
638 " vmul.f32 q0, q8, q12\n"
639 " vmla.f32 q0, q9, q13\n"
640 " vmla.f32 q0, q10, q14\n"
641 " vmla.f32 q0, q11, q15\n"
642 " vst1.32 {q0}, [%[o]]!\n"
643 " bne 1b\n"
644 "2:"
645 : [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
646 [c2] "+r" (c[2]), [c3] "+r" (c[3]),
647 [len] "+r" (len), [o] "+r" (o)
648 : [ic] "r" (ic)
649 : "cc", "q0", "q8", "q9",
650 "q10", "q11", "q12", "q13", "q14", "q15", "memory");
651 }
652
653 MAKE_RESAMPLE_FUNC_STATIC (gint16, full, 1, neon);
654 MAKE_RESAMPLE_FUNC_STATIC (gint16, linear, 1, neon);
655 MAKE_RESAMPLE_FUNC_STATIC (gint16, cubic, 1, neon);
656
657 MAKE_RESAMPLE_FUNC_STATIC (gint32, full, 1, neon);
658 MAKE_RESAMPLE_FUNC_STATIC (gint32, linear, 1, neon);
659 MAKE_RESAMPLE_FUNC_STATIC (gint32, cubic, 1, neon);
660
661 MAKE_RESAMPLE_FUNC_STATIC (gfloat, full, 1, neon);
662 MAKE_RESAMPLE_FUNC_STATIC (gfloat, linear, 1, neon);
663 MAKE_RESAMPLE_FUNC_STATIC (gfloat, cubic, 1, neon);
664
665 static void
audio_resampler_check_neon(const gchar * option)666 audio_resampler_check_neon (const gchar *option)
667 {
668 if (!strcmp (option, "neon")) {
669 GST_DEBUG ("enable NEON optimisations");
670 resample_gint16_full_1 = resample_gint16_full_1_neon;
671 resample_gint16_linear_1 = resample_gint16_linear_1_neon;
672 resample_gint16_cubic_1 = resample_gint16_cubic_1_neon;
673
674 interpolate_gint16_linear = interpolate_gint16_linear_neon;
675 interpolate_gint16_cubic = interpolate_gint16_cubic_neon;
676
677 resample_gint32_full_1 = resample_gint32_full_1_neon;
678 resample_gint32_linear_1 = resample_gint32_linear_1_neon;
679 resample_gint32_cubic_1 = resample_gint32_cubic_1_neon;
680
681 interpolate_gint32_linear = interpolate_gint32_linear_neon;
682 interpolate_gint32_cubic = interpolate_gint32_cubic_neon;
683
684 resample_gfloat_full_1 = resample_gfloat_full_1_neon;
685 resample_gfloat_linear_1 = resample_gfloat_linear_1_neon;
686 resample_gfloat_cubic_1 = resample_gfloat_cubic_1_neon;
687
688 interpolate_gfloat_linear = interpolate_gfloat_linear_neon;
689 interpolate_gfloat_cubic = interpolate_gfloat_cubic_neon;
690 }
691 }
692