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_pld_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[restrict XNN_MIN_ELEMENTS(1)])  sp + 116 -> (r7)
25
26
27// inner loop registers
28
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_pld_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        PLD         [r3,  0]    // Prefetch A
92        PLD         [r3, 64]
93        PLD         [r12,  0]
94        PLD         [r12, 64]
95        PLD         [r10,  0]
96        PLD         [r10, 64]
97        PLD         [r0,  0]
98        PLD         [r0, 64]
99        PLD         [r9,   0]  // Prefetch B
100        PLD         [r9,  64]
101        PLD         [r9, 128]
102        PLD         [r9, 192]
103        PLD         [r9, 256]
104        PLD         [r9, 320]
105        PLD         [r9, 384]
106
107        BLO         4f               // less than 4 channels?
108
109        // Prologue
110        VLD1.32    {d0}, [r3]!       // A0
111        VLDM        r9!, {d8-d11}    // B0
112        VLD1.32    {d1}, [r12]!      // A1
113        VLD1.32    {d2}, [r10]!      // A2
114        VLD1.32    {d3}, [ r0]!      // A3
115
116        SUBS        r5, r5, 16
117        BLO         2f               // less than 4 channels?  skip main loop
118
119        .p2align 3
120
121        // Main loop - 4 floats of A (16 bytes)
1221:
123        VMLA.F32     q8, q4, d0[0]
124        VLDM        r9!, {d12-d15}   // B1
125        VMLA.F32    q10, q4, d1[0]
126        VMLA.F32    q12, q4, d2[0]
127        VLD1.32    {d4}, [r3]!       // A0
128        VMLA.F32    q14, q4, d3[0]
129        VMLA.F32     q9, q5, d0[0]
130        VLD1.32    {d5}, [r12]!      // A1
131        VMLA.F32    q11, q5, d1[0]
132        VMLA.F32    q13, q5, d2[0]
133        VMLA.F32    q15, q5, d3[0]
134        VLD1.32    {d6}, [r10]!      // A2
135        VMLA.F32     q8, q6, d0[1]
136        VMLA.F32    q10, q6, d1[1]
137        VLD1.32    {d7}, [ r0]!      // A3
138        VMLA.F32    q12, q6, d2[1]
139        VMLA.F32    q14, q6, d3[1]
140        VLDM        r9!, {d8-d11}    // B0
141        VMLA.F32     q9, q7, d0[1]
142        VMLA.F32    q11, q7, d1[1]
143        VMLA.F32    q13, q7, d2[1]
144        VMLA.F32    q15, q7, d3[1]
145
146        VMLA.F32     q8, q4, d4[0]
147        VLDM        r9!, {d12-d15}   // B1
148        VMLA.F32    q10, q4, d5[0]
149        PLD         [r3, 128]        // Prefetch A0
150        VMLA.F32    q12, q4, d6[0]
151        VLD1.32    {d0}, [r3]!       // A0
152        VMLA.F32    q14, q4, d7[0]
153        PLD         [r12, 128]       // Prefetch A1
154        VMLA.F32     q9, q5, d4[0]
155        VLD1.32    {d1}, [r12]!      // A1
156        VMLA.F32    q11, q5, d5[0]
157        PLD         [r10, 128]       // Prefetch A2
158        VMLA.F32    q13, q5, d6[0]
159        VLD1.32    {d2}, [r10]!      // A2
160        VMLA.F32    q15, q5, d7[0]
161        PLD         [r0, 128]        // Prefetch A3
162        VMLA.F32     q8, q6, d4[1]
163        VLD1.32    {d3}, [ r0]!      // A3
164        VMLA.F32    q10, q6, d5[1]
165        PLD         [r9, 352]        // Prefetch B
166        VMLA.F32    q12, q6, d6[1]
167        PLD         [r9, 416]        // Prefetch B
168        VMLA.F32    q14, q6, d7[1]
169        VLDM        r9!, {d8-d11}    // B0
170        VMLA.F32     q9, q7, d4[1]
171        VMLA.F32    q11, q7, d5[1]
172        SUBS         r5, r5, 16
173        VMLA.F32    q13, q7, d6[1]
174        VMLA.F32    q15, q7, d7[1]
175        BHS         1b
176
177        // Epilogue
1782:
179        VMLA.F32     q8, q4, d0[0]
180        VLDM        r9!, {d12-d15}   // B1
181        VMLA.F32    q10, q4, d1[0]
182        VMLA.F32    q12, q4, d2[0]
183        VLD1.32    {d4}, [r3]!       // A0
184        VMLA.F32    q14, q4, d3[0]
185        VMLA.F32     q9, q5, d0[0]
186        VLD1.32    {d5}, [r12]!      // A1
187        VMLA.F32    q11, q5, d1[0]
188        VMLA.F32    q13, q5, d2[0]
189        VMLA.F32    q15, q5, d3[0]
190        VLD1.32    {d6}, [r10]!      // A2
191        VMLA.F32     q8, q6, d0[1]
192        VMLA.F32    q10, q6, d1[1]
193        VLD1.32    {d7}, [ r0]!      // A3
194        VMLA.F32    q12, q6, d2[1]
195        VMLA.F32    q14, q6, d3[1]
196        VLDM        r9!, {d8-d11}    // B0
197        VMLA.F32     q9, q7, d0[1]
198        VMLA.F32    q11, q7, d1[1]
199        VMLA.F32    q13, q7, d2[1]
200        VMLA.F32    q15, q7, d3[1]
201
202        VMLA.F32     q8, q4, d4[0]
203        VLDM        r9!, {d12-d15}   // B1
204        VMLA.F32    q10, q4, d5[0]
205        VMLA.F32    q12, q4, d6[0]
206        VMLA.F32    q14, q4, d7[0]
207        VMLA.F32     q9, q5, d4[0]
208        VMLA.F32    q11, q5, d5[0]
209        VMLA.F32    q13, q5, d6[0]
210        VMLA.F32    q15, q5, d7[0]
211        VMLA.F32     q8, q6, d4[1]
212        VMLA.F32    q10, q6, d5[1]
213        VMLA.F32    q12, q6, d6[1]
214        VMLA.F32    q14, q6, d7[1]
215        VMLA.F32     q9, q7, d4[1]
216        VMLA.F32    q11, q7, d5[1]
217        TST         r5, 15
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        BNE         4f
223
224        .p2align 3
2253:
226        // Load params pointer
227        LDR    r5, [sp, 116]         // params
228
229        // Load min/max values
230        VLD1.32     {d4[],d5[]}, [r5]!
231        SUBS        r1, r1, 8
232        VLD1.32     {d6[],d7[]}, [r5]
233
234        // Clamp
235        VMAX.F32     q8,  q8, q2
236        VMAX.F32     q9,  q9, q2
237        VMAX.F32    q10, q10, q2
238        VMAX.F32    q11, q11, q2
239        VMAX.F32    q12, q12, q2
240        VMAX.F32    q13, q13, q2
241        VMAX.F32    q14, q14, q2
242        VMAX.F32    q15, q15, q2
243        VMIN.F32     q8,  q8, q3
244        VMIN.F32     q9,  q9, q3
245        VMIN.F32    q10, q10, q3
246        VMIN.F32    q11, q11, q3
247        VMIN.F32    q12, q12, q3
248        VMIN.F32    q13, q13, q3
249        VMIN.F32    q14, q14, q3
250        VMIN.F32    q15, q15, q3
251
252        // Store full 4 x 8
253        BLO         6f
254        VST1.32     {d16-d19}, [r11], r7
255        SUB         r0, r0, r2
256        VST1.32     {d20-d23}, [r4], r7
257        SUB         r10, r10, r2
258        VST1.32     {d24-d27}, [r8], r7
259        SUB         r12, r12, r2
260        VST1.32     {d28-d31}, [r6], r7
261        SUB         r3, r3, r2
262        BHI         0b
263
264        VPOP        {d8-d15}
265        POP         {r4, r5, r6, r7, r8, r9, r10, r11}
266        BX          lr
267
268        .p2align 3
2694:
270        // Is there a remainder?- 2 floats of A (8 bytes)
271        TST         r5, 8
272        BEQ         5f
273
274        // Remainder - 2 floats of A (8 bytes)
275        VLD1.32    {d0}, [r3]!       // A0
276        VLDM        r9!, {d8-d11}    // B0
277        VLD1.32    {d1}, [r12]!      // A1
278        VLD1.32    {d2}, [r10]!      // A2
279        VLD1.32    {d3}, [ r0]!      // A3
280
281        VMLA.F32     q8, q4, d0[0]
282        VMLA.F32     q9, q5, d0[0]
283        VMLA.F32    q10, q4, d1[0]
284        VMLA.F32    q11, q5, d1[0]
285        VLDM        r9!, {d12-d15}   // B1
286        VMLA.F32    q12, q4, d2[0]
287        VMLA.F32    q13, q5, d2[0]
288        VMLA.F32    q14, q4, d3[0]
289        VMLA.F32    q15, q5, d3[0]
290        VMLA.F32     q8, q6, d0[1]
291        VMLA.F32     q9, q7, d0[1]
292        VMLA.F32    q10, q6, d1[1]
293        VMLA.F32    q11, q7, d1[1]
294        VMLA.F32    q12, q6, d2[1]
295        VMLA.F32    q13, q7, d2[1]
296        VMLA.F32    q14, q6, d3[1]
297        VMLA.F32    q15, q7, d3[1]
298
299        // Is there a remainder?- 1 floats of A (4 bytes)
300        TST         r5, 4
301        BEQ         3b
302
3035:
304        // Remainder- 1 floats of A (4 bytes)
305        VLDM        r3!,  {s0}       // A0
306        VLDM        r9!, {d8-d11}    // B0
307        VLDM        r12!, {s2}       // A1
308        VLDM        r10!, {s4}       // A2
309        VLDM         r0!, {s6}       // A3
310        VMLA.F32     q8, q4, d0[0]
311        VMLA.F32     q9, q5, d0[0]
312        VMLA.F32    q10, q4, d1[0]
313        VMLA.F32    q11, q5, d1[0]
314        VMLA.F32    q12, q4, d2[0]
315        VMLA.F32    q13, q5, d2[0]
316        VMLA.F32    q14, q4, d3[0]
317        VMLA.F32    q15, q5, d3[0]
318        B           3b
319
320        // Store odd width
3216:
322        TST         r1, 4
323        BEQ         7f
324        VST1.32    {d16-d17}, [r11]!
325        VMOV         q8,  q9
326        VST1.32    {d20-d21},  [r4]!
327        VMOV        q10, q11
328        VST1.32    {d24-d25},  [r8]!
329        VMOV        q12, q13
330        VST1.32    {d28-d29},  [r6]!
331        VMOV        q14, q15
332
3337:
334        TST        r1, 2
335        BEQ        8f
336        VST1.32    {d16}, [r11]!
337        VMOV        d16, d17
338        VST1.32    {d20},  [r4]!
339        VMOV        d20, d21
340        VST1.32    {d24},  [r8]!
341        VMOV        d24, d25
342        VST1.32    {d28},  [r6]!
343        VMOV        d28, d29
344
3458:
346        TST         r1, 1
347        BEQ         9f
348        VST1.32    {d16[0]}, [r11]
349        VST1.32    {d20[0]},  [r4]
350        VST1.32    {d24[0]},  [r8]
351        VST1.32    {d28[0]},  [r6]
352
3539:
354        VPOP        {d8-d15}
355        POP         {r4, r5, r6, r7, r8, r9, r10, r11}
356        BX          lr
357
358END_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_pld_cortex_a75
359
360#ifdef __ELF__
361.section ".note.GNU-stack","",%progbits
362#endif
363
364