xref: /aosp_15_r20/external/XNNPACK/src/qc8-gemm/gen/4x8c4-minmax-fp32-aarch32-neondot-cortex-a55.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/qs8-gemm/4x8c4-aarch32-neondot-cortex-a55.S.in
3//   Generator: tools/xngen
4//
5// Copyright 2022 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_4x8c4__aarch32_neondot_cortex_a55(
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 + 80 -> (r7)
21//     const void*restrict w,     sp + 84 -> r9
22//     uint8_t*restrict c,        sp + 88 -> r11
23//     size_t cm_stride,          sp + 92 -> (r6)
24//     size_t cn_stride,          sp + 96 -> r7
25//     xnn_qs8_minmax_params params)  sp + 100 -> (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
31// A1  r12  d1
32// A2  r10  d2
33// A3   r0  d3
34
35// B    r9  q2 q3 q4 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 q7
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
51// iOS does not support 32 bit ARM with Neon DotProduct.
52#ifndef __APPLE__
53BEGIN_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8c4__aarch32_neondot_cortex_a55
54        # Push 80 bytes
55        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
56        VPUSH   {d8-d13}                            // +48 = 80
57
58        LDR     r7, [sp, 80]            // a_stride
59        ADD     r2, r2, 3               // kc = (kc + 3) & ~3
60        LDR     r11, [sp, 88]           // c
61        LDR     r6, [sp, 92]            // cm_stride
62        LDR     r9, [sp, 84]            // w
63        BIC     r2, r2, 3
64        LDR     r5, [sp, 100]           // 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 {d13[]}, [r5]           // QC8 params
86        LDR     r7, [sp, 96]            // cn_stride
87
88        .p2align 3
890:
90        # Load initial bias from w into accumulators
91        VLDM    r9!, {d16-d19}          // Bias
92        SUBS    r5, r2, 8               // k = kc - 8
93
94        # Prologue + Bias
95        VLD1.8  {d4},  [r9]!            // B0
96        VMOV    q10, q8
97        VLD1.8  {d0},  [r3]!            // A0
98        VMOV    q11, q9
99        VLD1.8  {d5},  [r9]!            // B1
100        VMOV    q12, q8
101        VLD1.8  {d6},  [r9]!            // B2
102        VMOV    q13, q9
103        VLD1.8  {d1}, [r12]!            // A1
104        VMOV    q14, q8
105        VLD1.8  {d7},  [r9]!            // B3
106        VMOV    q15, q9
107        BLO     4f                      // less than 8 channels?
108
109        SUBS    r5, r5, 8               // k = k - 8
110        BLO     12f                     // less than 16 channels - skip mainloop
111
112        # Main loop - 8 bytes of A.
113        # 16 SDOT, 12 LD64
114        .p2align 3
1151:
116        VSDOT.S8 q8, q2, d0[0]
117        VLD1.8  {d2}, [r10]!            // A2
118        VSDOT.S8 q9, q3, d0[0]
119        VLD1.8  {d3},  [r0]!            // A3
120        VSDOT.S8 q10, q2, d1[0]
121        VLD1.8  {d8},  [r9]!            // B4
122        VSDOT.S8 q11, q3, d1[0]
123        VLD1.8  {d9},  [r9]!            // B5
124        VSDOT.S8 q12, q2, d2[0]
125        VLD1.8  {d10},  [r9]!           // B6
126        VSDOT.S8 q13, q3, d2[0]
127        VLD1.8  {d11},  [r9]!           // B7
128        VSDOT.S8 q14, q2, d3[0]
129        VSDOT.S8 q15, q3, d3[0]
130        SUBS    r5, r5, 8
131
132        VSDOT.S8 q8, q4, d0[1]
133        VLD1.8  {d4},  [r9]!            // B0
134        VSDOT.S8 q9, q5, d0[1]
135        VLD1.8  {d5},  [r9]!            // B1
136        VSDOT.S8 q10, q4, d1[1]
137        VLD1.8  {d6},  [r9]!            // B2
138        VSDOT.S8 q11, q5, d1[1]
139        VLD1.8  {d7},  [r9]!            // B3
140        VSDOT.S8 q12, q4, d2[1]
141        VLD1.8  {d0},  [r3]!            // A0
142        VSDOT.S8 q13, q5, d2[1]
143        VLD1.8  {d1}, [r12]!            // A1
144        VSDOT.S8 q14, q4, d3[1]
145        VSDOT.S8 q15, q5, d3[1]
146        BHS     1b
147
148        # Epilogue
149        .p2align 3
15012:
151        VSDOT.S8 q8, q2, d0[0]
152        VLD1.8  {d2}, [r10]!            // A2
153        VSDOT.S8 q9, q3, d0[0]
154        VLD1.8  {d3},  [r0]!            // A3
155        VSDOT.S8 q10, q2, d1[0]
156        VLD1.8  {d8},  [r9]!            // B4
157        VSDOT.S8 q11, q3, d1[0]
158        VLD1.8  {d9},  [r9]!            // B5
159        VSDOT.S8 q12, q2, d2[0]
160        VLD1.8  {d10},  [r9]!           // B6
161        VSDOT.S8 q13, q3, d2[0]
162        VLD1.8  {d11},  [r9]!           // B7
163        VSDOT.S8 q14, q2, d3[0]
164        VSDOT.S8 q15, q3, d3[0]
165        TST     r5, 7
166
167        VSDOT.S8 q8, q4, d0[1]
168        VSDOT.S8 q9, q5, d0[1]
169        VSDOT.S8 q10, q4, d1[1]
170        VSDOT.S8 q11, q5, d1[1]
171        VSDOT.S8 q12, q4, d2[1]
172        VSDOT.S8 q13, q5, d2[1]
173        VSDOT.S8 q14, q4, d3[1]
174        VSDOT.S8 q15, q5, d3[1]
175
176        # Is there a remainder?- 4 bytes of A
177        BNE     3f
178
1792:
180        # QC8 FP32 quantization
181        VLD1.8  {q0-q1},  [r9]!
182
183        VCVT.F32.S32 q8,  q8
184        VCVT.F32.S32 q9,  q9
185        VCVT.F32.S32 q10, q10
186        VCVT.F32.S32 q11, q11
187        VCVT.F32.S32 q12, q12
188        VCVT.F32.S32 q13, q13
189        VCVT.F32.S32 q14, q14
190        VCVT.F32.S32 q15, q15
191
192        VMUL.F32 q8,  q8, q0            // multiplier
193        VMUL.F32 q9,  q9, q1
194        VMUL.F32 q10, q10, q0
195        VMUL.F32 q11, q11, q1
196        VMUL.F32 q12, q12, q0
197        VMUL.F32 q13, q13, q1
198        VMUL.F32 q14, q14, q0
199        VMUL.F32 q15, q15, q1
200
201        VCVTN.S32.F32 q8,  q8
202        VCVTN.S32.F32 q9,  q9
203        VCVTN.S32.F32 q10, q10
204        VCVTN.S32.F32 q11, q11
205        VCVTN.S32.F32 q12, q12
206        VCVTN.S32.F32 q13, q13
207        VCVTN.S32.F32 q14, q14
208        VCVTN.S32.F32 q15, q15
209
210        VDUP.16 q0, d13[2]              // output_zero_point
211
212        VQMOVN.S32 d16, q8
213        VQMOVN.S32 d17, q9
214        VQMOVN.S32 d18, q10
215        VQMOVN.S32 d19, q11
216        VQMOVN.S32 d20, q12
217        VQMOVN.S32 d21, q13
218        VQMOVN.S32 d22, q14
219        VQMOVN.S32 d23, q15
220
221        VQADD.S16 q8,  q8, q0
222        VQADD.S16 q9,  q9, q0
223        VQADD.S16 q10, q10, q0
224        VQADD.S16 q11, q11, q0
225
226        VDUP.8  q12, d13[6]             // output_min
227
228        VQMOVN.S16 d0,  q8
229        VQMOVN.S16 d1,  q9
230        VQMOVN.S16 d2, q10
231        VQMOVN.S16 d3, q11
232
233        VDUP.8  q13, d13[7]             // output_max
234
235        VMAX.S8 q0, q0, q12
236        VMAX.S8 q1, q1, q12
237
238        SUBS    r1, r1, 8
239
240        VMIN.S8 q0, q0, q13
241        VMIN.S8 q1, q1, q13
242
243        # Store full 4 x 8
244        BLO     5f
245        VST1.8  {d0}, [r11], r7
246        SUB     r3, r3, r2
247        VST1.8  {d1}, [r4], r7
248        SUB     r12, r12, r2
249        VST1.8  {d2}, [r8], r7
250        SUB     r10, r10, r2
251        VST1.8  {d3}, [r6], r7
252        SUB     r0, r0, r2
253        BHI     0b
254
255        VPOP    {d8-d13}
256        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
257        BX      lr
258
259        # Remainder prologue
260        .p2align 3
2613:
262        VLD1.8  {d4},  [r9]!            // B0
263        VLD1.8  {d0},  [r3]!            // A0
264        VLD1.8  {d5},  [r9]!            // B1
265        VLD1.8  {d6},  [r9]!            // B2
266        VLD1.8  {d1}, [r12]!            // A1
267        VLD1.8  {d7},  [r9]!            // B3
268
269        # Remainder- 4 bytes of A
2704:
271        VSDOT.S8 q8, q2, d0[0]
272        VLD1.32 {d2[0]}, [r10]!         // A2
273        VSDOT.S8 q9, q3, d0[0]
274        VLD1.32 {d3[0]},  [r0]!         // A3
275        VSDOT.S8 q10, q2, d1[0]
276        SUB     r3, r3, 4               // Rewind A0
277        VSDOT.S8 q11, q3, d1[0]
278        SUB     r12, r12, 4             // Rewind A1
279        VSDOT.S8 q12, q2, d2[0]
280        VSDOT.S8 q13, q3, d2[0]
281        VSDOT.S8 q14, q2, d3[0]
282        VSDOT.S8 q15, q3, d3[0]
283        B       2b
284
285        # Store odd width
286        .p2align 3
2875:
288        TST     r1, 4
289        BEQ     6f
290        VST1.32 {d0[0]}, [r11]!
291        VST1.32 {d1[0]}, [r4]!
292        VST1.32 {d2[0]}, [r8]!
293        VST1.32 {d3[0]}, [r6]!
294        VEXT.8  q0, q0, q0, 4
295        VEXT.8  q1, q1, q1, 4
2966:
297        TST     r1, 2
298        BEQ     7f
299        VST1.16 {d0[0]}, [r11]!
300        VST1.16 {d1[0]}, [r4]!
301        VST1.16 {d2[0]}, [r8]!
302        VST1.16 {d3[0]}, [r6]!
303        VEXT.8  q0, q0, q0, 2
304        VEXT.8  q1, q1, q1, 2
305
3067:
307        TST     r1, 1
308        BEQ     12f
309        VST1.8  {d0[0]}, [r11]
310        VST1.8  {d1[0]}, [r4]
311        VST1.8  {d2[0]}, [r8]
312        VST1.8  {d3[0]}, [r6]
313
31412:
315        VPOP    {d8-d13}
316        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
317        BX      lr
318
319END_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8c4__aarch32_neondot_cortex_a55
320#endif  // __APPLE__
321
322#ifdef __ELF__
323.section ".note.GNU-stack","",%progbits
324#endif
325
326