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