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