1// Auto-generated file. Do not edit!
2//   Template: src/qs8-igemm/4x8-aarch32-neon-mlal-lane-cortex-a7.S.in
3//   Generator: tools/xngen
4//
5// Copyright 2021 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
11#include <xnnpack/assembly.h>
12
13.syntax unified
14
15// void xnn_qc8_igemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_prfm_cortex_a7(
16//     size_t mr,                                     (r0)
17//     size_t nc,                                      r1 -> sp + 56
18//     size_t kc,                                     (r2) -> r5 -> sp + 60
19//     size_t ks,                                     (r3) -> sp + 64 -> r14
20//     const int8_t**restrict a,            sp + 104  -> r2
21//     const void*restrict w,              sp + 108  -> r9
22//     int8_t*restrict c,                   sp + 112  -> r11
23//     size_t cm_stride,                   sp + 116  -> (r6)
24//     size_t cn_stride,                   sp + 120  -> (r7)
25//     size_t a_offset,                    sp + 124 -> (r5)
26//     const int8_t* zero,                  sp + 128 -> (r7)
27//     xnn_qs8_minmax_params*params); sp + 132 -> (r5)
28
29// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
30
31// Register usage
32// A0   r3  d0-d1 q0
33// A1  r12  d2-d3 q1
34// A2  r10  d4-d5 q2
35// A3   r0  d6-d7 q3
36
37// B    r9  d8-d9 q4 q5
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// Unused d15
45
46// params structure is 10 bytes
47// struct {
48//   float magic_bias;                           d12[0]
49//   int32_t magic_bias_less_output_zero_point;  d12[1]
50//   int8_t output_min;                          d13[6]
51//   int8_t output_max;                          d13[7]
52// } xnn_qs8_minmax_params.neon;
53
54BEGIN_FUNCTION xnn_qc8_igemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_prfm_cortex_a7
55        # Push 104 bytes
56        # r1, r2 will be reloaded in outer loop.  r3 is ks
57        PUSH    {r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}   // +48
58        SUB     sp, sp, 8                           // +8
59        VPUSH   {d8-d13}                            // +48 = 104
60
61        LDR     r11, [sp, 112]          // c
62        LDR     r6, [sp, 116]           // cm_stride
63        LDR     r2, [sp, 104]           // a
64        LDR     r9, [sp, 108]           // w
65        LDR     r5, [sp, 132]           // params
66        MOV     r14, r3                 // p = ks
67
68        # Clamp C pointers
69        CMP     r0, 2                   // if mr >= 2
70        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
71        MOVLO   r4, r11                 // c1
72                                        // if mr > 2
73        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
74        MOVLS   r8, r4                  // c2
75        CMP     r0, 4                   // if mr >=4
76        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
77        MOVLO   r6, r8                  // c3
78
79        # Load params values
80        VLDM    r5!, {d12}              // QC8 neon params
81        VLD1.16 {d13[]}, [r5]
82
83        PLD     [r9,  64]               // Prefetch B
84        PLD     [r9, 128]
85        PLD     [r9, 192]
86        PLD     [r9, 256]
87        PLD     [r9, 320]
88        PLD     [r9, 384]
89
90        .p2align 3
910:
92        # Load initial bias from w into accumulators
93        VLDM    r9!, {d16-d19}          // Bias
94        VMOV    q10, q8
95        VMOV    q11, q9
96        STR     r1, [sp, 56]            // save nc
97        VMOV    q12, q8
98        VMOV    q13, q9
99        VMOV    q14, q8
100        VMOV    q15, q9
101
102        .p2align 3
1031:
104        # Load next 4 A pointers
105        LDR     r3, [r2,  0]
106        LDR     r12, [r2,  4]
107        LDR     r10, [r2,  8]
108        LDR     r0, [r2, 12]
109
110        # Add a_offset
111        LDR     r5, [sp, 124]           // a_offset
112        LDR     r7, [sp, 128]           // zero
113        ADD     r2, r2, 16
114        CMP     r3,  r7                 // if a0 == zero
115        ADD     r3,  r3, r5             // a0 += a_offset
116        MOVEQ   r3,  r7                 //   a0 = zero, else += a0 + a_offset
117        CMP     r12,  r7                // if a1 == zero
118        ADD     r12, r12, r5            // a1 += a_offset
119        MOVEQ   r12,  r7                //   a1 = zero, else += a1 + a_offset
120        CMP     r10,  r7                // if a2 == zero
121        ADD     r10, r10, r5            // a2 += a_offset
122        MOVEQ   r10,  r7                //   a2 = zero, else += a2 + a_offset
123        CMP     r0,  r7                 // if a3 == zero
124        ADD     r0,  r0, r5             // a3 += a_offset
125        LDR     r5, [sp, 60]            // kc
126        MOVEQ   r0,  r7                 //   a3 = zero, else += a3 + a_offset
127        SUBS    r5, r5, 8               // kc - 8
128        BLO     5f                      // less than 8 channels?
129
130        // Prologue - load 4A's and B0
131        VLD1.8  {d0},  [r3]!            // A0
132        VLD1.8  {d8},  [r9]!            // B0
133        SUBS    r5, r5, 8               // k = k - 8
134        VLD1.8  {d2}, [r12]!            // A1
135        VLD1.8  {d4}, [r10]!            // A2
136        VLD1.8  {d6},  [r0]!            // A3
137
138        BLO     3f                      // less than 8 channels?
139
140        // Main loop - 8 bytes
141        // 64 bytes for weights.
142        // 5 VMOVL = 4 A and 1 B = 5 cycles
143        // 7 blocks with VLD B, VMOVL, 8 VMLA = 10 cycles
144        // 1 blocks with VLD B, VMLA = 9 cycles
145        // total = 84 cycles
146        .p2align 3
1472:
148        // Extend - 5 cycles
149        VMOVL.S8 q0, d0
150        VMOVL.S8 q4, d8
151        PLD     [r9, 448]
152        VMOVL.S8 q1, d2
153        VMOVL.S8 q2, d4
154        VMOVL.S8 q3, d6
155
156        // BLOCK 0 - 10 cycles
157        VLD1.8  {d10},  [r9]!           // B1
158        VMLAL.S16 q8, d8, d0[0]
159        VMLAL.S16 q9, d9, d0[0]
160        VMLAL.S16 q10, d8, d2[0]
161        VMLAL.S16 q11, d9, d2[0]
162        VMOVL.S8 q5, d10
163        VMLAL.S16 q12, d8, d4[0]
164        VMLAL.S16 q13, d9, d4[0]
165        VMLAL.S16 q14, d8, d6[0]
166        VMLAL.S16 q15, d9, d6[0]
167
168        // BLOCK 1 - 10 cycles
169        VLD1.8  {d8},  [r9]!            // B2
170        VMLAL.S16 q8, d10, d0[1]
171        VMLAL.S16 q9, d11, d0[1]
172        VMLAL.S16 q10, d10, d2[1]
173        VMLAL.S16 q11, d11, d2[1]
174        VMOVL.S8 q4, d8
175        VMLAL.S16 q12, d10, d4[1]
176        VMLAL.S16 q13, d11, d4[1]
177        VMLAL.S16 q14, d10, d6[1]
178        VMLAL.S16 q15, d11, d6[1]
179
180        // BLOCK 2 - 10 cycles
181        VLD1.8  {d10},  [r9]!           // B3
182        VMLAL.S16 q8, d8, d0[2]
183        VMLAL.S16 q9, d9, d0[2]
184        VMLAL.S16 q10, d8, d2[2]
185        VMLAL.S16 q11, d9, d2[2]
186        VMOVL.S8 q5, d10
187        VMLAL.S16 q12, d8, d4[2]
188        VMLAL.S16 q13, d9, d4[2]
189        VMLAL.S16 q14, d8, d6[2]
190        VMLAL.S16 q15, d9, d6[2]
191
192        // BLOCK 3 - 10 cycles
193        VLD1.8  {d8},  [r9]!            // B4
194        VMLAL.S16 q8, d10, d0[3]
195        VMLAL.S16 q9, d11, d0[3]
196        VMLAL.S16 q10, d10, d2[3]
197        VMLAL.S16 q11, d11, d2[3]
198        VLD1.8  {d0},  [r3]!            // A0
199        VMOVL.S8 q4, d8
200        VMLAL.S16 q12, d10, d4[3]
201        VMLAL.S16 q13, d11, d4[3]
202        VMLAL.S16 q14, d10, d6[3]
203        VMLAL.S16 q15, d11, d6[3]
204
205        // BLOCK 4 - 10 cycles
206        VLD1.8  {d10},  [r9]!           // B5
207        VMLAL.S16 q8, d8, d1[0]
208        VMLAL.S16 q9, d9, d1[0]
209        VMLAL.S16 q10, d8, d3[0]
210        VMLAL.S16 q11, d9, d3[0]
211        VLD1.8  {d2}, [r12]!            // A1
212        VMOVL.S8 q5, d10
213        VMLAL.S16 q12, d8, d5[0]
214        VMLAL.S16 q13, d9, d5[0]
215        VMLAL.S16 q14, d8, d7[0]
216        VMLAL.S16 q15, d9, d7[0]
217
218        // BLOCK 5 - 10 cycles
219        VLD1.8  {d8},  [r9]!            // B6
220        VMLAL.S16 q8, d10, d1[1]
221        VMLAL.S16 q9, d11, d1[1]
222        VMLAL.S16 q10, d10, d3[1]
223        VMLAL.S16 q11, d11, d3[1]
224        VLD1.8  {d4}, [r10]!            // A2
225        VMOVL.S8 q4, d8
226        VMLAL.S16 q12, d10, d5[1]
227        VMLAL.S16 q13, d11, d5[1]
228        VMLAL.S16 q14, d10, d7[1]
229        VMLAL.S16 q15, d11, d7[1]
230
231        // BLOCK 6 - 10 cycles
232        VLD1.8  {d10},  [r9]!           // B7
233        VMLAL.S16 q8, d8, d1[2]
234        VMLAL.S16 q9, d9, d1[2]
235        VMLAL.S16 q10, d8, d3[2]
236        VMLAL.S16 q11, d9, d3[2]
237        VLD1.8  {d6},  [r0]!            // A3
238        VMOVL.S8 q5, d10
239        VMLAL.S16 q12, d8, d5[2]
240        VMLAL.S16 q13, d9, d5[2]
241        VMLAL.S16 q14, d8, d7[2]
242        VMLAL.S16 q15, d9, d7[2]
243
244        // BLOCK 7 - 9 cycles
245        VLD1.8  {d8},  [r9]!            // B0
246        VMLAL.S16 q8, d10, d1[3]
247        VMLAL.S16 q9, d11, d1[3]
248        VMLAL.S16 q10, d10, d3[3]
249        VMLAL.S16 q11, d11, d3[3]
250        VMLAL.S16 q12, d10, d5[3]
251        VMLAL.S16 q13, d11, d5[3]
252        SUBS    r5, r5, 8
253        VMLAL.S16 q14, d10, d7[3]
254        VMLAL.S16 q15, d11, d7[3]
255        BHS     2b
256
257        // Epilogue
258
259        .p2align 3
2603:
261        VMOVL.S8 q0, d0
262        VMOVL.S8 q4, d8
263        VMOVL.S8 q1, d2
264        VMOVL.S8 q2, d4
265        VMOVL.S8 q3, d6
266
267        VLD1.8  {d10},  [r9]!           // B1
268        VMLAL.S16 q8, d8, d0[0]
269        VMLAL.S16 q9, d9, d0[0]
270        VMLAL.S16 q10, d8, d2[0]
271        VMLAL.S16 q11, d9, d2[0]
272        VMOVL.S8 q5, d10
273        VMLAL.S16 q12, d8, d4[0]
274        VMLAL.S16 q13, d9, d4[0]
275        VMLAL.S16 q14, d8, d6[0]
276        VMLAL.S16 q15, d9, d6[0]
277
278        VLD1.8  {d8},  [r9]!            // B2
279        VMLAL.S16 q8, d10, d0[1]
280        VMLAL.S16 q9, d11, d0[1]
281        VMLAL.S16 q10, d10, d2[1]
282        VMLAL.S16 q11, d11, d2[1]
283        VMOVL.S8 q4, d8
284        VMLAL.S16 q12, d10, d4[1]
285        VMLAL.S16 q13, d11, d4[1]
286        VMLAL.S16 q14, d10, d6[1]
287        VMLAL.S16 q15, d11, d6[1]
288
289        VLD1.8  {d10},  [r9]!           // B3
290        VMLAL.S16 q8, d8, d0[2]
291        VMLAL.S16 q9, d9, d0[2]
292        VMLAL.S16 q10, d8, d2[2]
293        VMLAL.S16 q11, d9, d2[2]
294        VMOVL.S8 q5, d10
295        VMLAL.S16 q12, d8, d4[2]
296        VMLAL.S16 q13, d9, d4[2]
297        VMLAL.S16 q14, d8, d6[2]
298        VMLAL.S16 q15, d9, d6[2]
299
300        VLD1.8  {d8},  [r9]!            // B4
301        VMLAL.S16 q8, d10, d0[3]
302        VMLAL.S16 q9, d11, d0[3]
303        VMLAL.S16 q10, d10, d2[3]
304        VMLAL.S16 q11, d11, d2[3]
305        VMOVL.S8 q4, d8
306        VMLAL.S16 q12, d10, d4[3]
307        VMLAL.S16 q13, d11, d4[3]
308        VMLAL.S16 q14, d10, d6[3]
309        VMLAL.S16 q15, d11, d6[3]
310
311        VLD1.8  {d10},  [r9]!           // B5
312        VMLAL.S16 q8, d8, d1[0]
313        VMLAL.S16 q9, d9, d1[0]
314        VMLAL.S16 q10, d8, d3[0]
315        VMLAL.S16 q11, d9, d3[0]
316        VMOVL.S8 q5, d10
317        VMLAL.S16 q12, d8, d5[0]
318        VMLAL.S16 q13, d9, d5[0]
319        VMLAL.S16 q14, d8, d7[0]
320        VMLAL.S16 q15, d9, d7[0]
321
322        VLD1.8  {d8},  [r9]!            // B6
323        VMLAL.S16 q8, d10, d1[1]
324        VMLAL.S16 q9, d11, d1[1]
325        VMLAL.S16 q10, d10, d3[1]
326        VMLAL.S16 q11, d11, d3[1]
327        VMOVL.S8 q4, d8
328        VMLAL.S16 q12, d10, d5[1]
329        VMLAL.S16 q13, d11, d5[1]
330        VMLAL.S16 q14, d10, d7[1]
331        VMLAL.S16 q15, d11, d7[1]
332
333        VLD1.8  {d10},  [r9]!           // B7
334        VMLAL.S16 q8, d8, d1[2]
335        VMLAL.S16 q9, d9, d1[2]
336        VMLAL.S16 q10, d8, d3[2]
337        VMLAL.S16 q11, d9, d3[2]
338        VMOVL.S8 q5, d10
339        VMLAL.S16 q12, d8, d5[2]
340        VMLAL.S16 q13, d9, d5[2]
341        VMLAL.S16 q14, d8, d7[2]
342        VMLAL.S16 q15, d9, d7[2]
343
344        VMLAL.S16 q8, d10, d1[3]
345        VMLAL.S16 q9, d11, d1[3]
346        VMLAL.S16 q10, d10, d3[3]
347        VMLAL.S16 q11, d11, d3[3]
348        VMLAL.S16 q12, d10, d5[3]
349        VMLAL.S16 q13, d11, d5[3]
350        ADDS    r5, r5, 8
351        VMLAL.S16 q14, d10, d7[3]
352        VMLAL.S16 q15, d11, d7[3]
353
354        # Is there a remainder?- 1-7 bytes of A
355        BNE     6f
356
3574:
358        # ks loop
359        SUBS    r14, r14, 16            // ks -= MR * sizeof(void*)
360        BHI     1b
361
362        LDR     r7, [sp, 120]           // cn_stride
363        LDR     r14, [sp, 64]           // p = ks
364
365        # QC8 FP32 quantization
366        VLD1.8  {q0-q1},  [r9]!
367
368        VDUP.32 q2, d12[0]              // magic_bias
369        VDUP.32 q3, d12[1]              // magic_bias_less_output_zero_point
370
371        VCVT.F32.S32 q8,  q8
372        VCVT.F32.S32 q9,  q9
373        VCVT.F32.S32 q10, q10
374        VCVT.F32.S32 q11, q11
375        VCVT.F32.S32 q12, q12
376        VCVT.F32.S32 q13, q13
377        VCVT.F32.S32 q14, q14
378        VCVT.F32.S32 q15, q15
379
380        VMUL.F32 q8,  q8, q0            // multiplier
381        VMUL.F32 q9,  q9, q1
382        VMUL.F32 q10, q10, q0
383        VMUL.F32 q11, q11, q1
384        VMUL.F32 q12, q12, q0
385        VMUL.F32 q13, q13, q1
386        VMUL.F32 q14, q14, q0
387        VMUL.F32 q15, q15, q1
388
389        VADD.F32 q8,  q8, q2            // magic_bias
390        VADD.F32 q9,  q9, q2
391        VADD.F32 q10, q10, q2
392        VADD.F32 q11, q11, q2
393        VADD.F32 q12, q12, q2
394        VADD.F32 q13, q13, q2
395        VADD.F32 q14, q14, q2
396        VADD.F32 q15, q15, q2
397
398        VQSUB.S32 q8,  q8, q3           // magic_bias_less_output_zero_point
399        VQSUB.S32 q9,  q9, q3
400        VQSUB.S32 q10, q10, q3
401        VQSUB.S32 q11, q11, q3
402        VQSUB.S32 q12, q12, q3
403        VQSUB.S32 q13, q13, q3
404        VQSUB.S32 q14, q14, q3
405        VQSUB.S32 q15, q15, q3
406
407
408        VQMOVN.S32 d16, q8
409        VQMOVN.S32 d17, q9
410        VQMOVN.S32 d18, q10
411        VQMOVN.S32 d19, q11
412        VQMOVN.S32 d20, q12
413        VQMOVN.S32 d21, q13
414        VQMOVN.S32 d22, q14
415        VQMOVN.S32 d23, q15
416
417
418        LDR     r1, [sp, 56]            // restore nc
419        VDUP.8  q12, d13[6]             // output_min
420
421        VQMOVN.S16 d0,  q8
422        VQMOVN.S16 d1,  q9
423        VQMOVN.S16 d2, q10
424        VQMOVN.S16 d3, q11
425
426        VDUP.8  q13, d13[7]             // output_max
427
428        VMAX.S8 q0, q0, q12
429        VMAX.S8 q1, q1, q12
430
431        SUBS    r1, r1, 8               // nc -= 8
432
433        VMIN.S8 q0, q0, q13
434        VMIN.S8 q1, q1, q13
435
436        # Store full 4 x 8
437        BLO     7f
438        VST1.8  {d3}, [r6], r7
439        VST1.8  {d2}, [r8], r7
440        VST1.8  {d1}, [r4], r7
441        VST1.8  {d0}, [r11], r7
442        SUB     r2, r2, r14             // a -= ks
443        BHI     0b
444
445        VPOP    {d8-d13}
446        ADD     sp, sp, 20              // skip pad of 8, r1, r2, r3
447        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
448
449        # Remainder- 1 to 7 bytes of A
450        .p2align 3
4515:
452        AND     r5, r5, 7               // kc remainder 1 to 7
4536:
454        VLD1.8  {d0},  [r3]
455        VLD1.8  {d8},  [r9]!
456        VLD1.8  {d2}, [r12]
457        VLD1.8  {d4}, [r10]
458        VLD1.8  {d6},  [r0]
459
460        VMOVL.S8 q0, d0
461        VMOVL.S8 q4, d8
462        VMOVL.S8 q1, d2
463        VMOVL.S8 q2, d4
464        VMOVL.S8 q3, d6
465        VMLAL.S16 q8, d8, d0[0]
466        VMLAL.S16 q9, d9, d0[0]
467        VMLAL.S16 q10, d8, d2[0]
468        VMLAL.S16 q11, d9, d2[0]
469        VMLAL.S16 q12, d8, d4[0]
470        VMLAL.S16 q13, d9, d4[0]
471        VMLAL.S16 q14, d8, d6[0]
472        VMLAL.S16 q15, d9, d6[0]
473        CMP     r5, 2
474        BLO     4b
475
476        VLD1.8  {d8},  [r9]!
477        VMOVL.S8 q4, d8
478        VMLAL.S16 q8, d8, d0[1]
479        VMLAL.S16 q9, d9, d0[1]
480        VMLAL.S16 q10, d8, d2[1]
481        VMLAL.S16 q11, d9, d2[1]
482        VMLAL.S16 q12, d8, d4[1]
483        VMLAL.S16 q13, d9, d4[1]
484        VMLAL.S16 q14, d8, d6[1]
485        VMLAL.S16 q15, d9, d6[1]
486        BEQ     4b
487
488        VLD1.8  {d8},  [r9]!
489        VMOVL.S8 q4, d8
490        VMLAL.S16 q8, d8, d0[2]
491        VMLAL.S16 q9, d9, d0[2]
492        VMLAL.S16 q10, d8, d2[2]
493        VMLAL.S16 q11, d9, d2[2]
494        VMLAL.S16 q12, d8, d4[2]
495        VMLAL.S16 q13, d9, d4[2]
496        VMLAL.S16 q14, d8, d6[2]
497        VMLAL.S16 q15, d9, d6[2]
498        CMP     r5, 4
499        BLO     4b
500
501        VLD1.8  {d8},  [r9]!
502        VMOVL.S8 q4, d8
503        VMLAL.S16 q8, d8, d0[3]
504        VMLAL.S16 q9, d9, d0[3]
505        VMLAL.S16 q10, d8, d2[3]
506        VMLAL.S16 q11, d9, d2[3]
507        VMLAL.S16 q12, d8, d4[3]
508        VMLAL.S16 q13, d9, d4[3]
509        VMLAL.S16 q14, d8, d6[3]
510        VMLAL.S16 q15, d9, d6[3]
511        BEQ     4b
512
513        VLD1.8  {d8},  [r9]!
514        VMOVL.S8 q4, d8
515        VMLAL.S16 q8, d8, d1[0]
516        VMLAL.S16 q9, d9, d1[0]
517        VMLAL.S16 q10, d8, d3[0]
518        VMLAL.S16 q11, d9, d3[0]
519        VMLAL.S16 q12, d8, d5[0]
520        VMLAL.S16 q13, d9, d5[0]
521        VMLAL.S16 q14, d8, d7[0]
522        VMLAL.S16 q15, d9, d7[0]
523        CMP     r5, 6
524        BLO     4b
525
526        VLD1.8  {d8},  [r9]!
527        VMOVL.S8 q4, d8
528        VMLAL.S16 q8, d8, d1[1]
529        VMLAL.S16 q9, d9, d1[1]
530        VMLAL.S16 q10, d8, d3[1]
531        VMLAL.S16 q11, d9, d3[1]
532        VMLAL.S16 q12, d8, d5[1]
533        VMLAL.S16 q13, d9, d5[1]
534        VMLAL.S16 q14, d8, d7[1]
535        VMLAL.S16 q15, d9, d7[1]
536        BEQ     4b
537
538        VLD1.8  {d8},  [r9]!
539        VMOVL.S8 q4, d8
540        VMLAL.S16 q8, d8, d1[2]
541        VMLAL.S16 q9, d9, d1[2]
542        VMLAL.S16 q10, d8, d3[2]
543        VMLAL.S16 q11, d9, d3[2]
544        VMLAL.S16 q12, d8, d5[2]
545        VMLAL.S16 q13, d9, d5[2]
546        VMLAL.S16 q14, d8, d7[2]
547        VMLAL.S16 q15, d9, d7[2]
548        B       4b
549
550        # Store odd width
551        .p2align 3
5527:
553        TST     r1, 4
554        BEQ     8f
555        VST1.32 {d3[0]}, [r6]!
556        VST1.32 {d2[0]}, [r8]!
557        VST1.32 {d1[0]}, [r4]!
558        VST1.32 {d0[0]}, [r11]!
559        VEXT.8  q1, q1, q1, 4
560        VEXT.8  q0, q0, q0, 4
5618:
562        TST     r1, 2
563        BEQ     9f
564        VST1.16 {d3[0]}, [r6]!
565        VST1.16 {d2[0]}, [r8]!
566        VST1.16 {d1[0]}, [r4]!
567        VST1.16 {d0[0]}, [r11]!
568        VEXT.8  q1, q1, q1, 2
569        VEXT.8  q0, q0, q0, 2
570
5719:
572        TST     r1, 1
573        BEQ     10f
574        VST1.8  {d3[0]}, [r6]
575        VST1.8  {d2[0]}, [r8]
576        VST1.8  {d1[0]}, [r4]
577        VST1.8  {d0[0]}, [r11]
578
57910:
580        VPOP    {d8-d13}
581        ADD     sp, sp, 20              // skip pad of 8, r1, r2, r3
582        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
583
584END_FUNCTION xnn_qc8_igemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_prfm_cortex_a7
585
586#ifdef __ELF__
587.section ".note.GNU-stack","",%progbits
588#endif
589