xref: /aosp_15_r20/external/XNNPACK/src/f32-gemm/gen/4x8-minmax-aarch32-neon-cortex-a75.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/f32-gemm/4x8-aarch32-neon-cortex-a75.S.in
3//   Generator: tools/xngen
4//
5// Copyright 2019 Google LLC
6//
7// This source code is licensed under the BSD-style license found in the
8// LICENSE file in the root directory of this source tree.
9
10#include <xnnpack/assembly.h>
11
12.syntax unified
13
14// void xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_cortex_a75(
15//     size_t mr,                            r0
16//     size_t nc,                            r1
17//     size_t kc,                            r2 -> r5
18//     const uint8_t*restrict a,             r3
19//     size_t a_stride,          sp + 96  -> (r7)
20//     const void*restrict w,    sp + 100 -> r9
21//     uint8_t*restrict c,       sp + 104 -> r11
22//     size_t cm_stride,         sp + 108 -> (r6)
23//     size_t cn_stride,         sp + 112 -> r7
24//     const union xnn_f32_minmax_params params)  sp + 116 -> (r7)
25
26// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
27
28// Register usage
29// A0   r3  d0
30// A1  r12  d1
31// A2  r10  d2
32// A3   r0  d3
33
34// B    r9  d8,  d9, d10, d11
35// B       d12, d13, d14, d15
36
37// C0  r11 d16-d17  q8  d18-d19  q9
38// C1   r4 d20-d21 q10  d22-d23 q11
39// C2   r8 d24-d25 q12  d26-d27 q13
40// C3   r6 d28-d29 q14  d30-d31 q15
41
42// Clamp (r5) d4 d5 d6 d7
43
44BEGIN_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_cortex_a75
45        .arm
46#ifndef __APPLE__
47        .arch   armv7-a
48        .fpu    neon
49#endif
50        # Push 96 bytes
51        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
52        VPUSH   {d8-d15}                            // +64 = 96
53
54        LDR     r7, [sp, 96]            // a_stride
55        LDR     r6, [sp, 108]           // cm_stride
56        LDR     r11, [sp, 104]          // c
57        LDR     r9, [sp, 100]           // w
58
59        # Clamp A and C pointers
60        CMP     r0, 2                   // if mr >= 2
61        ADD     r12, r3, r7             //   a1 = a0 + a_stride
62        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
63        MOVLO   r12, r3                 // a1
64        MOVLO   r4, r11                 // c1
65                                        // if mr > 2
66        ADD     r10, r12, r7            //   a2 = a1 + a_stride
67        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
68        MOVLS   r10, r12                // a2
69        MOVLS   r8, r4                  // c2
70
71        CMP     r0, 4                   // if mr >=4
72        ADD     r0, r10, r7             //   a3 = a2 + a_stride
73        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
74        MOVLO   r0, r10                 // a3
75        MOVLO   r6, r8                  // c3
76
77        LDR     r7, [sp, 112]           // cn_stride
78
79        .p2align 3
800:
81        # Load initial bias from w into accumulators
82        VLDM    r9!, {d16-d19}          // Bias
83        SUBS    r5, r2, 16
84        VMOV    q10, q8
85        VMOV    q11, q9
86        VMOV    q12, q8
87        VMOV    q13, q9
88        VMOV    q14, q8
89        VMOV    q15, q9
90
91
92        BLO     4f                      // less than 4 channels?
93
94        # Prologue
95        VLD1.32 {d0}, [r3]!             // A0
96        VLDM    r9!, {d8-d11}           // B0
97        VLD1.32 {d1}, [r12]!            // A1
98        VLD1.32 {d2}, [r10]!            // A2
99        VLD1.32 {d3}, [ r0]!            // A3
100
101        SUBS    r5, r5, 16
102        BLO     2f                      // less than 4 channels?  skip main loop
103
104        .p2align 3
105
106        # Main loop - 4 floats of A (16 bytes)
1071:
108        VMLA.F32 q8, q4, d0[0]
109        VLDM    r9!, {d12-d15}          // B1
110        VMLA.F32 q10, q4, d1[0]
111        VMLA.F32 q12, q4, d2[0]
112        VLD1.32 {d4}, [r3]!             // A0
113        VMLA.F32 q14, q4, d3[0]
114        VMLA.F32 q9, q5, d0[0]
115        VLD1.32 {d5}, [r12]!            // A1
116        VMLA.F32 q11, q5, d1[0]
117        VMLA.F32 q13, q5, d2[0]
118        VMLA.F32 q15, q5, d3[0]
119        VLD1.32 {d6}, [r10]!            // A2
120        VMLA.F32 q8, q6, d0[1]
121        VMLA.F32 q10, q6, d1[1]
122        VLD1.32 {d7}, [ r0]!            // A3
123        VMLA.F32 q12, q6, d2[1]
124        VMLA.F32 q14, q6, d3[1]
125        VLDM    r9!, {d8-d11}           // B0
126        VMLA.F32 q9, q7, d0[1]
127        VMLA.F32 q11, q7, d1[1]
128        VMLA.F32 q13, q7, d2[1]
129        VMLA.F32 q15, q7, d3[1]
130
131        VMLA.F32 q8, q4, d4[0]
132        VLDM    r9!, {d12-d15}          // B1
133        VMLA.F32 q10, q4, d5[0]
134        VMLA.F32 q12, q4, d6[0]
135        VLD1.32 {d0}, [r3]!             // A0
136        VMLA.F32 q14, q4, d7[0]
137        VMLA.F32 q9, q5, d4[0]
138        VLD1.32 {d1}, [r12]!            // A1
139        VMLA.F32 q11, q5, d5[0]
140        VMLA.F32 q13, q5, d6[0]
141        VLD1.32 {d2}, [r10]!            // A2
142        VMLA.F32 q15, q5, d7[0]
143        VMLA.F32 q8, q6, d4[1]
144        VLD1.32 {d3}, [ r0]!            // A3
145        VMLA.F32 q10, q6, d5[1]
146        VMLA.F32 q12, q6, d6[1]
147        VMLA.F32 q14, q6, d7[1]
148        VLDM    r9!, {d8-d11}           // B0
149        VMLA.F32 q9, q7, d4[1]
150        VMLA.F32 q11, q7, d5[1]
151        SUBS    r5, r5, 16
152        VMLA.F32 q13, q7, d6[1]
153        VMLA.F32 q15, q7, d7[1]
154        BHS     1b
155
156        # Epilogue
1572:
158        VMLA.F32 q8, q4, d0[0]
159        VLDM    r9!, {d12-d15}          // B1
160        VMLA.F32 q10, q4, d1[0]
161        VMLA.F32 q12, q4, d2[0]
162        VLD1.32 {d4}, [r3]!             // A0
163        VMLA.F32 q14, q4, d3[0]
164        VMLA.F32 q9, q5, d0[0]
165        VLD1.32 {d5}, [r12]!            // A1
166        VMLA.F32 q11, q5, d1[0]
167        VMLA.F32 q13, q5, d2[0]
168        VMLA.F32 q15, q5, d3[0]
169        VLD1.32 {d6}, [r10]!            // A2
170        VMLA.F32 q8, q6, d0[1]
171        VMLA.F32 q10, q6, d1[1]
172        VLD1.32 {d7}, [ r0]!            // A3
173        VMLA.F32 q12, q6, d2[1]
174        VMLA.F32 q14, q6, d3[1]
175        VLDM    r9!, {d8-d11}           // B0
176        VMLA.F32 q9, q7, d0[1]
177        VMLA.F32 q11, q7, d1[1]
178        VMLA.F32 q13, q7, d2[1]
179        VMLA.F32 q15, q7, d3[1]
180
181        VMLA.F32 q8, q4, d4[0]
182        VLDM    r9!, {d12-d15}          // B1
183        VMLA.F32 q10, q4, d5[0]
184        VMLA.F32 q12, q4, d6[0]
185        VMLA.F32 q14, q4, d7[0]
186        VMLA.F32 q9, q5, d4[0]
187        VMLA.F32 q11, q5, d5[0]
188        VMLA.F32 q13, q5, d6[0]
189        VMLA.F32 q15, q5, d7[0]
190        VMLA.F32 q8, q6, d4[1]
191        VMLA.F32 q10, q6, d5[1]
192        VMLA.F32 q12, q6, d6[1]
193        VMLA.F32 q14, q6, d7[1]
194        VMLA.F32 q9, q7, d4[1]
195        VMLA.F32 q11, q7, d5[1]
196        TST     r5, 15
197        VMLA.F32 q13, q7, d6[1]
198        VMLA.F32 q15, q7, d7[1]
199
200        # Is there a remainder?- 1 to 3 floats of A (4, 8 or 12 bytes)
201        BNE     4f
202
203        .p2align 3
2043:
205        # Load params pointer
206        LDR     r5, [sp, 116]           // params
207
208        # Load min/max values
209        VLD1.32 {d4[],d5[]}, [r5]!
210        SUBS    r1, r1, 8
211        VLD1.32 {d6[],d7[]}, [r5]
212
213        # Clamp
214        VMAX.F32 q8,  q8, q2
215        VMAX.F32 q9,  q9, q2
216        VMAX.F32 q10, q10, q2
217        VMAX.F32 q11, q11, q2
218        VMAX.F32 q12, q12, q2
219        VMAX.F32 q13, q13, q2
220        VMAX.F32 q14, q14, q2
221        VMAX.F32 q15, q15, q2
222        VMIN.F32 q8,  q8, q3
223        VMIN.F32 q9,  q9, q3
224        VMIN.F32 q10, q10, q3
225        VMIN.F32 q11, q11, q3
226        VMIN.F32 q12, q12, q3
227        VMIN.F32 q13, q13, q3
228        VMIN.F32 q14, q14, q3
229        VMIN.F32 q15, q15, q3
230
231        # Store full 4 x 8
232        BLO     6f
233        VST1.32 {d16-d19}, [r11], r7
234        SUB     r0, r0, r2
235        VST1.32 {d20-d23}, [r4], r7
236        SUB     r10, r10, r2
237        VST1.32 {d24-d27}, [r8], r7
238        SUB     r12, r12, r2
239        VST1.32 {d28-d31}, [r6], r7
240        SUB     r3, r3, r2
241        BHI     0b
242
243        VPOP    {d8-d15}
244        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
245        BX      lr
246
247        .p2align 3
2484:
249        # Is there a remainder?- 2 floats of A (8 bytes)
250        TST     r5, 8
251        BEQ     5f
252
253        # Remainder - 2 floats of A (8 bytes)
254        VLD1.32 {d0}, [r3]!             // A0
255        VLDM    r9!, {d8-d11}           // B0
256        VLD1.32 {d1}, [r12]!            // A1
257        VLD1.32 {d2}, [r10]!            // A2
258        VLD1.32 {d3}, [ r0]!            // A3
259
260        VMLA.F32 q8, q4, d0[0]
261        VMLA.F32 q9, q5, d0[0]
262        VMLA.F32 q10, q4, d1[0]
263        VMLA.F32 q11, q5, d1[0]
264        VLDM    r9!, {d12-d15}          // B1
265        VMLA.F32 q12, q4, d2[0]
266        VMLA.F32 q13, q5, d2[0]
267        VMLA.F32 q14, q4, d3[0]
268        VMLA.F32 q15, q5, d3[0]
269        VMLA.F32 q8, q6, d0[1]
270        VMLA.F32 q9, q7, d0[1]
271        VMLA.F32 q10, q6, d1[1]
272        VMLA.F32 q11, q7, d1[1]
273        VMLA.F32 q12, q6, d2[1]
274        VMLA.F32 q13, q7, d2[1]
275        VMLA.F32 q14, q6, d3[1]
276        VMLA.F32 q15, q7, d3[1]
277
278        # Is there a remainder?- 1 float of A (4 bytes)
279        TST     r5, 4
280        BEQ     3b
281
2825:
283        # Remainder- 1 float of A (4 bytes)
284        VLDM    r3!,  {s0}              // A0
285        VLDM    r9!, {d8-d11}           // B0
286        VLDM    r12!, {s2}              // A1
287        VLDM    r10!, {s4}              // A2
288        VLDM    r0!, {s6}               // A3
289        VMLA.F32 q8, q4, d0[0]
290        VMLA.F32 q9, q5, d0[0]
291        VMLA.F32 q10, q4, d1[0]
292        VMLA.F32 q11, q5, d1[0]
293        VMLA.F32 q12, q4, d2[0]
294        VMLA.F32 q13, q5, d2[0]
295        VMLA.F32 q14, q4, d3[0]
296        VMLA.F32 q15, q5, d3[0]
297        B       3b
298
299        # Store odd width
3006:
301        TST     r1, 4
302        BEQ     7f
303        VST1.32 {d16-d17}, [r11]!
304        VST1.32 {d20-d21},  [r4]!
305        VMOV    q8,  q9
306        VMOV    q10, q11
307        VST1.32 {d24-d25},  [r8]!
308        VST1.32 {d28-d29},  [r6]!
309        VMOV    q12, q13
310        VMOV    q14, q15
311
3127:
313        TST     r1, 2
314        BEQ     8f
315        VST1.32 {d16}, [r11]!
316        VST1.32 {d20},  [r4]!
317        VMOV    d16, d17
318        VMOV    d20, d21
319        VST1.32 {d24},  [r8]!
320        VST1.32 {d28},  [r6]!
321        VMOV    d24, d25
322        VMOV    d28, d29
323
3248:
325        TST     r1, 1
326        BEQ     9f
327        VST1.32 {d16[0]}, [r11]
328        VST1.32 {d20[0]},  [r4]
329        VST1.32 {d24[0]},  [r8]
330        VST1.32 {d28[0]},  [r6]
331
3329:
333        VPOP    {d8-d15}
334        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
335        BX      lr
336
337END_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_cortex_a75
338
339#ifdef __ELF__
340.section ".note.GNU-stack","",%progbits
341#endif
342
343