xref: /aosp_15_r20/external/XNNPACK/src/qc8-gemm/gen/4x8c4-minmax-fp32-aarch32-neondot-ld64.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/qs8-gemm/4x8c4-aarch32-neondot-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_4x8c4__aarch32_neondot_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 + 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_ld64
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        VMOV    q10, q8
94        VMOV    q11, q9
95        VMOV    q12, q8
96        VMOV    q13, q9
97        VMOV    q14, q8
98        VMOV    q15, q9
99        BLO     3f                      // less than 8 channels?
100
101        # Main loop - 8 bytes of A.
102        # 16 SDOT, 4 LD64 A, 4 LD128 B
103        .p2align 3
1041:
105        VLD1.8  {d0},  [r3]!            // A0
106        VLD1.8  {q2},  [r9]!            // B0
107        VLD1.8  {d1}, [r12]!            // A1
108        VLD1.8  {q3},  [r9]!            // B1
109        VLD1.8  {d2}, [r10]!            // A2
110        VLD1.8  {q4},  [r9]!            // B2
111        VLD1.8  {d3},  [r0]!            // A3
112        VLD1.8  {q5},  [r9]!            // B3
113        SUBS    r5, r5, 8
114
115        VSDOT.S8 q8, q2, d0[0]
116        VSDOT.S8 q9, q3, d0[0]
117        VSDOT.S8 q10, q2, d1[0]
118        VSDOT.S8 q11, q3, d1[0]
119        VSDOT.S8 q12, q2, d2[0]
120        VSDOT.S8 q13, q3, d2[0]
121        VSDOT.S8 q14, q2, d3[0]
122        VSDOT.S8 q15, q3, d3[0]
123
124        VSDOT.S8 q8, q4, d0[1]
125        VSDOT.S8 q9, q5, d0[1]
126        VSDOT.S8 q10, q4, d1[1]
127        VSDOT.S8 q11, q5, d1[1]
128        VSDOT.S8 q12, q4, d2[1]
129        VSDOT.S8 q13, q5, d2[1]
130        VSDOT.S8 q14, q4, d3[1]
131        VSDOT.S8 q15, q5, d3[1]
132        BHS     1b
133
134        # Is there a remainder?- 4 bytes of A
135        ADDS    r5, r5, 8
136        BNE     3f
137
1382:
139        # QC8 FP32 quantization
140        VLD1.8  {q0-q1},  [r9]!
141
142        VCVT.F32.S32 q8,  q8
143        VCVT.F32.S32 q9,  q9
144        VCVT.F32.S32 q10, q10
145        VCVT.F32.S32 q11, q11
146        VCVT.F32.S32 q12, q12
147        VCVT.F32.S32 q13, q13
148        VCVT.F32.S32 q14, q14
149        VCVT.F32.S32 q15, q15
150
151        VMUL.F32 q8,  q8, q0            // multiplier
152        VMUL.F32 q9,  q9, q1
153        VMUL.F32 q10, q10, q0
154        VMUL.F32 q11, q11, q1
155        VMUL.F32 q12, q12, q0
156        VMUL.F32 q13, q13, q1
157        VMUL.F32 q14, q14, q0
158        VMUL.F32 q15, q15, q1
159
160        VCVTN.S32.F32 q8,  q8
161        VCVTN.S32.F32 q9,  q9
162        VCVTN.S32.F32 q10, q10
163        VCVTN.S32.F32 q11, q11
164        VCVTN.S32.F32 q12, q12
165        VCVTN.S32.F32 q13, q13
166        VCVTN.S32.F32 q14, q14
167        VCVTN.S32.F32 q15, q15
168
169        VDUP.16 q0, d13[2]              // output_zero_point
170
171        VQMOVN.S32 d16, q8
172        VQMOVN.S32 d17, q9
173        VQMOVN.S32 d18, q10
174        VQMOVN.S32 d19, q11
175        VQMOVN.S32 d20, q12
176        VQMOVN.S32 d21, q13
177        VQMOVN.S32 d22, q14
178        VQMOVN.S32 d23, q15
179
180        VQADD.S16 q8,  q8, q0
181        VQADD.S16 q9,  q9, q0
182        VQADD.S16 q10, q10, q0
183        VQADD.S16 q11, q11, q0
184
185        VDUP.8  q12, d13[6]             // output_min
186
187        VQMOVN.S16 d0,  q8
188        VQMOVN.S16 d1,  q9
189        VQMOVN.S16 d2, q10
190        VQMOVN.S16 d3, q11
191
192        VDUP.8  q13, d13[7]             // output_max
193
194        VMAX.S8 q0, q0, q12
195        VMAX.S8 q1, q1, q12
196
197        SUBS    r1, r1, 8
198
199        VMIN.S8 q0, q0, q13
200        VMIN.S8 q1, q1, q13
201
202        # Store full 4 x 8
203        BLO     4f
204        VST1.8  {d0}, [r11], r7
205        SUB     r3, r3, r2
206        VST1.8  {d1}, [r4], r7
207        SUB     r12, r12, r2
208        VST1.8  {d2}, [r8], r7
209        SUB     r10, r10, r2
210        VST1.8  {d3}, [r6], r7
211        SUB     r0, r0, r2
212        BHI     0b
213
214        VPOP    {d8-d13}
215        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
216        BX      lr
217
218        # Remainder- 4 bytes of A
219        .p2align 3
2203:
221        VLD1.32 {d0[0]},  [r3]!         // A0
222        VLD1.32 {q2},  [r9]!            // B0
223        VLD1.32 {d1[0]}, [r12]!         // A1
224        VLD1.32 {q3},  [r9]!            // B1
225        VLD1.32 {d2[0]}, [r10]!         // A2
226        VLD1.32 {d3[0]},  [r0]!         // A3
227
228        VSDOT.S8 q8, q2, d0[0]
229        VSDOT.S8 q9, q3, d0[0]
230        VSDOT.S8 q10, q2, d1[0]
231        VSDOT.S8 q11, q3, d1[0]
232        VSDOT.S8 q12, q2, d2[0]
233        VSDOT.S8 q13, q3, d2[0]
234        VSDOT.S8 q14, q2, d3[0]
235        VSDOT.S8 q15, q3, d3[0]
236        B       2b
237
238        # Store odd width
239        .p2align 3
2404:
241        TST     r1, 4
242        BEQ     5f
243        VST1.32 {d0[0]}, [r11]!
244        VST1.32 {d1[0]}, [r4]!
245        VST1.32 {d2[0]}, [r8]!
246        VST1.32 {d3[0]}, [r6]!
247        VEXT.8  q0, q0, q0, 4
248        VEXT.8  q1, q1, q1, 4
2495:
250        TST     r1, 2
251        BEQ     6f
252        VST1.16 {d0[0]}, [r11]!
253        VST1.16 {d1[0]}, [r4]!
254        VST1.16 {d2[0]}, [r8]!
255        VST1.16 {d3[0]}, [r6]!
256        VEXT.8  q0, q0, q0, 2
257        VEXT.8  q1, q1, q1, 2
258
2596:
260        TST     r1, 1
261        BEQ     7f
262        VST1.8  {d0[0]}, [r11]
263        VST1.8  {d1[0]}, [r4]
264        VST1.8  {d2[0]}, [r8]
265        VST1.8  {d3[0]}, [r6]
266
2677:
268        VPOP    {d8-d13}
269        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
270        BX      lr
271
272END_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8c4__aarch32_neondot_ld64
273#endif  // __APPLE__
274
275#ifdef __ELF__
276.section ".note.GNU-stack","",%progbits
277#endif
278
279