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