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