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