mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 02:30:35 +00:00
0c955c16ce
If the remainder is not evenly divisable by 4, we'd miss the check for zero and continue the loop until crashing. Change the branch to take into account negatives as well. This more closely matches the SSE loop.
691 lines
30 KiB
C
691 lines
30 KiB
C
/* GStreamer
|
|
* Copyright (C) <2016> Wim Taymans <wim.taymans@gmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
static inline void
|
|
inner_product_gint16_full_1_neon (gint16 * o, const gint16 * a,
|
|
const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
|
|
{
|
|
uint32_t remainder = len % 16;
|
|
len = len - remainder;
|
|
|
|
asm volatile (" vmov.s32 q0, #0\n"
|
|
" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
" vmov.s32 q1, #0\n"
|
|
"1:"
|
|
" vld1.16 {d16, d17, d18, d19}, [%[b]]!\n"
|
|
" vld1.16 {d20, d21, d22, d23}, [%[a]]!\n"
|
|
" subs %[len], %[len], #16\n"
|
|
" vmlal.s16 q0, d16, d20\n"
|
|
" vmlal.s16 q1, d17, d21\n"
|
|
" vmlal.s16 q0, d18, d22\n"
|
|
" vmlal.s16 q1, d19, d23\n"
|
|
" bne 1b\n"
|
|
" vadd.s32 q0, q0, q1\n"
|
|
"2:"
|
|
" cmp %[remainder], #0\n"
|
|
" beq 4f\n"
|
|
"3:"
|
|
" vld1.16 {d16}, [%[b]]!\n"
|
|
" vld1.16 {d20}, [%[a]]!\n"
|
|
" subs %[remainder], %[remainder], #4\n"
|
|
" vmlal.s16 q0, d16, d20\n"
|
|
" bgt 3b\n"
|
|
"4:"
|
|
" vadd.s32 d0, d0, d1\n"
|
|
" vpadd.s32 d0, d0, d0\n"
|
|
" vqrshrn.s32 d0, q0, #15\n"
|
|
" vst1.16 d0[0], [%[o]]\n"
|
|
: [a] "+r" (a), [b] "+r" (b),
|
|
[len] "+r" (len), [remainder] "+r" (remainder)
|
|
: [o] "r" (o)
|
|
: "cc", "q0", "q1",
|
|
"d16", "d17", "d18", "d19",
|
|
"d20", "d21", "d22", "d23");
|
|
}
|
|
|
|
static inline void
|
|
inner_product_gint16_linear_1_neon (gint16 * o, const gint16 * a,
|
|
const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
|
|
{
|
|
uint32_t remainder = len % 16;
|
|
const gint16 *c[2] = {(gint16*)((gint8*)b + 0*bstride),
|
|
(gint16*)((gint8*)b + 1*bstride)};
|
|
len = len - remainder;
|
|
|
|
asm volatile (" vmov.s16 q0, #0\n"
|
|
" vmov.s16 q1, #0\n"
|
|
" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
"1:"
|
|
" vld1.16 {d16, d17, d18, d19}, [%[c0]]!\n"
|
|
" vld1.16 {d20, d21, d22, d23}, [%[c1]]!\n"
|
|
" vld1.16 {d24, d25, d26, d27}, [%[a]]!\n"
|
|
" subs %[len], %[len], #16\n"
|
|
" vmlal.s16 q0, d16, d24\n"
|
|
" vmlal.s16 q1, d20, d24\n"
|
|
" vmlal.s16 q0, d17, d25\n"
|
|
" vmlal.s16 q1, d21, d25\n"
|
|
" vmlal.s16 q0, d18, d26\n"
|
|
" vmlal.s16 q1, d22, d26\n"
|
|
" vmlal.s16 q0, d19, d27\n"
|
|
" vmlal.s16 q1, d23, d27\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
" cmp %[remainder], #0\n"
|
|
" beq 4f\n"
|
|
"3:"
|
|
" vld1.16 {d16}, [%[c0]]!\n"
|
|
" vld1.16 {d20}, [%[c1]]!\n"
|
|
" vld1.16 {d24}, [%[a]]!\n"
|
|
" subs %[remainder], %[remainder], #4\n"
|
|
" vmlal.s16 q0, d16, d24\n"
|
|
" vmlal.s16 q1, d20, d24\n"
|
|
" bgt 3b\n"
|
|
"4:"
|
|
" vld2.16 {d20[], d21[]}, [%[ic]]\n"
|
|
" vshrn.s32 d0, q0, #15\n"
|
|
" vshrn.s32 d2, q1, #15\n"
|
|
" vmull.s16 q0, d0, d20\n"
|
|
" vmlal.s16 q0, d2, d21\n"
|
|
" vadd.s32 d0, d0, d1\n"
|
|
" vpadd.s32 d0, d0, d0\n"
|
|
" vqrshrn.s32 d0, q0, #15\n"
|
|
" vst1.16 d0[0], [%[o]]\n"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[len] "+r" (len), [remainder] "+r" (remainder)
|
|
: [o] "r" (o), [ic] "r" (icoeff)
|
|
: "cc", "q0", "q1",
|
|
"d16", "d17", "d18", "d19",
|
|
"d20", "d21", "d22", "d23",
|
|
"d24", "d25", "d26", "d27", "memory");
|
|
}
|
|
|
|
static inline void
|
|
inner_product_gint16_cubic_1_neon (gint16 * o, const gint16 * a,
|
|
const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
|
|
{
|
|
const gint16 *c[4] = {(gint16*)((gint8*)b + 0*bstride),
|
|
(gint16*)((gint8*)b + 1*bstride),
|
|
(gint16*)((gint8*)b + 2*bstride),
|
|
(gint16*)((gint8*)b + 3*bstride)};
|
|
|
|
asm volatile (" vmov.s32 q0, #0\n"
|
|
" vmov.s32 q1, #0\n"
|
|
" vmov.s32 q2, #0\n"
|
|
" vmov.s32 q3, #0\n"
|
|
" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
"1:"
|
|
" vld1.16 {d16, d17}, [%[c0]]!\n"
|
|
" vld1.16 {d18, d19}, [%[c1]]!\n"
|
|
" vld1.16 {d20, d21}, [%[c2]]!\n"
|
|
" vld1.16 {d22, d23}, [%[c3]]!\n"
|
|
" vld1.16 {d24, d25}, [%[a]]!\n"
|
|
" subs %[len], %[len], #8\n"
|
|
" vmlal.s16 q0, d16, d24\n"
|
|
" vmlal.s16 q1, d18, d24\n"
|
|
" vmlal.s16 q2, d20, d24\n"
|
|
" vmlal.s16 q3, d22, d24\n"
|
|
" vmlal.s16 q0, d17, d25\n"
|
|
" vmlal.s16 q1, d19, d25\n"
|
|
" vmlal.s16 q2, d21, d25\n"
|
|
" vmlal.s16 q3, d23, d25\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
" vld4.16 {d20[], d21[], d22[], d23[]}, [%[ic]]\n"
|
|
" vshrn.s32 d0, q0, #15\n"
|
|
" vshrn.s32 d2, q1, #15\n"
|
|
" vshrn.s32 d4, q2, #15\n"
|
|
" vshrn.s32 d6, q3, #15\n"
|
|
" vmull.s16 q0, d0, d20\n"
|
|
" vmlal.s16 q0, d2, d21\n"
|
|
" vmlal.s16 q0, d4, d22\n"
|
|
" vmlal.s16 q0, d6, d23\n"
|
|
" vadd.s32 d0, d0, d1\n"
|
|
" vpadd.s32 d0, d0, d0\n"
|
|
" vqrshrn.s32 d0, q0, #15\n"
|
|
" vst1.16 d0[0], [%[o]]\n"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[c2] "+r" (c[2]), [c3] "+r" (c[3]), [len] "+r" (len)
|
|
: [o] "r" (o), [ic] "r" (icoeff)
|
|
: "cc", "q0", "q1", "q2", "q3",
|
|
"d16", "d17", "d18", "d19",
|
|
"d20", "d21", "d22", "d23",
|
|
"d24", "d25", "memory");
|
|
}
|
|
|
|
static inline void
|
|
interpolate_gint16_linear_neon (gpointer op, const gpointer ap,
|
|
gint len, const gpointer icp, gint astride)
|
|
{
|
|
gint16 *o = op, *a = ap, *ic = icp;
|
|
const gint16 *c[2] = {(gint16*)((gint8*)a + 0*astride),
|
|
(gint16*)((gint8*)a + 1*astride)};
|
|
|
|
asm volatile (" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
" vld2.16 {d20[], d21[]}, [%[ic]]\n"
|
|
"1:"
|
|
" vld1.16 {d16, d17}, [%[c0]]!\n"
|
|
" vld1.16 {d18, d19}, [%[c1]]!\n"
|
|
" subs %[len], %[len], #8\n"
|
|
" vmull.s16 q0, d16, d20\n"
|
|
" vmull.s16 q1, d17, d20\n"
|
|
" vmlal.s16 q0, d18, d21\n"
|
|
" vmlal.s16 q1, d19, d21\n"
|
|
" vqrshrn.s32 d0, q0, #15\n"
|
|
" vqrshrn.s32 d1, q1, #15\n"
|
|
" vst1.16 {d0, d1}, [%[o]]!\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[len] "+r" (len), [o] "+r" (o)
|
|
: [ic] "r" (ic)
|
|
: "cc", "q0", "q1",
|
|
"d16", "d17", "d18", "d19", "d20", "d21", "memory");
|
|
}
|
|
|
|
static inline void
|
|
interpolate_gint16_cubic_neon (gpointer op, const gpointer ap,
|
|
gint len, const gpointer icp, gint astride)
|
|
{
|
|
gint16 *o = op, *a = ap, *ic = icp;
|
|
const gint16 *c[4] = {(gint16*)((gint8*)a + 0*astride),
|
|
(gint16*)((gint8*)a + 1*astride),
|
|
(gint16*)((gint8*)a + 2*astride),
|
|
(gint16*)((gint8*)a + 3*astride)};
|
|
|
|
asm volatile (" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
" vld4.16 {d24[], d25[], d26[], d27[]}, [%[ic]]\n"
|
|
"1:"
|
|
" vld1.16 {d16, d17}, [%[c0]]!\n"
|
|
" vld1.16 {d18, d19}, [%[c1]]!\n"
|
|
" vld1.16 {d20, d21}, [%[c2]]!\n"
|
|
" vld1.16 {d22, d23}, [%[c3]]!\n"
|
|
" subs %[len], %[len], #8\n"
|
|
" vmull.s16 q0, d16, d24\n"
|
|
" vmull.s16 q1, d17, d24\n"
|
|
" vmlal.s16 q0, d18, d25\n"
|
|
" vmlal.s16 q1, d19, d25\n"
|
|
" vmlal.s16 q0, d20, d26\n"
|
|
" vmlal.s16 q1, d21, d26\n"
|
|
" vmlal.s16 q0, d22, d27\n"
|
|
" vmlal.s16 q1, d23, d27\n"
|
|
" vqrshrn.s32 d0, q0, #15\n"
|
|
" vqrshrn.s32 d1, q1, #15\n"
|
|
" vst1.16 {d0, d1}, [%[o]]!\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]), [c2] "+r" (c[2]), [c3] "+r" (c[3]),
|
|
[len] "+r" (len), [o] "+r" (o)
|
|
: [ic] "r" (ic)
|
|
: "cc", "q0", "q1",
|
|
"d16", "d17", "d18", "d19", "d20", "d21", "d22",
|
|
"d23", "d24", "d25", "d26", "d27", "memory");
|
|
}
|
|
|
|
static inline void
|
|
inner_product_gint32_full_1_neon (gint32 * o, const gint32 * a,
|
|
const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
|
|
{
|
|
uint32_t remainder = len % 8;
|
|
len = len - remainder;
|
|
|
|
asm volatile (" vmov.s64 q0, #0\n"
|
|
" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
" vmov.s64 q1, #0\n"
|
|
"1:"
|
|
" vld1.32 {d16, d17, d18, d19}, [%[b]]!\n"
|
|
" vld1.32 {d20, d21, d22, d23}, [%[a]]!\n"
|
|
" subs %[len], %[len], #8\n"
|
|
" vmlal.s32 q0, d16, d20\n"
|
|
" vmlal.s32 q1, d17, d21\n"
|
|
" vmlal.s32 q0, d18, d22\n"
|
|
" vmlal.s32 q1, d19, d23\n"
|
|
" bne 1b\n"
|
|
" vadd.s64 q0, q0, q1\n"
|
|
"2:"
|
|
" cmp %[remainder], #0\n"
|
|
" beq 4f\n"
|
|
"3:"
|
|
" vld1.32 {d16, d17}, [%[b]]!\n"
|
|
" vld1.32 {d20, d21}, [%[a]]!\n"
|
|
" subs %[remainder], %[remainder], #4\n"
|
|
" vmlal.s32 q0, d16, d20\n"
|
|
" vmlal.s32 q0, d17, d21\n"
|
|
" bgt 3b\n"
|
|
"4:"
|
|
" vadd.s64 d0, d0, d1\n"
|
|
" vqrshrn.s64 d0, q0, #31\n"
|
|
" vst1.32 d0[0], [%[o]]\n"
|
|
: [a] "+r" (a), [b] "+r" (b),
|
|
[len] "+r" (len), [remainder] "+r" (remainder)
|
|
: [o] "r" (o)
|
|
: "cc", "q0", "q1",
|
|
"d16", "d17", "d18", "d19",
|
|
"d20", "d21", "d22", "d23");
|
|
}
|
|
|
|
static inline void
|
|
inner_product_gint32_linear_1_neon (gint32 * o, const gint32 * a,
|
|
const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
|
|
{
|
|
const gint32 *c[2] = {(gint32*)((gint8*)b + 0*bstride),
|
|
(gint32*)((gint8*)b + 1*bstride)};
|
|
|
|
asm volatile (" vmov.s64 q0, #0\n"
|
|
" vmov.s64 q1, #0\n"
|
|
" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
"1:"
|
|
" vld1.32 {d16, d17, d18, d19}, [%[c0]]!\n"
|
|
" vld1.32 {d20, d21, d22, d23}, [%[c1]]!\n"
|
|
" vld1.32 {d24, d25, d26, d27}, [%[a]]!\n"
|
|
" subs %[len], %[len], #8\n"
|
|
" vmlal.s32 q0, d16, d24\n"
|
|
" vmlal.s32 q1, d20, d24\n"
|
|
" vmlal.s32 q0, d17, d25\n"
|
|
" vmlal.s32 q1, d21, d25\n"
|
|
" vmlal.s32 q0, d18, d26\n"
|
|
" vmlal.s32 q1, d22, d26\n"
|
|
" vmlal.s32 q0, d19, d27\n"
|
|
" vmlal.s32 q1, d23, d27\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
" vld2.32 {d20[], d21[]}, [%[ic]]\n"
|
|
" vshrn.s64 d0, q0, #31\n"
|
|
" vshrn.s64 d2, q1, #31\n"
|
|
" vmull.s32 q0, d0, d20\n"
|
|
" vmlal.s32 q0, d2, d21\n"
|
|
" vadd.s64 d0, d0, d1\n"
|
|
" vqrshrn.s64 d0, q0, #31\n"
|
|
" vst1.32 d0[0], [%[o]]\n"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[len] "+r" (len)
|
|
: [o] "r" (o), [ic] "r" (icoeff)
|
|
: "cc", "q0", "q1",
|
|
"d16", "d17", "d18", "d19",
|
|
"d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "memory");
|
|
}
|
|
|
|
static inline void
|
|
inner_product_gint32_cubic_1_neon (gint32 * o, const gint32 * a,
|
|
const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
|
|
{
|
|
const gint32 *c[4] = {(gint32*)((gint8*)b + 0*bstride),
|
|
(gint32*)((gint8*)b + 1*bstride),
|
|
(gint32*)((gint8*)b + 2*bstride),
|
|
(gint32*)((gint8*)b + 3*bstride)};
|
|
|
|
asm volatile (" vmov.s64 q0, #0\n"
|
|
" vmov.s64 q1, #0\n"
|
|
" vmov.s64 q2, #0\n"
|
|
" vmov.s64 q3, #0\n"
|
|
" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
"1:"
|
|
" vld1.32 {d16, d17}, [%[c0]]!\n"
|
|
" vld1.32 {d18, d19}, [%[c1]]!\n"
|
|
" vld1.32 {d20, d21}, [%[c2]]!\n"
|
|
" vld1.32 {d22, d23}, [%[c3]]!\n"
|
|
" vld1.32 {d24, d25}, [%[a]]!\n"
|
|
" subs %[len], %[len], #4\n"
|
|
" vmlal.s32 q0, d16, d24\n"
|
|
" vmlal.s32 q1, d18, d24\n"
|
|
" vmlal.s32 q2, d20, d24\n"
|
|
" vmlal.s32 q3, d22, d24\n"
|
|
" vmlal.s32 q0, d17, d25\n"
|
|
" vmlal.s32 q1, d19, d25\n"
|
|
" vmlal.s32 q2, d21, d25\n"
|
|
" vmlal.s32 q3, d23, d25\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
" vld4.32 {d20[], d21[], d22[], d23[]}, [%[ic]]\n"
|
|
" vshrn.s64 d0, q0, #31\n"
|
|
" vshrn.s64 d2, q1, #31\n"
|
|
" vshrn.s64 d4, q2, #31\n"
|
|
" vshrn.s64 d6, q3, #31\n"
|
|
" vmull.s32 q0, d0, d20\n"
|
|
" vmlal.s32 q0, d2, d21\n"
|
|
" vmlal.s32 q0, d4, d22\n"
|
|
" vmlal.s32 q0, d6, d23\n"
|
|
" vadd.s64 d0, d0, d1\n"
|
|
" vqrshrn.s64 d0, q0, #31\n"
|
|
" vst1.32 d0[0], [%[o]]\n"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[c2] "+r" (c[2]), [c3] "+r" (c[3]), [len] "+r" (len)
|
|
: [o] "r" (o), [ic] "r" (icoeff)
|
|
: "cc", "q0", "q1", "q2", "q3",
|
|
"d16", "d17", "d18", "d19",
|
|
"d20", "d21", "d22", "d23", "d24", "d25", "memory");
|
|
}
|
|
|
|
static inline void
|
|
interpolate_gint32_linear_neon (gpointer op, const gpointer ap,
|
|
gint len, const gpointer icp, gint astride)
|
|
{
|
|
gint32 *o = op, *a = ap, *ic = icp;
|
|
const gint32 *c[2] = {(gint32*)((gint8*)a + 0*astride),
|
|
(gint32*)((gint8*)a + 1*astride)};
|
|
|
|
asm volatile (" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
" vld2.32 {d24[], d25[]}, [%[ic]]!\n"
|
|
"1:"
|
|
" vld1.32 {d16, d17, d18, d19}, [%[c0]]!\n"
|
|
" vld1.32 {d20, d21, d22, d23}, [%[c1]]!\n"
|
|
" subs %[len], %[len], #8\n"
|
|
" vmull.s32 q0, d16, d24\n"
|
|
" vmull.s32 q1, d17, d24\n"
|
|
" vmull.s32 q2, d18, d24\n"
|
|
" vmull.s32 q3, d19, d24\n"
|
|
" vmlal.s32 q0, d20, d25\n"
|
|
" vmlal.s32 q1, d21, d25\n"
|
|
" vmlal.s32 q2, d22, d25\n"
|
|
" vmlal.s32 q3, d23, d25\n"
|
|
" vqrshrn.s64 d0, q0, #31\n"
|
|
" vqrshrn.s64 d1, q1, #31\n"
|
|
" vqrshrn.s64 d2, q2, #31\n"
|
|
" vqrshrn.s64 d3, q3, #31\n"
|
|
" vst1.32 {d0, d1, d2, d3}, [%[o]]!\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[len] "+r" (len), [o] "+r" (o)
|
|
: [ic] "r" (ic)
|
|
: "cc", "q0", "q1", "q2", "q3",
|
|
"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "memory");
|
|
}
|
|
|
|
static inline void
|
|
interpolate_gint32_cubic_neon (gpointer op, const gpointer ap,
|
|
gint len, const gpointer icp, gint astride)
|
|
{
|
|
gint32 *o = op, *a = ap, *ic = icp;
|
|
const gint32 *c[4] = {(gint32*)((gint8*)a + 0*astride),
|
|
(gint32*)((gint8*)a + 1*astride),
|
|
(gint32*)((gint8*)a + 2*astride),
|
|
(gint32*)((gint8*)a + 3*astride)};
|
|
|
|
asm volatile (" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
" vld4.32 {d24[], d25[], d26[], d27[]}, [%[ic]]!\n"
|
|
"1:"
|
|
" vld1.32 {d16, d17}, [%[c0]]!\n"
|
|
" vld1.32 {d18, d19}, [%[c1]]!\n"
|
|
" vld1.32 {d20, d21}, [%[c2]]!\n"
|
|
" vld1.32 {d22, d23}, [%[c3]]!\n"
|
|
" subs %[len], %[len], #4\n"
|
|
" vmull.s32 q0, d16, d24\n"
|
|
" vmull.s32 q1, d17, d24\n"
|
|
" vmlal.s32 q0, d18, d25\n"
|
|
" vmlal.s32 q1, d19, d25\n"
|
|
" vmlal.s32 q0, d20, d26\n"
|
|
" vmlal.s32 q1, d21, d26\n"
|
|
" vmlal.s32 q0, d22, d27\n"
|
|
" vmlal.s32 q1, d23, d27\n"
|
|
" vqrshrn.s64 d0, q0, #31\n"
|
|
" vqrshrn.s64 d1, q1, #31\n"
|
|
" vst1.32 {d0, d1}, [%[o]]!\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[c2] "+r" (c[2]), [c3] "+r" (c[3]), [len] "+r" (len), [o] "+r" (o)
|
|
: [ic] "r" (ic)
|
|
: "cc", "q0", "q1",
|
|
"d16", "d17", "d18", "d19", "d20",
|
|
"d21", "d22", "d23", "d24", "d25", "d26", "d27", "memory");
|
|
}
|
|
|
|
static inline void
|
|
inner_product_gfloat_full_1_neon (gfloat * o, const gfloat * a,
|
|
const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
|
|
{
|
|
uint32_t remainder = len % 16;
|
|
len = len - remainder;
|
|
|
|
asm volatile (" vmov.f32 q0, #0.0\n"
|
|
" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
" vmov.f32 q1, #0.0\n"
|
|
"1:"
|
|
" vld1.32 {q4, q5}, [%[b]]!\n"
|
|
" vld1.32 {q8, q9}, [%[a]]!\n"
|
|
" vld1.32 {q6, q7}, [%[b]]!\n"
|
|
" vld1.32 {q10, q11}, [%[a]]!\n"
|
|
" subs %[len], %[len], #16\n"
|
|
" vmla.f32 q0, q4, q8\n"
|
|
" vmla.f32 q1, q5, q9\n"
|
|
" vmla.f32 q0, q6, q10\n"
|
|
" vmla.f32 q1, q7, q11\n"
|
|
" bne 1b\n"
|
|
" vadd.f32 q0, q0, q1\n"
|
|
"2:"
|
|
" cmp %[remainder], #0\n"
|
|
" beq 4f\n"
|
|
"3:"
|
|
" vld1.32 {q6}, [%[b]]!\n"
|
|
" vld1.32 {q10}, [%[a]]!\n"
|
|
" subs %[remainder], %[remainder], #4\n"
|
|
" vmla.f32 q0, q6, q10\n"
|
|
" bgt 3b\n"
|
|
"4:"
|
|
" vadd.f32 d0, d0, d1\n"
|
|
" vpadd.f32 d0, d0, d0\n"
|
|
" vst1.32 d0[0], [%[o]]\n"
|
|
: [a] "+r" (a), [b] "+r" (b),
|
|
[len] "+r" (len), [remainder] "+r" (remainder)
|
|
: [o] "r" (o)
|
|
: "cc", "q0", "q1", "q4", "q5", "q6", "q7", "q8",
|
|
"q9", "q10", "q11");
|
|
}
|
|
|
|
static inline void
|
|
inner_product_gfloat_linear_1_neon (gfloat * o, const gfloat * a,
|
|
const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
|
|
{
|
|
const gfloat *c[2] = {(gfloat*)((gint8*)b + 0*bstride),
|
|
(gfloat*)((gint8*)b + 1*bstride)};
|
|
|
|
asm volatile (" vmov.f32 q0, #0.0\n"
|
|
" vmov.f32 q1, #0.0\n"
|
|
" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
"1:"
|
|
" vld1.32 {q8, q9}, [%[c0]]!\n"
|
|
" vld1.32 {q10, q11}, [%[c1]]!\n"
|
|
" vld1.32 {q12, q13}, [%[a]]!\n"
|
|
" subs %[len], %[len], #8\n"
|
|
" vmla.f32 q0, q8, q12\n"
|
|
" vmla.f32 q1, q10, q12\n"
|
|
" vmla.f32 q0, q9, q13\n"
|
|
" vmla.f32 q1, q11, q13\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
" vld2.32 {d20[], d21[]}, [%[ic]]\n"
|
|
" vmul.f32 d0, d0, d20\n"
|
|
" vmla.f32 d0, d1, d20\n"
|
|
" vmla.f32 d0, d2, d21\n"
|
|
" vmla.f32 d0, d3, d21\n"
|
|
" vpadd.f32 d0, d0, d0\n"
|
|
" vst1.32 d0[0], [%[o]]\n"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[len] "+r" (len)
|
|
: [o] "r" (o), [ic] "r" (icoeff)
|
|
: "cc", "q0", "q1",
|
|
"q8", "q9", "q10", "q11", "q12", "q13", "memory");
|
|
}
|
|
|
|
static inline void
|
|
inner_product_gfloat_cubic_1_neon (gfloat * o, const gfloat * a,
|
|
const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
|
|
{
|
|
const gfloat *c[4] = {(gfloat*)((gint8*)b + 0*bstride),
|
|
(gfloat*)((gint8*)b + 1*bstride),
|
|
(gfloat*)((gint8*)b + 2*bstride),
|
|
(gfloat*)((gint8*)b + 3*bstride)};
|
|
|
|
asm volatile (" vmov.f32 q0, #0.0\n"
|
|
" vmov.f32 q1, #0.0\n"
|
|
" vmov.f32 q2, #0.0\n"
|
|
" vmov.f32 q3, #0.0\n"
|
|
" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
"1:"
|
|
" vld1.32 {q8}, [%[c0]]!\n"
|
|
" vld1.32 {q9}, [%[c1]]!\n"
|
|
" vld1.32 {q10}, [%[c2]]!\n"
|
|
" vld1.32 {q11}, [%[c3]]!\n"
|
|
" vld1.32 {q12}, [%[a]]!\n"
|
|
" subs %[len], %[len], #4\n"
|
|
" vmla.f32 q0, q8, q12\n"
|
|
" vmla.f32 q1, q9, q12\n"
|
|
" vmla.f32 q2, q10, q12\n"
|
|
" vmla.f32 q3, q11, q12\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
" vld4.32 {d20[], d21[], d22[], d23[]}, [%[ic]]\n"
|
|
" vmul.f32 d0, d0, d20\n"
|
|
" vmla.f32 d0, d1, d20\n"
|
|
" vmla.f32 d0, d2, d21\n"
|
|
" vmla.f32 d0, d3, d21\n"
|
|
" vmla.f32 d0, d4, d22\n"
|
|
" vmla.f32 d0, d5, d22\n"
|
|
" vmla.f32 d0, d6, d23\n"
|
|
" vmla.f32 d0, d7, d23\n"
|
|
" vpadd.f32 d0, d0, d0\n"
|
|
" vst1.32 d0[0], [%[o]]\n"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[c2] "+r" (c[2]), [c3] "+r" (c[3]), [len] "+r" (len), [o] "+r" (o)
|
|
: [ic] "r" (icoeff)
|
|
: "cc", "q0", "q1", "q2", "q3",
|
|
"q8", "q9", "q10", "q11", "q12", "memory");
|
|
}
|
|
|
|
static inline void
|
|
interpolate_gfloat_linear_neon (gpointer op, const gpointer ap,
|
|
gint len, const gpointer icp, gint astride)
|
|
{
|
|
gfloat *o = op, *a = ap, *ic = icp;
|
|
const gfloat *c[2] = {(gfloat*)((gint8*)a + 0*astride),
|
|
(gfloat*)((gint8*)a + 1*astride)};
|
|
|
|
asm volatile (" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
" vld2.32 {d24[], d26[]}, [%[ic]]!\n"
|
|
" vmov.32 d25, d24\n"
|
|
" vmov.32 d27, d26\n"
|
|
"1:"
|
|
" vld1.32 {q8, q9}, [%[c0]]!\n"
|
|
" vld1.32 {q10, q11}, [%[c1]]!\n"
|
|
" subs %[len], %[len], #8\n"
|
|
" vmul.f32 q0, q8, q12\n"
|
|
" vmul.f32 q1, q9, q12\n"
|
|
" vmla.f32 q0, q10, q13\n"
|
|
" vmla.f32 q1, q11, q13\n"
|
|
" vst1.32 {q0, q1}, [%[o]]!\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[len] "+r" (len), [o] "+r" (o)
|
|
: [ic] "r" (ic)
|
|
: "cc", "q0", "q1", "q8", "q9",
|
|
"q10", "q11", "q12", "q13", "memory");
|
|
}
|
|
|
|
static inline void
|
|
interpolate_gfloat_cubic_neon (gpointer op, const gpointer ap,
|
|
gint len, const gpointer icp, gint astride)
|
|
{
|
|
gfloat *o = op, *a = ap, *ic = icp;
|
|
const gfloat *c[4] = {(gfloat*)((gint8*)a + 0*astride),
|
|
(gfloat*)((gint8*)a + 1*astride),
|
|
(gfloat*)((gint8*)a + 2*astride),
|
|
(gfloat*)((gint8*)a + 3*astride)};
|
|
|
|
asm volatile (" cmp %[len], #0\n"
|
|
" beq 2f\n"
|
|
" vld4.32 {d24[], d26[], d28[], d30[]}, [%[ic]]!\n"
|
|
" vmov.32 d25, d24\n"
|
|
" vmov.32 d27, d26\n"
|
|
" vmov.32 d29, d28\n"
|
|
" vmov.32 d31, d30\n"
|
|
"1:"
|
|
" vld1.32 {q8}, [%[c0]]!\n"
|
|
" vld1.32 {q9}, [%[c1]]!\n"
|
|
" vld1.32 {q10}, [%[c2]]!\n"
|
|
" vld1.32 {q11}, [%[c3]]!\n"
|
|
" subs %[len], %[len], #4\n"
|
|
" vmul.f32 q0, q8, q12\n"
|
|
" vmla.f32 q0, q9, q13\n"
|
|
" vmla.f32 q0, q10, q14\n"
|
|
" vmla.f32 q0, q11, q15\n"
|
|
" vst1.32 {q0}, [%[o]]!\n"
|
|
" bne 1b\n"
|
|
"2:"
|
|
: [a] "+r" (a), [c0] "+r" (c[0]), [c1] "+r" (c[1]),
|
|
[c2] "+r" (c[2]), [c3] "+r" (c[3]),
|
|
[len] "+r" (len), [o] "+r" (o)
|
|
: [ic] "r" (ic)
|
|
: "cc", "q0", "q8", "q9",
|
|
"q10", "q11", "q12", "q13", "q14", "q15", "memory");
|
|
}
|
|
|
|
MAKE_RESAMPLE_FUNC_STATIC (gint16, full, 1, neon);
|
|
MAKE_RESAMPLE_FUNC_STATIC (gint16, linear, 1, neon);
|
|
MAKE_RESAMPLE_FUNC_STATIC (gint16, cubic, 1, neon);
|
|
|
|
MAKE_RESAMPLE_FUNC_STATIC (gint32, full, 1, neon);
|
|
MAKE_RESAMPLE_FUNC_STATIC (gint32, linear, 1, neon);
|
|
MAKE_RESAMPLE_FUNC_STATIC (gint32, cubic, 1, neon);
|
|
|
|
MAKE_RESAMPLE_FUNC_STATIC (gfloat, full, 1, neon);
|
|
MAKE_RESAMPLE_FUNC_STATIC (gfloat, linear, 1, neon);
|
|
MAKE_RESAMPLE_FUNC_STATIC (gfloat, cubic, 1, neon);
|
|
|
|
static void
|
|
audio_resampler_check_neon (const gchar *option)
|
|
{
|
|
if (!strcmp (option, "neon")) {
|
|
GST_DEBUG ("enable NEON optimisations");
|
|
resample_gint16_full_1 = resample_gint16_full_1_neon;
|
|
resample_gint16_linear_1 = resample_gint16_linear_1_neon;
|
|
resample_gint16_cubic_1 = resample_gint16_cubic_1_neon;
|
|
|
|
interpolate_gint16_linear = interpolate_gint16_linear_neon;
|
|
interpolate_gint16_cubic = interpolate_gint16_cubic_neon;
|
|
|
|
resample_gint32_full_1 = resample_gint32_full_1_neon;
|
|
resample_gint32_linear_1 = resample_gint32_linear_1_neon;
|
|
resample_gint32_cubic_1 = resample_gint32_cubic_1_neon;
|
|
|
|
interpolate_gint32_linear = interpolate_gint32_linear_neon;
|
|
interpolate_gint32_cubic = interpolate_gint32_cubic_neon;
|
|
|
|
resample_gfloat_full_1 = resample_gfloat_full_1_neon;
|
|
resample_gfloat_linear_1 = resample_gfloat_linear_1_neon;
|
|
resample_gfloat_cubic_1 = resample_gfloat_cubic_1_neon;
|
|
|
|
interpolate_gfloat_linear = interpolate_gfloat_linear_neon;
|
|
interpolate_gfloat_cubic = interpolate_gfloat_cubic_neon;
|
|
}
|
|
}
|