xref: /aosp_15_r20/external/XNNPACK/src/qc8-gemm/gen/4x8-minmax-fp32-aarch32-neon-mlal-lane-cortex-a7.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/qs8-gemm/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_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_cortex_a7(
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 + 88 -> (r7)
21//     const void*restrict w,     sp + 92 -> r9
22//     int8_t*restrict c,         sp + 96 -> r11
23//     size_t cm_stride,          sp + 100 -> (r6)
24//     size_t cn_stride,          sp + 104 -> r7
25//     xnn_qs8_minmax_params params)  sp + 108 -> (r5)
26
27// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
28
29// Based on cortex_a53 microkernel but with Neon loads
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_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_cortex_a7
55        # Push 88 bytes
56        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
57        SUB     sp, sp, 8                           // +8
58        VPUSH   {d8-d13}                            // +48 = 88
59
60        LDR     r7, [sp, 88]            // a_stride
61        LDR     r11, [sp, 96]           // c
62        LDR     r6, [sp, 100]           // cm_stride
63        LDR     r9, [sp, 92]            // w
64        LDR     r5, [sp, 108]           // 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        VLDM    r5!, {d12}              // QC8 neon params
86        VLD1.16 {d13[]}, [r5]           // output_min/max
87        LDR     r7, [sp, 104]            // 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     4f                      // less than 8 channels?
103
104        // Prologue - load 4A's and B0
105        VLD1.8  {d0},  [r3]!            // A0
106        VLD1.8  {d2}, [r12]!            // A1
107        VLD1.8  {d4}, [r10]!            // A2
108        VLD1.8  {d6},  [r0]!            // A3
109        VLD1.8  {d8},  [r9]!            // B0
110
111        SUBS    r5, r5, 8               // k = k - 8
112        BLO     2f                      // less than 8 channels?
113
114        // Main loop - 8 bytes
115        // 64 bytes for weights.
116        // 5 VMOVL = 4 A and 1 B = 5 cycles
117        // 7 blocks with VLD B, VMOVL, 8 VMLA = 10 cycles
118        // 1 blocks with VLD B, VMLA = 9 cycles
119        // total = 84 cycles
120        .p2align 3
1211:
122        // Extend - 5 cycles
123        VMOVL.S8 q0, d0
124        VMOVL.S8 q4, d8
125        VMOVL.S8 q1, d2
126        VMOVL.S8 q2, d4
127        VMOVL.S8 q3, d6
128
129        // BLOCK 0 - 10 cycles
130        VLD1.8  {d10},  [r9]!           // B1
131        VMLAL.S16 q8, d8, d0[0]
132        VMLAL.S16 q9, d9, d0[0]
133        VMLAL.S16 q10, d8, d2[0]
134        VMLAL.S16 q11, d9, d2[0]
135        VMOVL.S8 q5, d10
136        VMLAL.S16 q12, d8, d4[0]
137        VMLAL.S16 q13, d9, d4[0]
138        VMLAL.S16 q14, d8, d6[0]
139        VMLAL.S16 q15, d9, d6[0]
140
141        // BLOCK 1 - 10 cycles
142        VLD1.8  {d8},  [r9]!            // B2
143        VMLAL.S16 q8, d10, d0[1]
144        VMLAL.S16 q9, d11, d0[1]
145        VMLAL.S16 q10, d10, d2[1]
146        VMLAL.S16 q11, d11, d2[1]
147        VMOVL.S8 q4, d8
148        VMLAL.S16 q12, d10, d4[1]
149        VMLAL.S16 q13, d11, d4[1]
150        VMLAL.S16 q14, d10, d6[1]
151        VMLAL.S16 q15, d11, d6[1]
152
153        // BLOCK 2 - 10 cycles
154        VLD1.8  {d10},  [r9]!           // B3
155        VMLAL.S16 q8, d8, d0[2]
156        VMLAL.S16 q9, d9, d0[2]
157        VMLAL.S16 q10, d8, d2[2]
158        VMLAL.S16 q11, d9, d2[2]
159        VMOVL.S8 q5, d10
160        VMLAL.S16 q12, d8, d4[2]
161        VMLAL.S16 q13, d9, d4[2]
162        VMLAL.S16 q14, d8, d6[2]
163        VMLAL.S16 q15, d9, d6[2]
164
165        // BLOCK 3 - 10 cycles
166        VLD1.8  {d8},  [r9]!            // B4
167        VMLAL.S16 q8, d10, d0[3]
168        VMLAL.S16 q9, d11, d0[3]
169        VMLAL.S16 q10, d10, d2[3]
170        VMLAL.S16 q11, d11, d2[3]
171        VLD1.8  {d0},  [r3]!            // A0
172        VMOVL.S8 q4, d8
173        VMLAL.S16 q12, d10, d4[3]
174        VMLAL.S16 q13, d11, d4[3]
175        VMLAL.S16 q14, d10, d6[3]
176        VMLAL.S16 q15, d11, d6[3]
177
178        // BLOCK 4 - 10 cycles
179        VLD1.8  {d10},  [r9]!           // B5
180        VMLAL.S16 q8, d8, d1[0]
181        VMLAL.S16 q9, d9, d1[0]
182        VMLAL.S16 q10, d8, d3[0]
183        VMLAL.S16 q11, d9, d3[0]
184        VLD1.8  {d2}, [r12]!            // A1
185        VMOVL.S8 q5, d10
186        VMLAL.S16 q12, d8, d5[0]
187        VMLAL.S16 q13, d9, d5[0]
188        VMLAL.S16 q14, d8, d7[0]
189        VMLAL.S16 q15, d9, d7[0]
190
191        // BLOCK 5 - 10 cycles
192        VLD1.8  {d8},  [r9]!            // B6
193        VMLAL.S16 q8, d10, d1[1]
194        VMLAL.S16 q9, d11, d1[1]
195        VMLAL.S16 q10, d10, d3[1]
196        VMLAL.S16 q11, d11, d3[1]
197        VLD1.8  {d4}, [r10]!            // A2
198        VMOVL.S8 q4, d8
199        VMLAL.S16 q12, d10, d5[1]
200        VMLAL.S16 q13, d11, d5[1]
201        VMLAL.S16 q14, d10, d7[1]
202        VMLAL.S16 q15, d11, d7[1]
203
204        // BLOCK 6 - 10 cycles
205        VLD1.8  {d10},  [r9]!           // B7
206        VMLAL.S16 q8, d8, d1[2]
207        VMLAL.S16 q9, d9, d1[2]
208        VMLAL.S16 q10, d8, d3[2]
209        VMLAL.S16 q11, d9, d3[2]
210        VLD1.8  {d6},  [r0]!            // A3
211        VMOVL.S8 q5, d10
212        VMLAL.S16 q12, d8, d5[2]
213        VMLAL.S16 q13, d9, d5[2]
214        VMLAL.S16 q14, d8, d7[2]
215        VMLAL.S16 q15, d9, d7[2]
216
217        // BLOCK 7 - 9 cycles
218        VLD1.8  {d8},  [r9]!            // B0
219        VMLAL.S16 q8, d10, d1[3]
220        VMLAL.S16 q9, d11, d1[3]
221        VMLAL.S16 q10, d10, d3[3]
222        VMLAL.S16 q11, d11, d3[3]
223        VMLAL.S16 q12, d10, d5[3]
224        VMLAL.S16 q13, d11, d5[3]
225        SUBS    r5, r5, 8
226        VMLAL.S16 q14, d10, d7[3]
227        VMLAL.S16 q15, d11, d7[3]
228        BHS     1b
229
230        // Epilogue
231
232        .p2align 3
2332:
234        VMOVL.S8 q0, d0
235        VMOVL.S8 q4, d8
236        VMOVL.S8 q1, d2
237        VMOVL.S8 q2, d4
238        VMOVL.S8 q3, d6
239
240        VLD1.8  {d10},  [r9]!           // B1
241        VMLAL.S16 q8, d8, d0[0]
242        VMLAL.S16 q9, d9, d0[0]
243        VMLAL.S16 q10, d8, d2[0]
244        VMLAL.S16 q11, d9, d2[0]
245        VMOVL.S8 q5, d10
246        VMLAL.S16 q12, d8, d4[0]
247        VMLAL.S16 q13, d9, d4[0]
248        VMLAL.S16 q14, d8, d6[0]
249        VMLAL.S16 q15, d9, d6[0]
250
251        VLD1.8  {d8},  [r9]!            // B2
252        VMLAL.S16 q8, d10, d0[1]
253        VMLAL.S16 q9, d11, d0[1]
254        VMLAL.S16 q10, d10, d2[1]
255        VMLAL.S16 q11, d11, d2[1]
256        VMOVL.S8 q4, d8
257        VMLAL.S16 q12, d10, d4[1]
258        VMLAL.S16 q13, d11, d4[1]
259        VMLAL.S16 q14, d10, d6[1]
260        VMLAL.S16 q15, d11, d6[1]
261
262        VLD1.8  {d10},  [r9]!           // B3
263        VMLAL.S16 q8, d8, d0[2]
264        VMLAL.S16 q9, d9, d0[2]
265        VMLAL.S16 q10, d8, d2[2]
266        VMLAL.S16 q11, d9, d2[2]
267        VMOVL.S8 q5, d10
268        VMLAL.S16 q12, d8, d4[2]
269        VMLAL.S16 q13, d9, d4[2]
270        VMLAL.S16 q14, d8, d6[2]
271        VMLAL.S16 q15, d9, d6[2]
272
273        VLD1.8  {d8},  [r9]!            // B4
274        VMLAL.S16 q8, d10, d0[3]
275        VMLAL.S16 q9, d11, d0[3]
276        VMLAL.S16 q10, d10, d2[3]
277        VMLAL.S16 q11, d11, d2[3]
278        VMOVL.S8 q4, d8
279        VMLAL.S16 q12, d10, d4[3]
280        VMLAL.S16 q13, d11, d4[3]
281        VMLAL.S16 q14, d10, d6[3]
282        VMLAL.S16 q15, d11, d6[3]
283
284        VLD1.8  {d10},  [r9]!           // B5
285        VMLAL.S16 q8, d8, d1[0]
286        VMLAL.S16 q9, d9, d1[0]
287        VMLAL.S16 q10, d8, d3[0]
288        VMLAL.S16 q11, d9, d3[0]
289        VMOVL.S8 q5, d10
290        VMLAL.S16 q12, d8, d5[0]
291        VMLAL.S16 q13, d9, d5[0]
292        VMLAL.S16 q14, d8, d7[0]
293        VMLAL.S16 q15, d9, d7[0]
294
295        VLD1.8  {d8},  [r9]!            // B6
296        VMLAL.S16 q8, d10, d1[1]
297        VMLAL.S16 q9, d11, d1[1]
298        VMLAL.S16 q10, d10, d3[1]
299        VMLAL.S16 q11, d11, d3[1]
300        VMOVL.S8 q4, d8
301        VMLAL.S16 q12, d10, d5[1]
302        VMLAL.S16 q13, d11, d5[1]
303        VMLAL.S16 q14, d10, d7[1]
304        VMLAL.S16 q15, d11, d7[1]
305
306        VLD1.8  {d10},  [r9]!           // B7
307        VMLAL.S16 q8, d8, d1[2]
308        VMLAL.S16 q9, d9, d1[2]
309        VMLAL.S16 q10, d8, d3[2]
310        VMLAL.S16 q11, d9, d3[2]
311        VMOVL.S8 q5, d10
312        VMLAL.S16 q12, d8, d5[2]
313        VMLAL.S16 q13, d9, d5[2]
314        VMLAL.S16 q14, d8, d7[2]
315        VMLAL.S16 q15, d9, d7[2]
316
317        VMLAL.S16 q8, d10, d1[3]
318        VMLAL.S16 q9, d11, d1[3]
319        VMLAL.S16 q10, d10, d3[3]
320        VMLAL.S16 q11, d11, d3[3]
321        VMLAL.S16 q12, d10, d5[3]
322        VMLAL.S16 q13, d11, d5[3]
323        ADDS    r5, r5, 8
324        VMLAL.S16 q14, d10, d7[3]
325        VMLAL.S16 q15, d11, d7[3]
326
327        # Is there a remainder?- 1-7 bytes of A
328        BNE     4f
329
3303:
331        # QC8 FP32 quantization
332        VLD1.8  {q0-q1},  [r9]!
333
334        VDUP.32 q2, d12[0]              // magic_bias
335        VDUP.32 q3, d12[1]              // magic_bias_less_output_zero_point
336
337        VCVT.F32.S32 q8,  q8
338        VCVT.F32.S32 q9,  q9
339        VCVT.F32.S32 q10, q10
340        VCVT.F32.S32 q11, q11
341        VCVT.F32.S32 q12, q12
342        VCVT.F32.S32 q13, q13
343        VCVT.F32.S32 q14, q14
344        VCVT.F32.S32 q15, q15
345
346        VMUL.F32 q8,  q8, q0            // multiplier
347        VMUL.F32 q9,  q9, q1
348        VMUL.F32 q10, q10, q0
349        VMUL.F32 q11, q11, q1
350        VMUL.F32 q12, q12, q0
351        VMUL.F32 q13, q13, q1
352        VMUL.F32 q14, q14, q0
353        VMUL.F32 q15, q15, q1
354
355        VADD.F32 q8,  q8, q2            // magic_bias
356        VADD.F32 q9,  q9, q2
357        VADD.F32 q10, q10, q2
358        VADD.F32 q11, q11, q2
359        VADD.F32 q12, q12, q2
360        VADD.F32 q13, q13, q2
361        VADD.F32 q14, q14, q2
362        VADD.F32 q15, q15, q2
363
364        VQSUB.S32 q8,  q8, q3           // magic_bias_less_output_zero_point
365        VQSUB.S32 q9,  q9, q3
366        VQSUB.S32 q10, q10, q3
367        VQSUB.S32 q11, q11, q3
368        VQSUB.S32 q12, q12, q3
369        VQSUB.S32 q13, q13, q3
370        VQSUB.S32 q14, q14, q3
371        VQSUB.S32 q15, q15, q3
372
373
374        VQMOVN.S32 d16, q8
375        VQMOVN.S32 d17, q9
376        VQMOVN.S32 d18, q10
377        VQMOVN.S32 d19, q11
378        VQMOVN.S32 d20, q12
379        VQMOVN.S32 d21, q13
380        VQMOVN.S32 d22, q14
381        VQMOVN.S32 d23, q15
382
383
384        VDUP.8  q12, d13[6]             // output_min
385
386        VQMOVN.S16 d0,  q8
387        VQMOVN.S16 d1,  q9
388        VQMOVN.S16 d2, q10
389        VQMOVN.S16 d3, q11
390
391        VDUP.8  q13, d13[7]             // output_max
392
393        VMAX.S8 q0, q0, q12
394        VMAX.S8 q1, q1, q12
395
396        SUBS    r1, r1, 8
397
398        VMIN.S8 q0, q0, q13
399        VMIN.S8 q1, q1, q13
400
401        # Store full 4 x 8
402        BLO     5f
403        VST1.8  {d0}, [r11], r7
404        SUB     r3, r3, r2
405        VST1.8  {d1}, [r4], r7
406        SUB     r12, r12, r2
407        VST1.8  {d2}, [r8], r7
408        SUB     r10, r10, r2
409        VST1.8  {d3}, [r6], r7
410        SUB     r0, r0, r2
411        BHI     0b
412
413        VPOP    {d8-d13}
414        ADD     sp, sp, 8               // skip d14
415        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
416        BX      lr
417
418        # Remainder- 1 to 7 bytes of A
419        .p2align 3
4204:
421        AND     r5, r5, 7               // kc remainder 1 to 7
422
423        VLD1.8  {d0},  [r3], r5
424        VLD1.8  {d8},  [r9]!
425        VLD1.8  {d2}, [r12], r5
426        VLD1.8  {d4}, [r10], r5
427        VLD1.8  {d6},  [r0], r5
428
429        VMOVL.S8 q0, d0
430        VMOVL.S8 q4, d8
431        VMOVL.S8 q1, d2
432        VMOVL.S8 q2, d4
433        VMOVL.S8 q3, d6
434        VMLAL.S16 q8, d8, d0[0]
435        VMLAL.S16 q9, d9, d0[0]
436        VMLAL.S16 q10, d8, d2[0]
437        VMLAL.S16 q11, d9, d2[0]
438        VMLAL.S16 q12, d8, d4[0]
439        VMLAL.S16 q13, d9, d4[0]
440        VMLAL.S16 q14, d8, d6[0]
441        VMLAL.S16 q15, d9, d6[0]
442        CMP     r5, 2
443        BLO     3b
444
445        VLD1.8  {d8},  [r9]!
446        VMOVL.S8 q4, d8
447        VMLAL.S16 q8, d8, d0[1]
448        VMLAL.S16 q9, d9, d0[1]
449        VMLAL.S16 q10, d8, d2[1]
450        VMLAL.S16 q11, d9, d2[1]
451        VMLAL.S16 q12, d8, d4[1]
452        VMLAL.S16 q13, d9, d4[1]
453        VMLAL.S16 q14, d8, d6[1]
454        VMLAL.S16 q15, d9, d6[1]
455        BEQ     3b
456
457        VLD1.8  {d8},  [r9]!
458        VMOVL.S8 q4, d8
459        VMLAL.S16 q8, d8, d0[2]
460        VMLAL.S16 q9, d9, d0[2]
461        VMLAL.S16 q10, d8, d2[2]
462        VMLAL.S16 q11, d9, d2[2]
463        VMLAL.S16 q12, d8, d4[2]
464        VMLAL.S16 q13, d9, d4[2]
465        VMLAL.S16 q14, d8, d6[2]
466        VMLAL.S16 q15, d9, d6[2]
467        CMP     r5, 4
468        BLO     3b
469
470        VLD1.8  {d8},  [r9]!
471        VMOVL.S8 q4, d8
472        VMLAL.S16 q8, d8, d0[3]
473        VMLAL.S16 q9, d9, d0[3]
474        VMLAL.S16 q10, d8, d2[3]
475        VMLAL.S16 q11, d9, d2[3]
476        VMLAL.S16 q12, d8, d4[3]
477        VMLAL.S16 q13, d9, d4[3]
478        VMLAL.S16 q14, d8, d6[3]
479        VMLAL.S16 q15, d9, d6[3]
480        BEQ     3b
481
482        VLD1.8  {d8},  [r9]!
483        VMOVL.S8 q4, d8
484        VMLAL.S16 q8, d8, d1[0]
485        VMLAL.S16 q9, d9, d1[0]
486        VMLAL.S16 q10, d8, d3[0]
487        VMLAL.S16 q11, d9, d3[0]
488        VMLAL.S16 q12, d8, d5[0]
489        VMLAL.S16 q13, d9, d5[0]
490        VMLAL.S16 q14, d8, d7[0]
491        VMLAL.S16 q15, d9, d7[0]
492        CMP     r5, 6
493        BLO     3b
494
495        VLD1.8  {d8},  [r9]!
496        VMOVL.S8 q4, d8
497        VMLAL.S16 q8, d8, d1[1]
498        VMLAL.S16 q9, d9, d1[1]
499        VMLAL.S16 q10, d8, d3[1]
500        VMLAL.S16 q11, d9, d3[1]
501        VMLAL.S16 q12, d8, d5[1]
502        VMLAL.S16 q13, d9, d5[1]
503        VMLAL.S16 q14, d8, d7[1]
504        VMLAL.S16 q15, d9, d7[1]
505        BEQ     3b
506
507        VLD1.8  {d8},  [r9]!
508        VMOVL.S8 q4, d8
509        VMLAL.S16 q8, d8, d1[2]
510        VMLAL.S16 q9, d9, d1[2]
511        VMLAL.S16 q10, d8, d3[2]
512        VMLAL.S16 q11, d9, d3[2]
513        VMLAL.S16 q12, d8, d5[2]
514        VMLAL.S16 q13, d9, d5[2]
515        VMLAL.S16 q14, d8, d7[2]
516        VMLAL.S16 q15, d9, d7[2]
517        B       3b
518
519        # Store odd width
520        .p2align 3
5215:
522        TST     r1, 4
523        BEQ     6f
524        VST1.32 {d0[0]}, [r11]!
525        VST1.32 {d1[0]}, [r4]!
526        VST1.32 {d2[0]}, [r8]!
527        VST1.32 {d3[0]}, [r6]!
528        VEXT.8  q0, q0, q0, 4
529        VEXT.8  q1, q1, q1, 4
5306:
531        TST     r1, 2
532        BEQ     7f
533        VST1.16 {d0[0]}, [r11]!
534        VST1.16 {d1[0]}, [r4]!
535        VST1.16 {d2[0]}, [r8]!
536        VST1.16 {d3[0]}, [r6]!
537        VEXT.8  q0, q0, q0, 2
538        VEXT.8  q1, q1, q1, 2
539
5407:
541        TST     r1, 1
542        BEQ     8f
543        VST1.8  {d0[0]}, [r11]
544        VST1.8  {d1[0]}, [r4]
545        VST1.8  {d2[0]}, [r8]
546        VST1.8  {d3[0]}, [r6]
547
5488:
549        VPOP    {d8-d13}
550        ADD     sp, sp, 8               // skip d14
551        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
552        BX      lr
553
554END_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_cortex_a7
555
556#ifdef __ELF__
557.section ".note.GNU-stack","",%progbits
558#endif
559
560