xref: /aosp_15_r20/external/XNNPACK/src/qs8-igemm/gen/4x8c4-minmax-rndnu-aarch32-neondot-ld64.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/qs8-igemm/4x8c4-aarch32-neondot-ld64.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_qs8_igemm_minmax_rndnu_ukernel_4x8c4__aarch32_neondot_ld64(
16//     size_t mr,                                      r0
17//     size_t nc,                                      r1
18//     size_t kc,                                      r2 -> r5 -> sp + 52
19//     size_t ks,                                      r3 -> sp + 56 -> r14
20//     const int8_t**restrict a,           sp + 96  -> r2
21//     const void*restrict w,              sp + 100 -> r9
22//     int8_t*restrict c,                  sp + 104 -> r11
23//     size_t cm_stride,                   sp + 108 -> (r6)
24//     size_t cn_stride,                   sp + 112 -> (r7)
25//     size_t a_offset,                    sp + 116 -> (r5)
26//     const int8_t* zero,                 sp + 120 -> (r7)
27//     xnn_qs8_conv_minmax_params*params); sp + 124 -> (r5)
28
29// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
30
31// Register usage
32// A0   r3  d0
33// A1  r12  d1
34// A2  r10  d2
35// A3   r0  d3
36
37// B    r9  q2 q3 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 q7
45
46// params structure is 16 bytes
47//  struct {
48//    int32_t right_pre_shift;    d12[0]
49//    int32_t multiplier;         d12[1]
50//    int32_t right_post_shift;   d13[0]
51//    int16_t output_zero_point;  d13[2]
52//    int8_t output_min;          d13[6]
53//    int8_t output_max;          d13[7]
54//  } rndnu_neon;
55
56// iOS does not support 32 bit ARM with Neon DotProduct.
57#ifndef __APPLE__
58BEGIN_FUNCTION xnn_qs8_igemm_minmax_rndnu_ukernel_4x8c4__aarch32_neondot_ld64
59        ADD     r2, r2, 3               // kc = (kc + 3) & ~3
60        BIC     r2, r2, 3
61        # Push 96 bytes
62        # r2 will be reloaded in outer loop.  r3 is ks
63        PUSH    {r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}   // +44
64        SUB     sp, sp, 4                                        // 4
65        VPUSH   {d8-d13}                                         // +48 = 96
66
67        LDR     r11, [sp, 104]          // c
68        LDR     r6, [sp, 108]           // cm_stride
69        LDR     r2, [sp, 96]            // a
70        LDR     r9, [sp, 100]           // w
71        LDR     r5, [sp, 124]           // params
72        MOV     r14, r3                 // p = ks
73
74        # Clamp C pointers
75        CMP     r0, 2                   // if mr >= 2
76        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
77        MOVLO   r4, r11                 // c1
78                                        // if mr > 2
79        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
80        MOVLS   r8, r4                  // c2
81        CMP     r0, 4                   // if mr >=4
82        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
83        MOVLO   r6, r8                  // c3
84
85        # Load params values
86        VLDM    r5, {d12-d13}           // RNDNU params
87
880:
89        # Load initial bias from w into accumulators
90        VLDM    r9!, {d16-d19}          // Bias
91        VMOV    q10, q8
92        VMOV    q11, q9
93        LDR     r7, [sp, 120]           // zero
94        VMOV    q12, q8
95        VMOV    q13, q9
96        VMOV    q14, q8
97        VMOV    q15, q9
98
991:
100        # Load next 4 A pointers
101        LDR     r3, [r2,  0]
102        LDR     r12, [r2,  4]
103        LDR     r10, [r2,  8]
104        LDR     r0, [r2, 12]
105        ADD     r2, r2, 16
106
107        # Add a_offset
108        LDR     r5, [sp, 116]           // a_offset
109        CMP     r3,  r7                 // if a0 == zero
110        ADD     r3,  r3, r5             // a0 += a_offset
111        MOVEQ   r3,  r7                 //   a0 = zero, else += a0 + a_offset
112        CMP     r12,  r7                // if a1 == zero
113        ADD     r12, r12, r5            // a1 += a_offset
114        MOVEQ   r12,  r7                //   a1 = zero, else += a1 + a_offset
115        CMP     r10,  r7                // if a2 == zero
116        ADD     r10, r10, r5            // a2 += a_offset
117        MOVEQ   r10,  r7                //   a2 = zero, else += a2 + a_offset
118        CMP     r0,  r7                 // if a3 == zero
119        ADD     r0,  r0, r5             // a3 += a_offset
120        LDR     r5, [sp, 52]            // kc
121        MOVEQ   r0,  r7                 //   a3 = zero, else += a3 + a_offset
122
123        SUBS    r5, r5, 8               // kc - 8
124        BLO     4f                      // less than 8 channels?
125
126        # Main loop - 8 bytes of A.
127        # 16 SDOT, 4 LD64 A, 4 LD128 B
128        .p2align 3
1292:
130        VLD1.8  {d0},  [r3]!            // A0
131        VLD1.8  {q2},  [r9]!            // B0
132        VLD1.8  {d1}, [r12]!            // A1
133        VLD1.8  {q3},  [r9]!            // B1
134        VLD1.8  {d2}, [r10]!            // A2
135        VLD1.8  {q4},  [r9]!            // B2
136        VLD1.8  {d3},  [r0]!            // A3
137        VLD1.8  {q5},  [r9]!            // B3
138        SUBS    r5, r5, 8
139
140        VSDOT.S8 q8, q2, d0[0]
141        VSDOT.S8 q9, q3, d0[0]
142        VSDOT.S8 q10, q2, d1[0]
143        VSDOT.S8 q11, q3, d1[0]
144        VSDOT.S8 q12, q2, d2[0]
145        VSDOT.S8 q13, q3, d2[0]
146        VSDOT.S8 q14, q2, d3[0]
147        VSDOT.S8 q15, q3, d3[0]
148
149        VSDOT.S8 q8, q4, d0[1]
150        VSDOT.S8 q9, q5, d0[1]
151        VSDOT.S8 q10, q4, d1[1]
152        VSDOT.S8 q11, q5, d1[1]
153        VSDOT.S8 q12, q4, d2[1]
154        VSDOT.S8 q13, q5, d2[1]
155        VSDOT.S8 q14, q4, d3[1]
156        VSDOT.S8 q15, q5, d3[1]
157        BHS     2b
158
159        # Is there a remainder?- 4 bytes of A
160        TST     r5, 4
161        BNE     4f
162
1633:
164        # ks loop
165        SUBS    r14, r14, 16            // ks -= MR * sizeof(void*)
166        BHI     1b
167
168        LDR     r7, [sp, 112]           // cn_stride
169        LDR     r14, [sp, 56]           // p = ks
170
171        # RNDNU quantization
172        VDUP.32 q0, d12[0]              // right_pre_shift
173
174        VQSHL.S32 q8,  q8, q0
175        VQSHL.S32 q9,  q9, q0
176        VQSHL.S32 q10, q10, q0
177        VQSHL.S32 q11, q11, q0
178        VQSHL.S32 q12, q12, q0
179        VQSHL.S32 q13, q13, q0
180        VQSHL.S32 q14, q14, q0
181        VQSHL.S32 q15, q15, q0
182
183        VDUP.32 q2, d13[0]              // right_post_shift
184
185        VQDMULH.S32 q8,  q8, d12[1]     // multiplier
186        VQDMULH.S32 q9,  q9, d12[1]
187        VQDMULH.S32 q10, q10, d12[1]
188        VQDMULH.S32 q11, q11, d12[1]
189        VQDMULH.S32 q12, q12, d12[1]
190        VQDMULH.S32 q13, q13, d12[1]
191        VQDMULH.S32 q14, q14, d12[1]
192        VQDMULH.S32 q15, q15, d12[1]
193
194        VRSHL.S32 q8,  q8, q2
195        VRSHL.S32 q9,  q9, q2
196        VRSHL.S32 q10, q10, q2
197        VRSHL.S32 q11, q11, q2
198        VRSHL.S32 q12, q12, q2
199        VRSHL.S32 q13, q13, q2
200        VRSHL.S32 q14, q14, q2
201        VRSHL.S32 q15, q15, q2
202        VDUP.16 q0, d13[2]              // output_zero_point
203
204        VQMOVN.S32 d16, q8
205        VQMOVN.S32 d17, q9
206        VQMOVN.S32 d18, q10
207        VQMOVN.S32 d19, q11
208        VQMOVN.S32 d20, q12
209        VQMOVN.S32 d21, q13
210        VQMOVN.S32 d22, q14
211        VQMOVN.S32 d23, q15
212
213        VQADD.S16 q8,  q8, q0
214        VQADD.S16 q9,  q9, q0
215        VQADD.S16 q10, q10, q0
216        VQADD.S16 q11, q11, q0
217
218        VDUP.8  q12, d13[6]             // output_min
219
220        VQMOVN.S16 d0,  q8
221        VQMOVN.S16 d1,  q9
222        VQMOVN.S16 d2, q10
223        VQMOVN.S16 d3, q11
224
225        VDUP.8  q13, d13[7]             // output_max
226
227        VMAX.S8 q0, q0, q12
228        VMAX.S8 q1, q1, q12
229
230        SUBS    r1, r1, 8               // nc -= 8
231
232        VMIN.S8 q0, q0, q13
233        VMIN.S8 q1, q1, q13
234
235        # Store full 4 x 8
236        BLO     5f
237        VST1.8  {d3}, [r6], r7
238        VST1.8  {d2}, [r8], r7
239        VST1.8  {d1}, [r4], r7
240        VST1.8  {d0}, [r11], r7
241        SUB     r2, r2, r14             // a -= ks
242        BHI     0b
243
244        VPOP    {d8-d13}
245        ADD     sp, sp, 12              // skip pad, r2, r3
246        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
247
2484:
249        # Remainder- 4 bytes of A
250        VLD1.32 {d0[0]},  [r3]!         // A0
251        VLD1.32 {q2},  [r9]!            // B0
252        VLD1.32 {d1[0]}, [r12]!         // A1
253        VLD1.32 {q3},  [r9]!            // B1
254        VLD1.32 {d2[0]}, [r10]!         // A2
255        VLD1.32 {d3[0]},  [r0]!         // A3
256
257        VSDOT.S8 q8, q2, d0[0]
258        VSDOT.S8 q9, q3, d0[0]
259        VSDOT.S8 q10, q2, d1[0]
260        VSDOT.S8 q11, q3, d1[0]
261        VSDOT.S8 q12, q2, d2[0]
262        VSDOT.S8 q13, q3, d2[0]
263        VSDOT.S8 q14, q2, d3[0]
264        VSDOT.S8 q15, q3, d3[0]
265        B       3b
266
267        # Store odd width
268        .p2align 3
2695:
270        TST     r1, 4
271        BEQ     6f
272        VST1.32 {d3[0]}, [r6]!
273        VST1.32 {d2[0]}, [r8]!
274        VST1.32 {d1[0]}, [r4]!
275        VST1.32 {d0[0]}, [r11]!
276        VEXT.8  q1, q1, q1, 4
277        VEXT.8  q0, q0, q0, 4
2786:
279        TST     r1, 2
280        BEQ     7f
281        VST1.16 {d3[0]}, [r6]!
282        VST1.16 {d2[0]}, [r8]!
283        VST1.16 {d1[0]}, [r4]!
284        VST1.16 {d0[0]}, [r11]!
285        VEXT.8  q1, q1, q1, 2
286        VEXT.8  q0, q0, q0, 2
287
2887:
289        TST     r1, 1
290        BEQ     8f
291        VST1.8  {d3[0]}, [r6]
292        VST1.8  {d2[0]}, [r8]
293        VST1.8  {d1[0]}, [r4]
294        VST1.8  {d0[0]}, [r11]
295
2968:
297        VPOP    {d8-d13}
298        ADD     sp, sp, 12              // skip pad, r2, r3
299        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
300
301END_FUNCTION xnn_qs8_igemm_minmax_rndnu_ukernel_4x8c4__aarch32_neondot_ld64
302#endif  // __APPLE__
303
304#ifdef __ELF__
305.section ".note.GNU-stack","",%progbits
306#endif
307