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