• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Auto-generated file. Do not edit!
2//   Template: src/f32-igemm/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_igemm_minmax_ukernel_4x8__aarch32_neon_cortex_a75(
15//     size_t mr,                            r0
16//     size_t nc,                            r1
17//     size_t kc,                            r2 -> r5 -> sp + 68
18//     size_t ks,                            r3 -> sp + 72 -> r14
19//     const float**restrict a,  sp + 112 -> r2
20//     const void*restrict w,    sp + 116 -> r9
21//     uint8_t*restrict c,       sp + 120 -> r11
22//     size_t cm_stride,         sp + 124 -> (r6)
23//     size_t cn_stride,         sp + 128 -> (r7)
24//     size_t a_offset,          sp + 132 -> (r5)
25//     const float* zero,        sp + 136 -> (r7)
26//     minmax_params*params,     sp + 140 -> (r5)
27
28// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
29
30// Register usage
31// A0   r3  d0
32// A1  r12  d1
33// A2  r10  d2
34// A3   r0  d3
35
36// B    r9  d8,  d9, d10, d11
37// B       d12, d13, d14, d15
38
39// C0  r11 d16-d17  q8  d18-d19  q9
40// C1   r4 d20-d21 q10  d22-d23 q11
41// C2   r8 d24-d25 q12  d26-d27 q13
42// C3   r6 d28-d29 q14  d30-d31 q15
43
44// Clamp (r5) d4 d5 d6 d7
45
46BEGIN_FUNCTION xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_cortex_a75
47        .arm
48#ifndef __APPLE__
49        .arch   armv7-a
50        .fpu    neon
51#endif
52        # Push 112 bytes
53        # r2 will be reloaded in outer loop.  r3 is ks
54        PUSH    {r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}   // +44
55        SUB     sp, sp, 4                                        // 4
56        VPUSH   {d8-d15}                                         // +64 = 112
57
58        LDR     r11, [sp, 120]          // c
59        LDR     r6, [sp, 124]           // cm_stride
60        LDR     r2, [sp, 112]           // a
61        LDR     r9, [sp, 116]           // w
62        MOV     r14, r3                 // p = ks
63
64        # Clamp C pointers
65        CMP     r0, 2                   // if mr >= 2
66        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
67        MOVLO   r4, r11                 // c1
68                                        // if mr > 2
69        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
70        MOVLS   r8, r4                  // c2
71        CMP     r0, 4                   // if mr >=4
72        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
73        MOVLO   r6, r8                  // c3
74
75        .p2align 3
760:
77        # Load initial bias from w into accumulators
78        VLDM    r9!, {d16-d19}          // Bias
79        VMOV    q10, q8
80        VMOV    q11, q9
81        VMOV    q12, q8
82        VMOV    q13, q9
83        VMOV    q14, q8
84        VMOV    q15, q9
85
86
871:
88        # Load next 4 A pointers
89        LDR     r3, [r2,  0]
90        LDR     r12, [r2,  4]
91        LDR     r10, [r2,  8]
92        LDR     r0, [r2, 12]
93        ADD     r2, r2, 16
94
95        # Add a_offset
96        LDR     r5, [sp, 132]           // a_offset
97        LDR     r7, [sp, 136]           // zero
98        CMP     r3,  r7                 // if a0 == zero
99        ADD     r3,  r3, r5             // a0 += a_offset
100        MOVEQ   r3,  r7                 //   a0 = zero, else += a0 + a_offset
101        CMP     r12,  r7                // if a1 == zero
102        ADD     r12, r12, r5            // a1 += a_offset
103        MOVEQ   r12,  r7                //   a1 = zero, else += a1 + a_offset
104        CMP     r10,  r7                // if a2 == zero
105        ADD     r10, r10, r5            // a2 += a_offset
106        MOVEQ   r10,  r7                //   a2 = zero, else += a2 + a_offset
107        CMP     r0,  r7                 // if a3 == zero
108        ADD     r0,  r0, r5             // a3 += a_offset
109        LDR     r5, [sp, 68]            // kc
110        MOVEQ   r0,  r7                 //   a3 = zero, else += a3 + a_offset
111
112
113        SUBS    r5, r5, 16              // kc - 16
114        BLO     5f                      // less than 4 channels?
115
116        # Prologue
117        VLD1.32 {d0}, [r3]!             // A0
118        VLDM    r9!, {d8-d11}           // B0
119        VLD1.32 {d1}, [r12]!            // A1
120        VLD1.32 {d2}, [r10]!            // A2
121        VLD1.32 {d3}, [ r0]!            // A3
122
123        SUBS    r5, r5, 16
124        BLO     3f                      // less than 4 channels?  skip main loop
125
126        .p2align 3
127
128        # Main loop - 4 floats of A (16 bytes)
1292:
130        VMLA.F32 q8, q4, d0[0]
131        VLDM    r9!, {d12-d15}          // B1
132        VMLA.F32 q10, q4, d1[0]
133        VMLA.F32 q12, q4, d2[0]
134        VLD1.32 {d4}, [r3]!             // A0
135        VMLA.F32 q14, q4, d3[0]
136        VMLA.F32 q9, q5, d0[0]
137        VLD1.32 {d5}, [r12]!            // A1
138        VMLA.F32 q11, q5, d1[0]
139        VMLA.F32 q13, q5, d2[0]
140        VMLA.F32 q15, q5, d3[0]
141        VLD1.32 {d6}, [r10]!            // A2
142        VMLA.F32 q8, q6, d0[1]
143        VMLA.F32 q10, q6, d1[1]
144        VLD1.32 {d7}, [ r0]!            // A3
145        VMLA.F32 q12, q6, d2[1]
146        VMLA.F32 q14, q6, d3[1]
147        VLDM    r9!, {d8-d11}           // B0
148        VMLA.F32 q9, q7, d0[1]
149        VMLA.F32 q11, q7, d1[1]
150        VMLA.F32 q13, q7, d2[1]
151        VMLA.F32 q15, q7, d3[1]
152
153        VMLA.F32 q8, q4, d4[0]
154        VLDM    r9!, {d12-d15}          // B1
155        VMLA.F32 q10, q4, d5[0]
156        VMLA.F32 q12, q4, d6[0]
157        VLD1.32 {d0}, [r3]!             // A0
158        VMLA.F32 q14, q4, d7[0]
159        VMLA.F32 q9, q5, d4[0]
160        VLD1.32 {d1}, [r12]!            // A1
161        VMLA.F32 q11, q5, d5[0]
162        VMLA.F32 q13, q5, d6[0]
163        VLD1.32 {d2}, [r10]!            // A2
164        VMLA.F32 q15, q5, d7[0]
165        VMLA.F32 q8, q6, d4[1]
166        VLD1.32 {d3}, [ r0]!            // A3
167        VMLA.F32 q10, q6, d5[1]
168        VMLA.F32 q12, q6, d6[1]
169        VMLA.F32 q14, q6, d7[1]
170        VLDM    r9!, {d8-d11}           // B0
171        VMLA.F32 q9, q7, d4[1]
172        VMLA.F32 q11, q7, d5[1]
173        SUBS    r5, r5, 16
174        VMLA.F32 q13, q7, d6[1]
175        VMLA.F32 q15, q7, d7[1]
176        BHS     2b
177
178        # Epilogue
1793:
180        VMLA.F32 q8, q4, d0[0]
181        VLDM    r9!, {d12-d15}          // B1
182        VMLA.F32 q10, q4, d1[0]
183        VMLA.F32 q12, q4, d2[0]
184        VLD1.32 {d4}, [r3]!             // A0
185        VMLA.F32 q14, q4, d3[0]
186        VMLA.F32 q9, q5, d0[0]
187        VLD1.32 {d5}, [r12]!            // A1
188        VMLA.F32 q11, q5, d1[0]
189        VMLA.F32 q13, q5, d2[0]
190        VMLA.F32 q15, q5, d3[0]
191        VLD1.32 {d6}, [r10]!            // A2
192        VMLA.F32 q8, q6, d0[1]
193        VMLA.F32 q10, q6, d1[1]
194        VLD1.32 {d7}, [ r0]!            // A3
195        VMLA.F32 q12, q6, d2[1]
196        VMLA.F32 q14, q6, d3[1]
197        VLDM    r9!, {d8-d11}           // B0
198        VMLA.F32 q9, q7, d0[1]
199        VMLA.F32 q11, q7, d1[1]
200        VMLA.F32 q13, q7, d2[1]
201        VMLA.F32 q15, q7, d3[1]
202
203        VMLA.F32 q8, q4, d4[0]
204        VLDM    r9!, {d12-d15}          // B1
205        VMLA.F32 q10, q4, d5[0]
206        VMLA.F32 q12, q4, d6[0]
207        VMLA.F32 q14, q4, d7[0]
208        VMLA.F32 q9, q5, d4[0]
209        VMLA.F32 q11, q5, d5[0]
210        VMLA.F32 q13, q5, d6[0]
211        VMLA.F32 q15, q5, d7[0]
212        VMLA.F32 q8, q6, d4[1]
213        VMLA.F32 q10, q6, d5[1]
214        VMLA.F32 q12, q6, d6[1]
215        VMLA.F32 q14, q6, d7[1]
216        VMLA.F32 q9, q7, d4[1]
217        VMLA.F32 q11, q7, d5[1]
218        VMLA.F32 q13, q7, d6[1]
219        VMLA.F32 q15, q7, d7[1]
220
221        # Is there a remainder?- 1 to 3 floats of A (4, 8 or 12 bytes)
222        TST     r5, 12
223        BNE     5f
224
225        .p2align 3
2264:
227        # ks loop
228        SUBS    r14, r14, 16            // ks -= MR * sizeof(void*)
229        BHI     1b
230
231        # Load params pointer
232        LDR     r5, [sp, 140]           // params
233        LDR     r7, [sp, 128]           // cn_stride
234        LDR     r14, [sp, 72]           // p = ks
235
236        # Load min/max values
237        VLD1.32 {d4[],d5[]}, [r5]!
238        SUBS    r1, r1, 8
239        VLD1.32 {d6[],d7[]}, [r5]
240
241        # Clamp
242        VMAX.F32 q8,  q8, q2
243        VMAX.F32 q9,  q9, q2
244        VMAX.F32 q10, q10, q2
245        VMAX.F32 q11, q11, q2
246        VMAX.F32 q12, q12, q2
247        VMAX.F32 q13, q13, q2
248        VMAX.F32 q14, q14, q2
249        VMAX.F32 q15, q15, q2
250        VMIN.F32 q8,  q8, q3
251        VMIN.F32 q9,  q9, q3
252        VMIN.F32 q10, q10, q3
253        VMIN.F32 q11, q11, q3
254        VMIN.F32 q12, q12, q3
255        VMIN.F32 q13, q13, q3
256        VMIN.F32 q14, q14, q3
257        VMIN.F32 q15, q15, q3
258
259        # Store full 4 x 8
260        BLO     7f
261        VST1.32 {d28-d31},  [r6], r7
262        VST1.32 {d24-d27},  [r8], r7
263        VST1.32 {d20-d23},  [r4], r7
264        VST1.32 {d16-d19}, [r11], r7
265        SUB     r2, r2, r14             // a -= ks
266        BHI     0b
267
268        VPOP    {d8-d15}
269        ADD     sp, sp, 12              // skip pad, r2, r3
270        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
271
272        .p2align 3
2735:
274        # Is there a remainder?- 2 floats of A (8 bytes)
275        TST     r5, 8
276        BEQ     6f
277
278        # Remainder - 2 floats of A (8 bytes)
279        VLD1.32 {d0}, [r3]!             // A0
280        VLDM    r9!, {d8-d11}           // B0
281        VLD1.32 {d1}, [r12]!            // A1
282        VLD1.32 {d2}, [r10]!            // A2
283        VLD1.32 {d3}, [ r0]!            // A3
284
285        VMLA.F32 q8, q4, d0[0]
286        VMLA.F32 q9, q5, d0[0]
287        VMLA.F32 q10, q4, d1[0]
288        VMLA.F32 q11, q5, d1[0]
289        VLDM    r9!, {d12-d15}          // B1
290        VMLA.F32 q12, q4, d2[0]
291        VMLA.F32 q13, q5, d2[0]
292        VMLA.F32 q14, q4, d3[0]
293        VMLA.F32 q15, q5, d3[0]
294        VMLA.F32 q8, q6, d0[1]
295        VMLA.F32 q9, q7, d0[1]
296        VMLA.F32 q10, q6, d1[1]
297        VMLA.F32 q11, q7, d1[1]
298        VMLA.F32 q12, q6, d2[1]
299        VMLA.F32 q13, q7, d2[1]
300        VMLA.F32 q14, q6, d3[1]
301        VMLA.F32 q15, q7, d3[1]
302
303        # Is there a remainder?- 1 float of A (4 bytes)
304        TST     r5, 4
305        BEQ     4b
306
3076:
308        # Remainder- 1 float of A (4 bytes)
309        VLDM    r3!, {s0}               // A0
310        VLDM    r9!, {d8-d11}           // B0
311        VLDM    r12!, {s2}              // A1
312        VLDM    r10!, {s4}              // A2
313        VLDM    r0!, {s6}               // A3
314        VMLA.F32 q8, q4, d0[0]
315        VMLA.F32 q9, q5, d0[0]
316        VMLA.F32 q10, q4, d1[0]
317        VMLA.F32 q11, q5, d1[0]
318        VMLA.F32 q12, q4, d2[0]
319        VMLA.F32 q13, q5, d2[0]
320        VMLA.F32 q14, q4, d3[0]
321        VMLA.F32 q15, q5, d3[0]
322        B       4b
323
324        # Store odd width
3257:
326        TST     r1, 4
327        BEQ     8f
328        VST1.32 {d28-d29},  [r6]!
329        VST1.32 {d24-d25},  [r8]!
330        VMOV    q14, q15
331        VMOV    q12, q13
332        VST1.32 {d20-d21},  [r4]!
333        VST1.32 {d16-d17}, [r11]!
334        VMOV    q10, q11
335        VMOV    q8,  q9
336
3378:
338        TST     r1, 2
339        BEQ     9f
340        VST1.32 {d28},  [r6]!
341        VST1.32 {d24},  [r8]!
342        VMOV    d28, d29
343        VMOV    d24, d25
344        VST1.32 {d20},  [r4]!
345        VST1.32 {d16}, [r11]!
346        VMOV    d20, d21
347        VMOV    d16, d17
348
3499:
350        TST     r1, 1
351        BEQ     10f
352        VST1.32 {d28[0]},  [r6]!
353        VST1.32 {d24[0]},  [r8]!
354        VST1.32 {d20[0]},  [r4]!
355        VST1.32 {d16[0]}, [r11]!
356
35710:
358        VPOP    {d8-d15}
359        ADD     sp, sp, 12              // skip pad, r2, r3
360        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
361
362END_FUNCTION xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_cortex_a75
363
364#ifdef __ELF__
365.section ".note.GNU-stack","",%progbits
366#endif
367