• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_qs8_gemm_minmax_rndnu_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_conv_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 16 bytes
45//  struct {
46//    int32_t right_pre_shift;    d12[0]
47//    int32_t multiplier;         d12[1]
48//    int32_t right_post_shift;   d13[0]
49//    int16_t output_zero_point;  d13[2]
50//    int8_t output_min;          d13[6]
51//    int8_t output_max;          d13[7]
52//  } rndnu_neon;
53
54// iOS does not support 32 bit ARM with Neon DotProduct.
55#ifndef __APPLE__
56BEGIN_FUNCTION xnn_qs8_gemm_minmax_rndnu_ukernel_4x8c4__aarch32_neondot_ld64
57        # Push 80 bytes
58        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
59        VPUSH   {d8-d13}                            // +48 = 80
60
61        LDR     r7, [sp, 80]            // a_stride
62        ADD     r2, r2, 3               // kc = (kc + 3) & ~3
63        LDR     r11, [sp, 88]           // c
64        LDR     r6, [sp, 92]            // cm_stride
65        LDR     r9, [sp, 84]            // w
66        BIC     r2, r2, 3
67        LDR     r5, [sp, 100]           // params
68
69        # Clamp A and C pointers
70        CMP     r0, 2                   // if mr >= 2
71        ADD     r12, r3, r7             //   a1 = a0 + a_stride
72        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
73        MOVLO   r12, r3                 // a1
74        MOVLO   r4, r11                 // c1
75                                        // if mr > 2
76        ADD     r10, r12, r7            //   a2 = a1 + a_stride
77        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
78        MOVLS   r10, r12                // a2
79        MOVLS   r8, r4                  // c2
80
81        CMP     r0, 4                   // if mr >=4
82        ADD     r0, r10, r7             //   a3 = a2 + a_stride
83        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
84        MOVLO   r0, r10                 // a3
85        MOVLO   r6, r8                  // c3
86
87        # Load params values
88        VLDM    r5, {d12-d13}           // RNDNU params
89        LDR     r7, [sp, 96]            // cn_stride
90
91        .p2align 3
920:
93        # Load initial bias from w into accumulators
94        VLDM    r9!, {d16-d19}          // Bias
95        SUBS    r5, r2, 8               // k = kc - 8
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     3f                      // less than 8 channels?
103
104        # Main loop - 8 bytes of A.
105        # 16 SDOT, 4 LD64 A, 4 LD128 B
106        .p2align 3
1071:
108        VLD1.8  {d0},  [r3]!            // A0
109        VLD1.8  {q2},  [r9]!            // B0
110        VLD1.8  {d1}, [r12]!            // A1
111        VLD1.8  {q3},  [r9]!            // B1
112        VLD1.8  {d2}, [r10]!            // A2
113        VLD1.8  {q4},  [r9]!            // B2
114        VLD1.8  {d3},  [r0]!            // A3
115        VLD1.8  {q5},  [r9]!            // B3
116        SUBS    r5, r5, 8
117
118        VSDOT.S8 q8, q2, d0[0]
119        VSDOT.S8 q9, q3, d0[0]
120        VSDOT.S8 q10, q2, d1[0]
121        VSDOT.S8 q11, q3, d1[0]
122        VSDOT.S8 q12, q2, d2[0]
123        VSDOT.S8 q13, q3, d2[0]
124        VSDOT.S8 q14, q2, d3[0]
125        VSDOT.S8 q15, q3, d3[0]
126
127        VSDOT.S8 q8, q4, d0[1]
128        VSDOT.S8 q9, q5, d0[1]
129        VSDOT.S8 q10, q4, d1[1]
130        VSDOT.S8 q11, q5, d1[1]
131        VSDOT.S8 q12, q4, d2[1]
132        VSDOT.S8 q13, q5, d2[1]
133        VSDOT.S8 q14, q4, d3[1]
134        VSDOT.S8 q15, q5, d3[1]
135        BHS     1b
136
137        # Is there a remainder?- 4 bytes of A
138        ADDS    r5, r5, 8
139        BNE     3f
140
1412:
142        # RNDNU quantization
143        VDUP.32 q0, d12[0]              // right_pre_shift
144
145        VQSHL.S32 q8,  q8, q0
146        VQSHL.S32 q9,  q9, q0
147        VQSHL.S32 q10, q10, q0
148        VQSHL.S32 q11, q11, q0
149        VQSHL.S32 q12, q12, q0
150        VQSHL.S32 q13, q13, q0
151        VQSHL.S32 q14, q14, q0
152        VQSHL.S32 q15, q15, q0
153
154        VDUP.32 q2, d13[0]              // right_post_shift
155
156        VQDMULH.S32 q8,  q8, d12[1]     // multiplier
157        VQDMULH.S32 q9,  q9, d12[1]
158        VQDMULH.S32 q10, q10, d12[1]
159        VQDMULH.S32 q11, q11, d12[1]
160        VQDMULH.S32 q12, q12, d12[1]
161        VQDMULH.S32 q13, q13, d12[1]
162        VQDMULH.S32 q14, q14, d12[1]
163        VQDMULH.S32 q15, q15, d12[1]
164
165        VRSHL.S32 q8,  q8, q2
166        VRSHL.S32 q9,  q9, q2
167        VRSHL.S32 q10, q10, q2
168        VRSHL.S32 q11, q11, q2
169        VRSHL.S32 q12, q12, q2
170        VRSHL.S32 q13, q13, q2
171        VRSHL.S32 q14, q14, q2
172        VRSHL.S32 q15, q15, q2
173
174        VDUP.16 q0, d13[2]              // output_zero_point
175
176        VQMOVN.S32 d16, q8
177        VQMOVN.S32 d17, q9
178        VQMOVN.S32 d18, q10
179        VQMOVN.S32 d19, q11
180        VQMOVN.S32 d20, q12
181        VQMOVN.S32 d21, q13
182        VQMOVN.S32 d22, q14
183        VQMOVN.S32 d23, q15
184
185        VQADD.S16 q8,  q8, q0
186        VQADD.S16 q9,  q9, q0
187        VQADD.S16 q10, q10, q0
188        VQADD.S16 q11, q11, q0
189
190        VDUP.8  q12, d13[6]             // output_min
191
192        VQMOVN.S16 d0,  q8
193        VQMOVN.S16 d1,  q9
194        VQMOVN.S16 d2, q10
195        VQMOVN.S16 d3, q11
196
197        VDUP.8  q13, d13[7]             // output_max
198
199        VMAX.S8 q0, q0, q12
200        VMAX.S8 q1, q1, q12
201
202        SUBS    r1, r1, 8
203
204        VMIN.S8 q0, q0, q13
205        VMIN.S8 q1, q1, q13
206
207        # Store full 4 x 8
208        BLO     4f
209        VST1.8  {d0}, [r11], r7
210        SUB     r3, r3, r2
211        VST1.8  {d1}, [r4], r7
212        SUB     r12, r12, r2
213        VST1.8  {d2}, [r8], r7
214        SUB     r10, r10, r2
215        VST1.8  {d3}, [r6], r7
216        SUB     r0, r0, r2
217        BHI     0b
218
219        VPOP    {d8-d13}
220        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
221        BX      lr
222
223        # Remainder- 4 bytes of A
224        .p2align 3
2253:
226        VLD1.32 {d0[0]},  [r3]!         // A0
227        VLD1.32 {q2},  [r9]!            // B0
228        VLD1.32 {d1[0]}, [r12]!         // A1
229        VLD1.32 {q3},  [r9]!            // B1
230        VLD1.32 {d2[0]}, [r10]!         // A2
231        VLD1.32 {d3[0]},  [r0]!         // A3
232
233        VSDOT.S8 q8, q2, d0[0]
234        VSDOT.S8 q9, q3, d0[0]
235        VSDOT.S8 q10, q2, d1[0]
236        VSDOT.S8 q11, q3, d1[0]
237        VSDOT.S8 q12, q2, d2[0]
238        VSDOT.S8 q13, q3, d2[0]
239        VSDOT.S8 q14, q2, d3[0]
240        VSDOT.S8 q15, q3, d3[0]
241        B       2b
242
243        # Store odd width
244        .p2align 3
2454:
246        TST     r1, 4
247        BEQ     5f
248        VST1.32 {d0[0]}, [r11]!
249        VST1.32 {d1[0]}, [r4]!
250        VST1.32 {d2[0]}, [r8]!
251        VST1.32 {d3[0]}, [r6]!
252        VEXT.8  q0, q0, q0, 4
253        VEXT.8  q1, q1, q1, 4
2545:
255        TST     r1, 2
256        BEQ     6f
257        VST1.16 {d0[0]}, [r11]!
258        VST1.16 {d1[0]}, [r4]!
259        VST1.16 {d2[0]}, [r8]!
260        VST1.16 {d3[0]}, [r6]!
261        VEXT.8  q0, q0, q0, 2
262        VEXT.8  q1, q1, q1, 2
263
2646:
265        TST     r1, 1
266        BEQ     7f
267        VST1.8  {d0[0]}, [r11]
268        VST1.8  {d1[0]}, [r4]
269        VST1.8  {d2[0]}, [r8]
270        VST1.8  {d3[0]}, [r6]
271
2727:
273        VPOP    {d8-d13}
274        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
275        BX      lr
276
277END_FUNCTION xnn_qs8_gemm_minmax_rndnu_ukernel_4x8c4__aarch32_neondot_ld64
278#endif  // __APPLE__
279
280#ifdef __ELF__
281.section ".note.GNU-stack","",%progbits
282#endif
283
284