blob: 3209d60657f8749dc19192c443ebd1bc09b9eee9 [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.
Thomas Tsou7e4e5362013-10-30 21:18:55 -040016 */
17
18#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22 .syntax unified
23 .text
24 .align 2
25 .global neon_conv_real4
26 .type neon_conv_real4, %function
27neon_conv_real4:
28 push {r4, lr}
29 vpush {q4-q7}
30 vld2.32 {q0-q1}, [r1]
31 ldr r4, =8
32.neon_conv_loop4:
33 vld2.32 {q2-q3}, [r0], r4
34 vmul.f32 q4, q2, q0
35 vmul.f32 q5, q3, q0
36 vpadd.f32 d12, d8, d9
37 vpadd.f32 d13, d10, d11
38 vpadd.f32 d14, d12, d13
39 vst1.64 {d14}, [r2]!
40 subs r3, r3, #1
41 bne .neon_conv_loop4
42 vpop {q4-q7}
43 pop {r4, pc}
44 .size neon_conv_real4, .-neon_conv_real4
45 .align 2
46 .p2align 4,,15
47 .global neon_conv_real8
48 .type neon_conv_real8, %function
49neon_conv_real8:
50 push {r4-r5, lr}
51 vpush {q4-q7}
52 vld2.32 {q0-q1}, [r1]!
53 vld2.32 {q2-q3}, [r1]
54 add r4, r0, #32
55 ldr r5, =8
56.neon_conv_loop8:
57 vld2.32 {q4-q5}, [r0], r5
58 vld2.32 {q6-q7}, [r4], r5
59 vmul.f32 q8, q4, q0
60 vmul.f32 q9, q5, q0
61 vmul.f32 q10, q6, q2
62 vmul.f32 q11, q7, q2
63
64 vadd.f32 q12, q8, q10
65 vadd.f32 q13, q9, q11
66
67 vpadd.f32 d22, d24, d25
68 vpadd.f32 d23, d26, d27
69 vpadd.f32 d24, d22, d23
70 vst1.64 {d24}, [r2]!
71 subs r3, r3, #1
72 bne .neon_conv_loop8
73 vpop {q4-q7}
74 pop {r4-r5, pc}
75 .size neon_conv_real8, .-neon_conv_real8
76 .align 2
77 .global neon_conv_real12
78 .type neon_conv_real12, %function
79neon_conv_real12:
80 push {r4-r6, lr}
81 vpush {q4-q7}
82 vld2.32 {q0-q1}, [r1]!
83 vld2.32 {q2-q3}, [r1]!
84 vld2.32 {q4-q5}, [r1]!
85 add r4, r0, #32
86 add r5, r0, #64
87 ldr r6, =8
88.neon_conv_loop12:
89 vld2.32 {q6-q7}, [r0], r6
90 vld2.32 {q8-q9}, [r4], r6
91 vld2.32 {q10-q11}, [r5], r6
92#ifdef HAVE_NEON_FMA
Sylvain Munautacf804c2018-12-21 16:47:12 +010093 vmul.f32 q1, q6, q0
94 vmul.f32 q3, q7, q0
Thomas Tsou7e4e5362013-10-30 21:18:55 -040095 vfma.f32 q1, q8, q2
96 vfma.f32 q3, q9, q2
97 vfma.f32 q1, q10, q4
98 vfma.f32 q3, q11, q4
99#else
100 vmul.f32 q12, q6, q0
101 vmul.f32 q13, q7, q0
102 vmul.f32 q14, q8, q2
103 vmul.f32 q15, q9, q2
104 vmul.f32 q1, q10, q4
105 vmul.f32 q3, q11, q4
106
107 vadd.f32 q5, q12, q14
108 vadd.f32 q6, q13, q15
109 vadd.f32 q1, q5, q1
110 vadd.f32 q3, q6, q3
111#endif
112 vpadd.f32 d2, d2, d3
113 vpadd.f32 d3, d6, d7
114 vpadd.f32 d6, d2, d3
115 vst1.64 {d6}, [r2]!
116 subs r3, r3, #1
117 bne .neon_conv_loop12
118 vpop {q4-q7}
119 pop {r4-r6, pc}
120 .size neon_conv_real12, .-neon_conv_real12
121 .align 2
122 .global neon_conv_real16
123 .type neon_conv_real16, %function
124neon_conv_real16:
125 push {r4-r7, lr}
126 vpush {q4-q7}
127 vld2.32 {q0-q1}, [r1]!
128 vld2.32 {q2-q3}, [r1]!
129 vld2.32 {q4-q5}, [r1]!
130 vld2.32 {q6-q7}, [r1]
131 add r4, r0, #32
132 add r5, r0, #64
133 add r6, r0, #96
134 ldr r7, =8
135.neon_conv_loop16:
136 vld2.32 {q8-q9}, [r0], r7
137 vld2.32 {q10-q11}, [r4], r7
138 vld2.32 {q12-q13}, [r5], r7
139 vld2.32 {q14-q15}, [r6], r7
140#ifdef HAVE_NEON_FMA
141 vmul.f32 q1, q8, q0
142 vmul.f32 q3, q9, q0
143 vfma.f32 q1, q10, q2
144 vfma.f32 q3, q11, q2
145 vfma.f32 q1, q12, q4
146 vfma.f32 q3, q13, q4
147 vfma.f32 q1, q14, q6
148 vfma.f32 q3, q15, q6
149#else
150 vmul.f32 q1, q8, q0
151 vmul.f32 q3, q9, q0
152 vmul.f32 q5, q10, q2
153 vmul.f32 q7, q11, q2
154 vmul.f32 q8, q12, q4
155 vmul.f32 q9, q13, q4
156 vmul.f32 q10, q14, q6
157 vmul.f32 q11, q15, q6
158
159 vadd.f32 q1, q1, q5
160 vadd.f32 q3, q3, q7
161 vadd.f32 q5, q8, q10
162 vadd.f32 q7, q9, q11
163 vadd.f32 q1, q1, q5
164 vadd.f32 q3, q3, q7
165#endif
166 vpadd.f32 d2, d2, d3
167 vpadd.f32 d3, d6, d7
168 vpadd.f32 d6, d2, d3
169 vst1.64 {d6}, [r2]!
170 subs r3, r3, #1
171 bne .neon_conv_loop16
172 vpop {q4-q7}
173 pop {r4-r7, pc}
174 .size neon_conv_real16, .-neon_conv_real16
175 .align 2
176 .global neon_conv_real20
177 .type neon_conv_real20, %function
178neon_conv_real20:
179 push {r4-r8, lr}
180 vpush {q4-q7}
181 vld2.32 {q0-q1}, [r1]!
182 vld2.32 {q2-q3}, [r1]!
183 vld2.32 {q4-q5}, [r1]!
184 vld2.32 {q6-q7}, [r1]!
185 vld2.32 {q8-q9}, [r1]
186 add r4, r0, #32
187 add r5, r0, #64
188 add r6, r0, #96
189 add r7, r0, #128
190 ldr r8, =8
191.neon_conv_loop20:
192 vld2.32 {q10-q11}, [r0], r8
193 vld2.32 {q12-q13}, [r4], r8
194 vld2.32 {q14-q15}, [r5], r8
195#ifdef HAVE_NEON_FMA
196 vmul.f32 q1, q10, q0
197 vfma.f32 q1, q12, q2
198 vfma.f32 q1, q14, q4
199 vmul.f32 q3, q11, q0
200 vfma.f32 q3, q13, q2
201 vfma.f32 q3, q15, q4
202
203 vld2.32 {q12-q13}, [r6], r8
204 vld2.32 {q14-q15}, [r7], r8
205
206 vfma.f32 q1, q12, q6
207 vfma.f32 q3, q13, q6
208 vfma.f32 q1, q14, q8
209 vfma.f32 q3, q15, q8
210#else
211 vmul.f32 q1, q10, q0
212 vmul.f32 q3, q12, q2
213 vmul.f32 q5, q14, q4
214 vmul.f32 q7, q11, q0
215 vmul.f32 q9, q13, q2
216 vmul.f32 q10, q15, q4
217 vadd.f32 q1, q1, q3
218 vadd.f32 q3, q7, q9
219 vadd.f32 q9, q1, q5
220 vadd.f32 q10, q3, q10
221
222 vld2.32 {q12-q13}, [r6], r8
223 vld2.32 {q14-q15}, [r7], r8
224
225 vmul.f32 q1, q12, q6
226 vmul.f32 q3, q13, q6
227 vmul.f32 q5, q14, q8
228 vmul.f32 q7, q15, q8
229 vadd.f32 q12, q1, q9
230 vadd.f32 q14, q3, q10
231 vadd.f32 q1, q12, q5
232 vadd.f32 q3, q14, q7
233#endif
234 vpadd.f32 d2, d2, d3
235 vpadd.f32 d3, d6, d7
236 vpadd.f32 d6, d2, d3
237 vst1.64 {d6}, [r2]!
238 subs r3, r3, #1
239 bne .neon_conv_loop20
240 vpop {q4-q7}
241 pop {r4-r8, pc}
242 .size neon_conv_real20, .-neon_conv_real20
243 .align 2
244 .global mac_cx_neon4
245 .type mac_cx_neon4, %function
246mac_cx_neon4:
247 push {r4, lr}
248 ldr r4, =32
249 veor q14, q14
250 veor q15, q15
251.neon_conv_loop_mac4:
252 vld2.32 {q0-q1}, [r0], r4
253 vld2.32 {q2-q3}, [r1]!
254
255 vmul.f32 q10, q0, q2
256 vmul.f32 q11, q1, q3
257 vmul.f32 q12, q0, q3
258 vmul.f32 q13, q2, q1
259 vsub.f32 q8, q10, q11
260 vadd.f32 q9, q12, q13
261
262 vadd.f32 q14, q8
263 vadd.f32 q15, q9
264 subs r3, #1
265 bne .neon_conv_loop_mac4
266
267 vld1.64 d0, [r2]
268 vpadd.f32 d28, d28, d29
269 vpadd.f32 d30, d30, d31
270 vpadd.f32 d1, d28, d30
271 vadd.f32 d1, d0
272 vst1.64 d1, [r2]
273 pop {r4, pc}
274 .size mac_cx_neon4, .-mac_cx_neon4
275 .section .note.GNU-stack,"",%progbits