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_prfm_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_prfm_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        PLD     [r9,  64]               // Prefetch B
86        PLD     [r9, 128]
87        PLD     [r9, 192]
88        PLD     [r9, 256]
89        PLD     [r9, 320]
90        PLD     [r9, 384]
91
92        .p2align 3
930:
94        # Load initial bias from w into accumulators
95        VLDM    r9!, {d16-d19}          // Bias
96        SUBS    r5, r2, 8               // k = kc - 8
97
98        VMOV    q10, q8
99        PLD     [r3,  64]               // Prefetch A
100        VMOV    q11, q9
101        PLD     [r12, 64]
102        VMOV    q12, q8
103        PLD     [r10, 64]
104        VMOV    q13, q9
105        PLD     [r0,  64]
106        VMOV    q14, q8
107        VMOV    q15, q9
108        BLO     3f                      // less than 8 channels?
109
110        # Main loop - 8 bytes
111        # 64 bytes for weights.
112        .p2align 3
1131:
114        VLD1.8  {d0},  [r3]!            // A0
115        VLD1.8  {d10},  [r9]!            // B
116        VLD1.8  {d2}, [r12]!            // A1
117        VLD1.8  {d4}, [r10]!            // A2
118        VLD1.8  {d6},  [r0]!            // A3
119        SUBS    r5, r5, 8
120        PLD     [r3, 128]
121        VMOVL.S8 q0, d0
122        PLD     [r12, 128]
123        VMOVL.S8 q5, d10
124        PLD     [r10, 128]
125        VMOVL.S8 q1, d2
126        PLD     [r0, 128]
127        VMOVL.S8 q2, d4
128        PLD     [r9, 448]
129        VMOVL.S8 q3, d6
130        VMLAL.S16 q8, d10, d0[0]
131        VMLAL.S16 q9, d11, d0[0]
132        VMLAL.S16 q10, d10, d2[0]
133        VMLAL.S16 q11, d11, d2[0]
134        VMLAL.S16 q12, d10, d4[0]
135        VMLAL.S16 q13, d11, d4[0]
136        VMLAL.S16 q14, d10, d6[0]
137        VMLAL.S16 q15, d11, d6[0]
138
139        VLD1.8  {d10},  [r9]!
140
141        VMOVL.S8 q5, d10
142        VMLAL.S16 q8, d10, d0[1]
143        VMLAL.S16 q9, d11, d0[1]
144        VMLAL.S16 q10, d10, d2[1]
145        VMLAL.S16 q11, d11, d2[1]
146        VMLAL.S16 q12, d10, d4[1]
147        VMLAL.S16 q13, d11, d4[1]
148        VMLAL.S16 q14, d10, d6[1]
149        VMLAL.S16 q15, d11, d6[1]
150
151        VLD1.8  {d10},  [r9]!
152        VMOVL.S8 q5, d10
153        VMLAL.S16 q8, d10, d0[2]
154        VMLAL.S16 q9, d11, d0[2]
155        VMLAL.S16 q10, d10, d2[2]
156        VMLAL.S16 q11, d11, d2[2]
157        VMLAL.S16 q12, d10, d4[2]
158        VMLAL.S16 q13, d11, d4[2]
159        VMLAL.S16 q14, d10, d6[2]
160        VMLAL.S16 q15, d11, d6[2]
161
162        VLD1.8  {d10},  [r9]!
163        VMOVL.S8 q5, d10
164        VMLAL.S16 q8, d10, d0[3]
165        VMLAL.S16 q9, d11, d0[3]
166        VMLAL.S16 q10, d10, d2[3]
167        VMLAL.S16 q11, d11, d2[3]
168        VMLAL.S16 q12, d10, d4[3]
169        VMLAL.S16 q13, d11, d4[3]
170        VMLAL.S16 q14, d10, d6[3]
171        VMLAL.S16 q15, d11, d6[3]
172
173        VLD1.8  {d10},  [r9]!
174        VMOVL.S8 q5, d10
175        VMLAL.S16 q8, d10, d1[0]
176        VMLAL.S16 q9, d11, d1[0]
177        VMLAL.S16 q10, d10, d3[0]
178        VMLAL.S16 q11, d11, d3[0]
179        VMLAL.S16 q12, d10, d5[0]
180        VMLAL.S16 q13, d11, d5[0]
181        VMLAL.S16 q14, d10, d7[0]
182        VMLAL.S16 q15, d11, d7[0]
183
184        VLD1.8  {d10},  [r9]!
185        VMOVL.S8 q5, d10
186        VMLAL.S16 q8, d10, d1[1]
187        VMLAL.S16 q9, d11, d1[1]
188        VMLAL.S16 q10, d10, d3[1]
189        VMLAL.S16 q11, d11, d3[1]
190        VMLAL.S16 q12, d10, d5[1]
191        VMLAL.S16 q13, d11, d5[1]
192        VMLAL.S16 q14, d10, d7[1]
193        VMLAL.S16 q15, d11, d7[1]
194
195        VLD1.8  {d10},  [r9]!
196        VMOVL.S8 q5, d10
197        VMLAL.S16 q8, d10, d1[2]
198        VMLAL.S16 q9, d11, d1[2]
199        VMLAL.S16 q10, d10, d3[2]
200        VMLAL.S16 q11, d11, d3[2]
201        VMLAL.S16 q12, d10, d5[2]
202        VMLAL.S16 q13, d11, d5[2]
203        VMLAL.S16 q14, d10, d7[2]
204        VMLAL.S16 q15, d11, d7[2]
205
206        VLD1.8  {d10},  [r9]!
207        VMOVL.S8 q5, d10
208        VMLAL.S16 q8, d10, d1[3]
209        VMLAL.S16 q9, d11, d1[3]
210        VMLAL.S16 q10, d10, d3[3]
211        VMLAL.S16 q11, d11, d3[3]
212        VMLAL.S16 q12, d10, d5[3]
213        VMLAL.S16 q13, d11, d5[3]
214        VMLAL.S16 q14, d10, d7[3]
215        VMLAL.S16 q15, d11, d7[3]
216        BHS     1b
217
218        # Is there a remainder?- 1-7 bytes of A
219        ADDS    r5, r5, 8
220        BNE     3f
221
2222:
223        # QC8 FP32 quantization
224        VLD1.8  {q0-q1},  [r9]!
225
226        VCVT.F32.S32 q8,  q8
227        VCVT.F32.S32 q9,  q9
228        VCVT.F32.S32 q10, q10
229        VCVT.F32.S32 q11, q11
230        VCVT.F32.S32 q12, q12
231        VCVT.F32.S32 q13, q13
232        VCVT.F32.S32 q14, q14
233        VCVT.F32.S32 q15, q15
234
235        VMUL.F32 q8,  q8, q0            // multiplier
236        VMUL.F32 q9,  q9, q1
237        VMUL.F32 q10, q10, q0
238        VMUL.F32 q11, q11, q1
239        VMUL.F32 q12, q12, q0
240        VMUL.F32 q13, q13, q1
241        VMUL.F32 q14, q14, q0
242        VMUL.F32 q15, q15, q1
243
244        VCVTN.S32.F32 q8,  q8
245        VCVTN.S32.F32 q9,  q9
246        VCVTN.S32.F32 q10, q10
247        VCVTN.S32.F32 q11, q11
248        VCVTN.S32.F32 q12, q12
249        VCVTN.S32.F32 q13, q13
250        VCVTN.S32.F32 q14, q14
251        VCVTN.S32.F32 q15, q15
252
253        VDUP.16 q0, d13[2]              // output_zero_point
254
255        VQMOVN.S32 d16, q8
256        VQMOVN.S32 d17, q9
257        VQMOVN.S32 d18, q10
258        VQMOVN.S32 d19, q11
259        VQMOVN.S32 d20, q12
260        VQMOVN.S32 d21, q13
261        VQMOVN.S32 d22, q14
262        VQMOVN.S32 d23, q15
263
264        VQADD.S16 q8,  q8, q0
265        VQADD.S16 q9,  q9, q0
266        VQADD.S16 q10, q10, q0
267        VQADD.S16 q11, q11, q0
268
269        VDUP.8  q12, d13[6]             // output_min
270
271        VQMOVN.S16 d0,  q8
272        VQMOVN.S16 d1,  q9
273        VQMOVN.S16 d2, q10
274        VQMOVN.S16 d3, q11
275
276        VDUP.8  q13, d13[7]             // output_max
277
278        VMAX.S8 q0, q0, q12
279        VMAX.S8 q1, q1, q12
280
281        SUBS    r1, r1, 8
282
283        VMIN.S8 q0, q0, q13
284        VMIN.S8 q1, q1, q13
285
286        # Store full 4 x 8
287        BLO     4f
288        VST1.8  {d0}, [r11], r7
289        SUB     r3, r3, r2
290        VST1.8  {d1}, [r4], r7
291        SUB     r12, r12, r2
292        VST1.8  {d2}, [r8], r7
293        SUB     r10, r10, r2
294        VST1.8  {d3}, [r6], r7
295        SUB     r0, r0, r2
296        BHI     0b
297
298        VPOP    {d10-d13}
299        ADD     sp, sp, 8
300        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
301        BX      lr
302
303        # Remainder- 1 to 7 bytes of A
304        .p2align 3
3053:
306        AND     r5, r5, 7               // kc remainder 1 to 7
307
308        VLD1.8  {d0},  [r3], r5
309        VLD1.8  {d10},  [r9]!
310        VLD1.8  {d2}, [r12], r5
311        VLD1.8  {d4}, [r10], r5
312        VLD1.8  {d6},  [r0], r5
313
314        VMOVL.S8 q0, d0
315        VMOVL.S8 q5, d10
316        VMOVL.S8 q1, d2
317        VMOVL.S8 q2, d4
318        VMOVL.S8 q3, d6
319        VMLAL.S16 q8, d10, d0[0]
320        VMLAL.S16 q9, d11, d0[0]
321        VMLAL.S16 q10, d10, d2[0]
322        VMLAL.S16 q11, d11, d2[0]
323        VMLAL.S16 q12, d10, d4[0]
324        VMLAL.S16 q13, d11, d4[0]
325        VMLAL.S16 q14, d10, d6[0]
326        VMLAL.S16 q15, d11, d6[0]
327        CMP     r5, 2
328        BLO     2b
329
330        VLD1.8  {d10},  [r9]!
331        VMOVL.S8 q5, d10
332        VMLAL.S16 q8, d10, d0[1]
333        VMLAL.S16 q9, d11, d0[1]
334        VMLAL.S16 q10, d10, d2[1]
335        VMLAL.S16 q11, d11, d2[1]
336        VMLAL.S16 q12, d10, d4[1]
337        VMLAL.S16 q13, d11, d4[1]
338        VMLAL.S16 q14, d10, d6[1]
339        VMLAL.S16 q15, d11, d6[1]
340        BEQ     2b
341
342        VLD1.8  {d10},  [r9]!
343        VMOVL.S8 q5, d10
344        VMLAL.S16 q8, d10, d0[2]
345        VMLAL.S16 q9, d11, d0[2]
346        VMLAL.S16 q10, d10, d2[2]
347        VMLAL.S16 q11, d11, d2[2]
348        VMLAL.S16 q12, d10, d4[2]
349        VMLAL.S16 q13, d11, d4[2]
350        VMLAL.S16 q14, d10, d6[2]
351        VMLAL.S16 q15, d11, d6[2]
352        CMP     r5, 4
353        BLO     2b
354
355        VLD1.8  {d10},  [r9]!
356        VMOVL.S8 q5, d10
357        VMLAL.S16 q8, d10, d0[3]
358        VMLAL.S16 q9, d11, d0[3]
359        VMLAL.S16 q10, d10, d2[3]
360        VMLAL.S16 q11, d11, d2[3]
361        VMLAL.S16 q12, d10, d4[3]
362        VMLAL.S16 q13, d11, d4[3]
363        VMLAL.S16 q14, d10, d6[3]
364        VMLAL.S16 q15, d11, d6[3]
365        BEQ     2b
366
367        VLD1.8  {d10},  [r9]!
368        VMOVL.S8 q5, d10
369        VMLAL.S16 q8, d10, d1[0]
370        VMLAL.S16 q9, d11, d1[0]
371        VMLAL.S16 q10, d10, d3[0]
372        VMLAL.S16 q11, d11, d3[0]
373        VMLAL.S16 q12, d10, d5[0]
374        VMLAL.S16 q13, d11, d5[0]
375        VMLAL.S16 q14, d10, d7[0]
376        VMLAL.S16 q15, d11, d7[0]
377        CMP     r5, 6
378        BLO     2b
379
380        VLD1.8  {d10},  [r9]!
381        VMOVL.S8 q5, d10
382        VMLAL.S16 q8, d10, d1[1]
383        VMLAL.S16 q9, d11, d1[1]
384        VMLAL.S16 q10, d10, d3[1]
385        VMLAL.S16 q11, d11, d3[1]
386        VMLAL.S16 q12, d10, d5[1]
387        VMLAL.S16 q13, d11, d5[1]
388        VMLAL.S16 q14, d10, d7[1]
389        VMLAL.S16 q15, d11, d7[1]
390        BEQ     2b
391
392        VLD1.8  {d10},  [r9]!
393        VMOVL.S8 q5, d10
394        VMLAL.S16 q8, d10, d1[2]
395        VMLAL.S16 q9, d11, d1[2]
396        VMLAL.S16 q10, d10, d3[2]
397        VMLAL.S16 q11, d11, d3[2]
398        VMLAL.S16 q12, d10, d5[2]
399        VMLAL.S16 q13, d11, d5[2]
400        VMLAL.S16 q14, d10, d7[2]
401        VMLAL.S16 q15, d11, d7[2]
402        B       2b
403
404        # Store odd width
405        .p2align 3
4064:
407        TST     r1, 4
408        BEQ     5f
409        VST1.32 {d0[0]}, [r11]!
410        VST1.32 {d1[0]}, [r4]!
411        VST1.32 {d2[0]}, [r8]!
412        VST1.32 {d3[0]}, [r6]!
413        VEXT.8  q0, q0, q0, 4
414        VEXT.8  q1, q1, q1, 4
4155:
416        TST     r1, 2
417        BEQ     6f
418        VST1.16 {d0[0]}, [r11]!
419        VST1.16 {d1[0]}, [r4]!
420        VST1.16 {d2[0]}, [r8]!
421        VST1.16 {d3[0]}, [r6]!
422        VEXT.8  q0, q0, q0, 2
423        VEXT.8  q1, q1, q1, 2
424
4256:
426        TST     r1, 1
427        BEQ     7f
428        VST1.8  {d0[0]}, [r11]
429        VST1.8  {d1[0]}, [r4]
430        VST1.8  {d2[0]}, [r8]
431        VST1.8  {d3[0]}, [r6]
432
4337:
434        VPOP    {d10-d13}
435        ADD     sp, sp, 8
436        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
437        BX      lr
438
439END_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neonv8_mlal_lane_prfm_ld64
440
441#ifdef __ELF__
442.section ".note.GNU-stack","",%progbits
443#endif
444
445