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