blob: a3e1ba56f3b31e768ebd42df778db0ec6e4a2ad6 [file] [log] [blame]
Thomas Tsou7e4e5362013-10-30 21:18:55 -04001/*
2 * NEON Convolution
3 * Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
4 *
Pau Espin Pedrol21d03d32019-07-22 12:05:52 +02005 * SPDX-License-Identifier: LGPL-2.1+
6 *
Thomas Tsou7e4e5362013-10-30 21:18:55 -04007 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26 .syntax unified
27 .text
28 .align 2
29 .global neon_conv_real4
30 .type neon_conv_real4, %function
31neon_conv_real4:
32 push {r4, lr}
33 vpush {q4-q7}
34 vld2.32 {q0-q1}, [r1]
35 ldr r4, =8
36.neon_conv_loop4:
37 vld2.32 {q2-q3}, [r0], r4
38 vmul.f32 q4, q2, q0
39 vmul.f32 q5, q3, q0
40 vpadd.f32 d12, d8, d9
41 vpadd.f32 d13, d10, d11
42 vpadd.f32 d14, d12, d13
43 vst1.64 {d14}, [r2]!
44 subs r3, r3, #1
45 bne .neon_conv_loop4
46 vpop {q4-q7}
47 pop {r4, pc}
48 .size neon_conv_real4, .-neon_conv_real4
49 .align 2
50 .p2align 4,,15
51 .global neon_conv_real8
52 .type neon_conv_real8, %function
53neon_conv_real8:
54 push {r4-r5, lr}
55 vpush {q4-q7}
56 vld2.32 {q0-q1}, [r1]!
57 vld2.32 {q2-q3}, [r1]
58 add r4, r0, #32
59 ldr r5, =8
60.neon_conv_loop8:
61 vld2.32 {q4-q5}, [r0], r5
62 vld2.32 {q6-q7}, [r4], r5
63 vmul.f32 q8, q4, q0
64 vmul.f32 q9, q5, q0
65 vmul.f32 q10, q6, q2
66 vmul.f32 q11, q7, q2
67
68 vadd.f32 q12, q8, q10
69 vadd.f32 q13, q9, q11
70
71 vpadd.f32 d22, d24, d25
72 vpadd.f32 d23, d26, d27
73 vpadd.f32 d24, d22, d23
74 vst1.64 {d24}, [r2]!
75 subs r3, r3, #1
76 bne .neon_conv_loop8
77 vpop {q4-q7}
78 pop {r4-r5, pc}
79 .size neon_conv_real8, .-neon_conv_real8
80 .align 2
81 .global neon_conv_real12
82 .type neon_conv_real12, %function
83neon_conv_real12:
84 push {r4-r6, lr}
85 vpush {q4-q7}
86 vld2.32 {q0-q1}, [r1]!
87 vld2.32 {q2-q3}, [r1]!
88 vld2.32 {q4-q5}, [r1]!
89 add r4, r0, #32
90 add r5, r0, #64
91 ldr r6, =8
92.neon_conv_loop12:
93 vld2.32 {q6-q7}, [r0], r6
94 vld2.32 {q8-q9}, [r4], r6
95 vld2.32 {q10-q11}, [r5], r6
96#ifdef HAVE_NEON_FMA
Sylvain Munautacf804c2018-12-21 16:47:12 +010097 vmul.f32 q1, q6, q0
98 vmul.f32 q3, q7, q0
Thomas Tsou7e4e5362013-10-30 21:18:55 -040099 vfma.f32 q1, q8, q2
100 vfma.f32 q3, q9, q2
101 vfma.f32 q1, q10, q4
102 vfma.f32 q3, q11, q4
103#else
104 vmul.f32 q12, q6, q0
105 vmul.f32 q13, q7, q0
106 vmul.f32 q14, q8, q2
107 vmul.f32 q15, q9, q2
108 vmul.f32 q1, q10, q4
109 vmul.f32 q3, q11, q4
110
111 vadd.f32 q5, q12, q14
112 vadd.f32 q6, q13, q15
113 vadd.f32 q1, q5, q1
114 vadd.f32 q3, q6, q3
115#endif
116 vpadd.f32 d2, d2, d3
117 vpadd.f32 d3, d6, d7
118 vpadd.f32 d6, d2, d3
119 vst1.64 {d6}, [r2]!
120 subs r3, r3, #1
121 bne .neon_conv_loop12
122 vpop {q4-q7}
123 pop {r4-r6, pc}
124 .size neon_conv_real12, .-neon_conv_real12
125 .align 2
126 .global neon_conv_real16
127 .type neon_conv_real16, %function
128neon_conv_real16:
129 push {r4-r7, lr}
130 vpush {q4-q7}
131 vld2.32 {q0-q1}, [r1]!
132 vld2.32 {q2-q3}, [r1]!
133 vld2.32 {q4-q5}, [r1]!
134 vld2.32 {q6-q7}, [r1]
135 add r4, r0, #32
136 add r5, r0, #64
137 add r6, r0, #96
138 ldr r7, =8
139.neon_conv_loop16:
140 vld2.32 {q8-q9}, [r0], r7
141 vld2.32 {q10-q11}, [r4], r7
142 vld2.32 {q12-q13}, [r5], r7
143 vld2.32 {q14-q15}, [r6], r7
144#ifdef HAVE_NEON_FMA
145 vmul.f32 q1, q8, q0
146 vmul.f32 q3, q9, q0
147 vfma.f32 q1, q10, q2
148 vfma.f32 q3, q11, q2
149 vfma.f32 q1, q12, q4
150 vfma.f32 q3, q13, q4
151 vfma.f32 q1, q14, q6
152 vfma.f32 q3, q15, q6
153#else
154 vmul.f32 q1, q8, q0
155 vmul.f32 q3, q9, q0
156 vmul.f32 q5, q10, q2
157 vmul.f32 q7, q11, q2
158 vmul.f32 q8, q12, q4
159 vmul.f32 q9, q13, q4
160 vmul.f32 q10, q14, q6
161 vmul.f32 q11, q15, q6
162
163 vadd.f32 q1, q1, q5
164 vadd.f32 q3, q3, q7
165 vadd.f32 q5, q8, q10
166 vadd.f32 q7, q9, q11
167 vadd.f32 q1, q1, q5
168 vadd.f32 q3, q3, q7
169#endif
170 vpadd.f32 d2, d2, d3
171 vpadd.f32 d3, d6, d7
172 vpadd.f32 d6, d2, d3
173 vst1.64 {d6}, [r2]!
174 subs r3, r3, #1
175 bne .neon_conv_loop16
176 vpop {q4-q7}
177 pop {r4-r7, pc}
178 .size neon_conv_real16, .-neon_conv_real16
179 .align 2
180 .global neon_conv_real20
181 .type neon_conv_real20, %function
182neon_conv_real20:
183 push {r4-r8, lr}
184 vpush {q4-q7}
185 vld2.32 {q0-q1}, [r1]!
186 vld2.32 {q2-q3}, [r1]!
187 vld2.32 {q4-q5}, [r1]!
188 vld2.32 {q6-q7}, [r1]!
189 vld2.32 {q8-q9}, [r1]
190 add r4, r0, #32
191 add r5, r0, #64
192 add r6, r0, #96
193 add r7, r0, #128
194 ldr r8, =8
195.neon_conv_loop20:
196 vld2.32 {q10-q11}, [r0], r8
197 vld2.32 {q12-q13}, [r4], r8
198 vld2.32 {q14-q15}, [r5], r8
199#ifdef HAVE_NEON_FMA
200 vmul.f32 q1, q10, q0
201 vfma.f32 q1, q12, q2
202 vfma.f32 q1, q14, q4
203 vmul.f32 q3, q11, q0
204 vfma.f32 q3, q13, q2
205 vfma.f32 q3, q15, q4
206
207 vld2.32 {q12-q13}, [r6], r8
208 vld2.32 {q14-q15}, [r7], r8
209
210 vfma.f32 q1, q12, q6
211 vfma.f32 q3, q13, q6
212 vfma.f32 q1, q14, q8
213 vfma.f32 q3, q15, q8
214#else
215 vmul.f32 q1, q10, q0
216 vmul.f32 q3, q12, q2
217 vmul.f32 q5, q14, q4
218 vmul.f32 q7, q11, q0
219 vmul.f32 q9, q13, q2
220 vmul.f32 q10, q15, q4
221 vadd.f32 q1, q1, q3
222 vadd.f32 q3, q7, q9
223 vadd.f32 q9, q1, q5
224 vadd.f32 q10, q3, q10
225
226 vld2.32 {q12-q13}, [r6], r8
227 vld2.32 {q14-q15}, [r7], r8
228
229 vmul.f32 q1, q12, q6
230 vmul.f32 q3, q13, q6
231 vmul.f32 q5, q14, q8
232 vmul.f32 q7, q15, q8
233 vadd.f32 q12, q1, q9
234 vadd.f32 q14, q3, q10
235 vadd.f32 q1, q12, q5
236 vadd.f32 q3, q14, q7
237#endif
238 vpadd.f32 d2, d2, d3
239 vpadd.f32 d3, d6, d7
240 vpadd.f32 d6, d2, d3
241 vst1.64 {d6}, [r2]!
242 subs r3, r3, #1
243 bne .neon_conv_loop20
244 vpop {q4-q7}
245 pop {r4-r8, pc}
246 .size neon_conv_real20, .-neon_conv_real20
247 .align 2
248 .global mac_cx_neon4
249 .type mac_cx_neon4, %function
250mac_cx_neon4:
251 push {r4, lr}
252 ldr r4, =32
253 veor q14, q14
254 veor q15, q15
255.neon_conv_loop_mac4:
256 vld2.32 {q0-q1}, [r0], r4
257 vld2.32 {q2-q3}, [r1]!
258
259 vmul.f32 q10, q0, q2
260 vmul.f32 q11, q1, q3
261 vmul.f32 q12, q0, q3
262 vmul.f32 q13, q2, q1
263 vsub.f32 q8, q10, q11
264 vadd.f32 q9, q12, q13
265
266 vadd.f32 q14, q8
267 vadd.f32 q15, q9
268 subs r3, #1
269 bne .neon_conv_loop_mac4
270
271 vld1.64 d0, [r2]
272 vpadd.f32 d28, d28, d29
273 vpadd.f32 d30, d30, d31
274 vpadd.f32 d1, d28, d30
275 vadd.f32 d1, d0
276 vst1.64 d1, [r2]
277 pop {r4, pc}
278 .size mac_cx_neon4, .-mac_cx_neon4
279 .section .note.GNU-stack,"",%progbits