xref: /aosp_15_r20/external/XNNPACK/src/qu8-gemm/gen/4x8-minmax-rndnu-aarch32-neon-mlal-lane-ld64.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/qs8-gemm/4x8-aarch32-neon-mlal-lane-ld64.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_gemm_minmax_rndnu_ukernel_4x8__aarch32_neon_mlal_lane_ld64(
16//     size_t mr,                            r0
17//     size_t nc,                            r1
18//     size_t kc,                            r2 -> r5
19//     const uint8_t*restrict a,              r3
20//     size_t a_stride,           sp + 72 -> (r7)
21//     const void*restrict w,     sp + 76 -> r9
22//     uint8_t*restrict c,         sp + 80 -> r11
23//     size_t cm_stride,          sp + 84 -> (r6)
24//     size_t cn_stride,          sp + 88 -> r7
25//     xnn_qs8_conv_minmax_params params)  sp + 92 -> (r5)
26
27// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
28
29// Register usage
30// A0   r3  d0-d1 q0
31// A1  r12  d2-d3 q1
32// A2  r10  d4-d5 q2
33// A3   r0  d6-d7 q3
34
35// B    r9  d10-d11 q5
36
37// C0  r11 d16-d17  q8  d18-d19  q9
38// C1   r4 d20-d21 q10  d22-d23 q11
39// C2   r8 d24-d25 q12  d26-d27 q13
40// C3   r6 d28-d29 q14  d30-d31 q15
41
42// Unused d13-d15
43
44# params structure is 20 bytes
45#  struct {
46#    uint8_t kernel_zero_point[4];  d14
47#    int32_t right_pre_shift;       d12[0]
48#    int32_t multiplier;            d12[1]
49#    int32_t right_post_shift;      d13[0]
50#    int16_t output_zero_point;     d13[2]
51#    uint8_t output_min;            d13[6]
52#    uint8_t output_max;            d13[7]
53#  } rndnu_neon;
54
55BEGIN_FUNCTION xnn_qu8_gemm_minmax_rndnu_ukernel_4x8__aarch32_neon_mlal_lane_ld64
56        # Push 72 bytes
57        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
58        VPUSH   {d10-d14}                           // +40 = 72
59
60        LDR     r7, [sp, 72]            // a_stride
61        LDR     r11, [sp, 80]           // c
62        LDR     r6, [sp, 84]            // cm_stride
63        LDR     r9, [sp, 76]            // w
64        LDR     r5, [sp, 92]            // params
65
66        # Clamp A and C pointers
67        CMP     r0, 2                   // if mr >= 2
68        ADD     r12, r3, r7             //   a1 = a0 + a_stride
69        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
70        MOVLO   r12, r3                 // a1
71        MOVLO   r4, r11                 // c1
72                                        // if mr > 2
73        ADD     r10, r12, r7            //   a2 = a1 + a_stride
74        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
75        MOVLS   r10, r12                // a2
76        MOVLS   r8, r4                  // c2
77
78        CMP     r0, 4                   // if mr >=4
79        ADD     r0, r10, r7             //   a3 = a2 + a_stride
80        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
81        MOVLO   r0, r10                 // a3
82        MOVLO   r6, r8                  // c3
83
84        # Load params values
85        VLD1.32 {d14[]}, [r5]!          // QU8 kernel_zero_point
86        VLDM    r5, {d12-d13}           // RNDNU params
87        LDR     r7, [sp, 88]            // cn_stride
88
89
90        .p2align 3
910:
92        # Load initial bias from w into accumulators
93        VLDM    r9!, {d16-d19}          // Bias
94        SUBS    r5, r2, 8               // k = kc - 8
95
96        VMOV    q10, q8
97        VMOV    q11, q9
98        VMOV    q12, q8
99        VMOV    q13, q9
100        VMOV    q14, q8
101        VMOV    q15, q9
102        BLO     3f                      // less than 8 channels?
103
104        # Main loop - 8 bytes
105        # 64 bytes for weights.
106        .p2align 3
1071:
108        VLD1.8  {d0},  [r3]!            // A0
109        VLD1.8  {d10},  [r9]!            // B
110        VLD1.8  {d2}, [r12]!            // A1
111        VLD1.8  {d4}, [r10]!            // A2
112        VLD1.8  {d6},  [r0]!            // A3
113        SUBS    r5, r5, 8
114        VMOVL.U8 q0, d0
115        VSUBL.U8 q5, d10, d14
116        VMOVL.U8 q1, d2
117        VMOVL.U8 q2, d4
118        VMOVL.U8 q3, d6
119        VMLAL.S16 q8, d10, d0[0]
120        VMLAL.S16 q9, d11, d0[0]
121        VMLAL.S16 q10, d10, d2[0]
122        VMLAL.S16 q11, d11, d2[0]
123        VMLAL.S16 q12, d10, d4[0]
124        VMLAL.S16 q13, d11, d4[0]
125        VMLAL.S16 q14, d10, d6[0]
126        VMLAL.S16 q15, d11, d6[0]
127
128        VLD1.8  {d10},  [r9]!
129
130        VSUBL.U8 q5, d10, d14
131        VMLAL.S16 q8, d10, d0[1]
132        VMLAL.S16 q9, d11, d0[1]
133        VMLAL.S16 q10, d10, d2[1]
134        VMLAL.S16 q11, d11, d2[1]
135        VMLAL.S16 q12, d10, d4[1]
136        VMLAL.S16 q13, d11, d4[1]
137        VMLAL.S16 q14, d10, d6[1]
138        VMLAL.S16 q15, d11, d6[1]
139
140        VLD1.8  {d10},  [r9]!
141        VSUBL.U8 q5, d10, d14
142        VMLAL.S16 q8, d10, d0[2]
143        VMLAL.S16 q9, d11, d0[2]
144        VMLAL.S16 q10, d10, d2[2]
145        VMLAL.S16 q11, d11, d2[2]
146        VMLAL.S16 q12, d10, d4[2]
147        VMLAL.S16 q13, d11, d4[2]
148        VMLAL.S16 q14, d10, d6[2]
149        VMLAL.S16 q15, d11, d6[2]
150
151        VLD1.8  {d10},  [r9]!
152        VSUBL.U8 q5, d10, d14
153        VMLAL.S16 q8, d10, d0[3]
154        VMLAL.S16 q9, d11, d0[3]
155        VMLAL.S16 q10, d10, d2[3]
156        VMLAL.S16 q11, d11, d2[3]
157        VMLAL.S16 q12, d10, d4[3]
158        VMLAL.S16 q13, d11, d4[3]
159        VMLAL.S16 q14, d10, d6[3]
160        VMLAL.S16 q15, d11, d6[3]
161
162        VLD1.8  {d10},  [r9]!
163        VSUBL.U8 q5, d10, d14
164        VMLAL.S16 q8, d10, d1[0]
165        VMLAL.S16 q9, d11, d1[0]
166        VMLAL.S16 q10, d10, d3[0]
167        VMLAL.S16 q11, d11, d3[0]
168        VMLAL.S16 q12, d10, d5[0]
169        VMLAL.S16 q13, d11, d5[0]
170        VMLAL.S16 q14, d10, d7[0]
171        VMLAL.S16 q15, d11, d7[0]
172
173        VLD1.8  {d10},  [r9]!
174        VSUBL.U8 q5, d10, d14
175        VMLAL.S16 q8, d10, d1[1]
176        VMLAL.S16 q9, d11, d1[1]
177        VMLAL.S16 q10, d10, d3[1]
178        VMLAL.S16 q11, d11, d3[1]
179        VMLAL.S16 q12, d10, d5[1]
180        VMLAL.S16 q13, d11, d5[1]
181        VMLAL.S16 q14, d10, d7[1]
182        VMLAL.S16 q15, d11, d7[1]
183
184        VLD1.8  {d10},  [r9]!
185        VSUBL.U8 q5, d10, d14
186        VMLAL.S16 q8, d10, d1[2]
187        VMLAL.S16 q9, d11, d1[2]
188        VMLAL.S16 q10, d10, d3[2]
189        VMLAL.S16 q11, d11, d3[2]
190        VMLAL.S16 q12, d10, d5[2]
191        VMLAL.S16 q13, d11, d5[2]
192        VMLAL.S16 q14, d10, d7[2]
193        VMLAL.S16 q15, d11, d7[2]
194
195        VLD1.8  {d10},  [r9]!
196        VSUBL.U8 q5, d10, d14
197        VMLAL.S16 q8, d10, d1[3]
198        VMLAL.S16 q9, d11, d1[3]
199        VMLAL.S16 q10, d10, d3[3]
200        VMLAL.S16 q11, d11, d3[3]
201        VMLAL.S16 q12, d10, d5[3]
202        VMLAL.S16 q13, d11, d5[3]
203        VMLAL.S16 q14, d10, d7[3]
204        VMLAL.S16 q15, d11, d7[3]
205        BHS     1b
206
207        # Is there a remainder?- 1-7 bytes of A
208        ADDS    r5, r5, 8
209        BNE     3f
210
2112:
212        # RNDNU quantization
213        VDUP.32 q0, d12[0]              // right_pre_shift
214
215        VQSHL.S32 q8,  q8, q0
216        VQSHL.S32 q9,  q9, q0
217        VQSHL.S32 q10, q10, q0
218        VQSHL.S32 q11, q11, q0
219        VQSHL.S32 q12, q12, q0
220        VQSHL.S32 q13, q13, q0
221        VQSHL.S32 q14, q14, q0
222        VQSHL.S32 q15, q15, q0
223
224        VDUP.32 q2, d13[0]              // right_post_shift
225
226        VQDMULH.S32 q8,  q8, d12[1]     // multiplier
227        VQDMULH.S32 q9,  q9, d12[1]
228        VQDMULH.S32 q10, q10, d12[1]
229        VQDMULH.S32 q11, q11, d12[1]
230        VQDMULH.S32 q12, q12, d12[1]
231        VQDMULH.S32 q13, q13, d12[1]
232        VQDMULH.S32 q14, q14, d12[1]
233        VQDMULH.S32 q15, q15, d12[1]
234
235        VRSHL.S32 q8,  q8, q2
236        VRSHL.S32 q9,  q9, q2
237        VRSHL.S32 q10, q10, q2
238        VRSHL.S32 q11, q11, q2
239        VRSHL.S32 q12, q12, q2
240        VRSHL.S32 q13, q13, q2
241        VRSHL.S32 q14, q14, q2
242        VRSHL.S32 q15, q15, q2
243
244        VDUP.16 q0, d13[2]              // output_zero_point
245
246        VQMOVN.S32 d16, q8
247        VQMOVN.S32 d17, q9
248        VQMOVN.S32 d18, q10
249        VQMOVN.S32 d19, q11
250        VQMOVN.S32 d20, q12
251        VQMOVN.S32 d21, q13
252        VQMOVN.S32 d22, q14
253        VQMOVN.S32 d23, q15
254
255        VQADD.S16 q8,  q8, q0
256        VQADD.S16 q9,  q9, q0
257        VQADD.S16 q10, q10, q0
258        VQADD.S16 q11, q11, q0
259
260        VDUP.8  q12, d13[6]             // output_min
261
262        VQMOVUN.S16 d0,  q8
263        VQMOVUN.S16 d1,  q9
264        VQMOVUN.S16 d2, q10
265        VQMOVUN.S16 d3, q11
266
267        VDUP.8  q13, d13[7]             // output_max
268
269        VMAX.U8 q0, q0, q12
270        VMAX.U8 q1, q1, q12
271
272        SUBS    r1, r1, 8
273
274        VMIN.U8 q0, q0, q13
275        VMIN.U8 q1, q1, q13
276
277        # Store full 4 x 8
278        BLO     4f
279        VST1.8  {d0}, [r11], r7
280        SUB     r3, r3, r2
281        VST1.8  {d1}, [r4], r7
282        SUB     r12, r12, r2
283        VST1.8  {d2}, [r8], r7
284        SUB     r10, r10, r2
285        VST1.8  {d3}, [r6], r7
286        SUB     r0, r0, r2
287        BHI     0b
288
289        VPOP    {d10-d14}
290        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
291        BX      lr
292
293        # Remainder- 1 to 7 bytes of A
294        .p2align 3
2953:
296        AND     r5, r5, 7               // kc remainder 1 to 7
297
298        VLD1.8  {d0},  [r3], r5
299        VLD1.8  {d10},  [r9]!
300        VLD1.8  {d2}, [r12], r5
301        VLD1.8  {d4}, [r10], r5
302        VLD1.8  {d6},  [r0], r5
303
304        VMOVL.U8 q0, d0
305        VSUBL.U8 q5, d10, d14
306        VMOVL.U8 q1, d2
307        VMOVL.U8 q2, d4
308        VMOVL.U8 q3, d6
309        VMLAL.S16 q8, d10, d0[0]
310        VMLAL.S16 q9, d11, d0[0]
311        VMLAL.S16 q10, d10, d2[0]
312        VMLAL.S16 q11, d11, d2[0]
313        VMLAL.S16 q12, d10, d4[0]
314        VMLAL.S16 q13, d11, d4[0]
315        VMLAL.S16 q14, d10, d6[0]
316        VMLAL.S16 q15, d11, d6[0]
317        CMP     r5, 2
318        BLO     2b
319
320        VLD1.8  {d10},  [r9]!
321        VSUBL.U8 q5, d10, d14
322        VMLAL.S16 q8, d10, d0[1]
323        VMLAL.S16 q9, d11, d0[1]
324        VMLAL.S16 q10, d10, d2[1]
325        VMLAL.S16 q11, d11, d2[1]
326        VMLAL.S16 q12, d10, d4[1]
327        VMLAL.S16 q13, d11, d4[1]
328        VMLAL.S16 q14, d10, d6[1]
329        VMLAL.S16 q15, d11, d6[1]
330        BEQ     2b
331
332        VLD1.8  {d10},  [r9]!
333        VSUBL.U8 q5, d10, d14
334        VMLAL.S16 q8, d10, d0[2]
335        VMLAL.S16 q9, d11, d0[2]
336        VMLAL.S16 q10, d10, d2[2]
337        VMLAL.S16 q11, d11, d2[2]
338        VMLAL.S16 q12, d10, d4[2]
339        VMLAL.S16 q13, d11, d4[2]
340        VMLAL.S16 q14, d10, d6[2]
341        VMLAL.S16 q15, d11, d6[2]
342        CMP     r5, 4
343        BLO     2b
344
345        VLD1.8  {d10},  [r9]!
346        VSUBL.U8 q5, d10, d14
347        VMLAL.S16 q8, d10, d0[3]
348        VMLAL.S16 q9, d11, d0[3]
349        VMLAL.S16 q10, d10, d2[3]
350        VMLAL.S16 q11, d11, d2[3]
351        VMLAL.S16 q12, d10, d4[3]
352        VMLAL.S16 q13, d11, d4[3]
353        VMLAL.S16 q14, d10, d6[3]
354        VMLAL.S16 q15, d11, d6[3]
355        BEQ     2b
356
357        VLD1.8  {d10},  [r9]!
358        VSUBL.U8 q5, d10, d14
359        VMLAL.S16 q8, d10, d1[0]
360        VMLAL.S16 q9, d11, d1[0]
361        VMLAL.S16 q10, d10, d3[0]
362        VMLAL.S16 q11, d11, d3[0]
363        VMLAL.S16 q12, d10, d5[0]
364        VMLAL.S16 q13, d11, d5[0]
365        VMLAL.S16 q14, d10, d7[0]
366        VMLAL.S16 q15, d11, d7[0]
367        CMP     r5, 6
368        BLO     2b
369
370        VLD1.8  {d10},  [r9]!
371        VSUBL.U8 q5, d10, d14
372        VMLAL.S16 q8, d10, d1[1]
373        VMLAL.S16 q9, d11, d1[1]
374        VMLAL.S16 q10, d10, d3[1]
375        VMLAL.S16 q11, d11, d3[1]
376        VMLAL.S16 q12, d10, d5[1]
377        VMLAL.S16 q13, d11, d5[1]
378        VMLAL.S16 q14, d10, d7[1]
379        VMLAL.S16 q15, d11, d7[1]
380        BEQ     2b
381
382        VLD1.8  {d10},  [r9]!
383        VSUBL.U8 q5, d10, d14
384        VMLAL.S16 q8, d10, d1[2]
385        VMLAL.S16 q9, d11, d1[2]
386        VMLAL.S16 q10, d10, d3[2]
387        VMLAL.S16 q11, d11, d3[2]
388        VMLAL.S16 q12, d10, d5[2]
389        VMLAL.S16 q13, d11, d5[2]
390        VMLAL.S16 q14, d10, d7[2]
391        VMLAL.S16 q15, d11, d7[2]
392        B       2b
393
394        # Store odd width
395        .p2align 3
3964:
397        TST     r1, 4
398        BEQ     5f
399        VST1.32 {d0[0]}, [r11]!
400        VST1.32 {d1[0]}, [r4]!
401        VST1.32 {d2[0]}, [r8]!
402        VST1.32 {d3[0]}, [r6]!
403        VEXT.8  q0, q0, q0, 4
404        VEXT.8  q1, q1, q1, 4
4055:
406        TST     r1, 2
407        BEQ     6f
408        VST1.16 {d0[0]}, [r11]!
409        VST1.16 {d1[0]}, [r4]!
410        VST1.16 {d2[0]}, [r8]!
411        VST1.16 {d3[0]}, [r6]!
412        VEXT.8  q0, q0, q0, 2
413        VEXT.8  q1, q1, q1, 2
414
4156:
416        TST     r1, 1
417        BEQ     7f
418        VST1.8  {d0[0]}, [r11]
419        VST1.8  {d1[0]}, [r4]
420        VST1.8  {d2[0]}, [r8]
421        VST1.8  {d3[0]}, [r6]
422
4237:
424        VPOP    {d10-d14}
425        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
426        BX      lr
427
428END_FUNCTION xnn_qu8_gemm_minmax_rndnu_ukernel_4x8__aarch32_neon_mlal_lane_ld64
429
430#ifdef __ELF__
431.section ".note.GNU-stack","",%progbits
432#endif
433
434