• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Auto-generated file. Do not edit!
2//   Template: src/qs8-igemm/4x8c4-aarch32-neondot-cortex-a55.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_igemm_minmax_fp32_ukernel_4x8c4__aarch32_neondot_cortex_a55(
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_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 4 bytes
47//  struct {
48//    int16_t output_zero_point;  d13[2]
49//    int8_t output_min;          d13[6]
50//    int8_t output_max;          d13[7]
51//  } xnn_qs8_minmax_params.neonv8;
52
53// iOS does not support 32 bit ARM with Neon DotProduct.
54#ifndef __APPLE__
55BEGIN_FUNCTION xnn_qc8_igemm_minmax_fp32_ukernel_4x8c4__aarch32_neondot_cortex_a55
56        ADD     r2, r2, 3               // kc = (kc + 3) & ~3
57        BIC     r2, r2, 3
58        # Push 96 bytes
59        # r2 will be reloaded in outer loop.  r3 is ks
60        PUSH    {r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}   // +44
61        SUB     sp, sp, 4                                        // 4
62        VPUSH   {d8-d13}                                         // +48 = 96
63
64        LDR     r11, [sp, 104]          // c
65        LDR     r6, [sp, 108]           // cm_stride
66        LDR     r2, [sp, 96]            // a
67        LDR     r9, [sp, 100]           // w
68        LDR     r5, [sp, 124]           // params
69        MOV     r14, r3                 // p = ks
70
71        # Clamp C pointers
72        CMP     r0, 2                   // if mr >= 2
73        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
74        MOVLO   r4, r11                 // c1
75                                        // if mr > 2
76        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
77        MOVLS   r8, r4                  // c2
78        CMP     r0, 4                   // if mr >=4
79        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
80        MOVLO   r6, r8                  // c3
81
82        # Load params values
83        VLD1.32 {d13[]}, [r5]           // QC8 params
84
850:
86        # Load initial bias from w into accumulators
87        VLDM    r9!, {d16-d19}          // Bias
88        VMOV    q10, q8
89        VMOV    q11, q9
90        LDR     r7, [sp, 120]           // zero
91        VMOV    q12, q8
92        VMOV    q13, q9
93        VMOV    q14, q8
94        VMOV    q15, q9
95
961:
97        # Load next 4 A pointers + Add a_offset + Prologue
98        # - Load next 4 A pointers to GPR
99        # - Adjust A pointers by a_offset if not zero
100        # - Load prologue
101        # - Load k = kc from stack
102        LDR     r3, [r2,  0]            // A0
103        LDR     r5, [sp, 116]           // a_offset
104        CMP     r3,  r7                 // if a0 == zero
105        LDR     r12, [r2,  4]           // A1
106        ADD     r3,  r3, r5             // a0 += a_offset
107        LDR     r10, [r2,  8]           // A2
108        MOVEQ   r3,  r7                 //   a0 = zero, else += a0 + a_offset
109        LDR     r0, [r2, 12]            // A3
110        CMP     r12,  r7                // if a1 == zero
111        VLD1.8  {d4},  [r9]!            // B0
112        ADD     r12, r12, r5            // a1 += a_offset
113        VLD1.8  {d5},  [r9]!            // B1
114        MOVEQ   r12,  r7                //   a1 = zero, else += a1 + a_offset
115        VLD1.8  {d6},  [r9]!            // B2
116        CMP     r10,  r7                // if a2 == zero
117        VLD1.8  {d7},  [r9]!            // B3
118        ADD     r10, r10, r5            // a2 += a_offset
119        VLD1.8  {d0},  [r3]!            // A0
120        MOVEQ   r10,  r7                //   a2 = zero, else += a2 + a_offset
121        VLD1.8  {d1}, [r12]!            // A1
122        CMP     r0,  r7                 // if a3 == zero
123        ADD     r0,  r0, r5             // a3 += a_offset
124        LDR     r5, [sp, 52]            // k = kc
125        MOVEQ   r0,  r7                 //   a3 = zero, else += a3 + a_offset
126        SUBS    r5, r5, 8               // k = k - 8
127        ADD     r2, r2, 16
128
129        BLO     4f                      // less than 8 channels?
130
131        SUBS    r5, r5, 8               // k = k - 8
132        BLO     21f                     // less than 8 channels?
133
134        # Main loop - 8 bytes of A.
135        # 16 SDOT, 12 LD64
136        .p2align 3
1372:
138        VSDOT.S8 q8, q2, d0[0]
139        VLD1.8  {d2}, [r10]!            // A2
140        VSDOT.S8 q9, q3, d0[0]
141        VLD1.8  {d3},  [r0]!            // A3
142        VSDOT.S8 q10, q2, d1[0]
143        VLD1.8  {d8},  [r9]!            // B4
144        VSDOT.S8 q11, q3, d1[0]
145        VLD1.8  {d9},  [r9]!            // B5
146        VSDOT.S8 q12, q2, d2[0]
147        VLD1.8  {d10},  [r9]!           // B6
148        VSDOT.S8 q13, q3, d2[0]
149        VLD1.8  {d11},  [r9]!           // B7
150        VSDOT.S8 q14, q2, d3[0]
151        VSDOT.S8 q15, q3, d3[0]
152        SUBS    r5, r5, 8
153
154        VSDOT.S8 q8, q4, d0[1]
155        VLD1.8  {d4},  [r9]!            // B0
156        VSDOT.S8 q9, q5, d0[1]
157        VLD1.8  {d5},  [r9]!            // B1
158        VSDOT.S8 q10, q4, d1[1]
159        VLD1.8  {d6},  [r9]!            // B2
160        VSDOT.S8 q11, q5, d1[1]
161        VLD1.8  {d7},  [r9]!            // B3
162        VSDOT.S8 q12, q4, d2[1]
163        VLD1.8  {d0},  [r3]!            // A0
164        VSDOT.S8 q13, q5, d2[1]
165        VLD1.8  {d1}, [r12]!            // A1
166        VSDOT.S8 q14, q4, d3[1]
167        VSDOT.S8 q15, q5, d3[1]
168        BHS     2b
169
170        # Epilogue
171        .p2align 3
17221:
173        VSDOT.S8 q8, q2, d0[0]
174        VLD1.8  {d2}, [r10]!            // A2
175        VSDOT.S8 q9, q3, d0[0]
176        VLD1.8  {d3},  [r0]!            // A3
177        VSDOT.S8 q10, q2, d1[0]
178        VLD1.8  {d8},  [r9]!            // B4
179        VSDOT.S8 q11, q3, d1[0]
180        VLD1.8  {d9},  [r9]!            // B5
181        VSDOT.S8 q12, q2, d2[0]
182        VLD1.8  {d10},  [r9]!           // B6
183        VSDOT.S8 q13, q3, d2[0]
184        VLD1.8  {d11},  [r9]!           // B7
185        VSDOT.S8 q14, q2, d3[0]
186        VSDOT.S8 q15, q3, d3[0]
187        TST     r5, 5
188
189        VSDOT.S8 q8, q4, d0[1]
190        VSDOT.S8 q9, q5, d0[1]
191        VSDOT.S8 q10, q4, d1[1]
192        VSDOT.S8 q11, q5, d1[1]
193        VSDOT.S8 q12, q4, d2[1]
194        VSDOT.S8 q13, q5, d2[1]
195        VSDOT.S8 q14, q4, d3[1]
196        VSDOT.S8 q15, q5, d3[1]
197        # Is there a remainder?- 4 bytes of A
198        BNE     40f
199
2003:
201        # ks loop
202        SUBS    r14, r14, 16            // ks -= MR * sizeof(void*)
203        BHI     1b
204
205        LDR     r7, [sp, 112]           // cn_stride
206        LDR     r14, [sp, 56]           // p = ks
207
208        # QC8 FP32 quantization
209        VLD1.8  {q0-q1},  [r9]!
210
211        VCVT.F32.S32 q8,  q8
212        VCVT.F32.S32 q9,  q9
213        VCVT.F32.S32 q10, q10
214        VCVT.F32.S32 q11, q11
215        VCVT.F32.S32 q12, q12
216        VCVT.F32.S32 q13, q13
217        VCVT.F32.S32 q14, q14
218        VCVT.F32.S32 q15, q15
219
220        VMUL.F32 q8,  q8, q0            // multiplier
221        VMUL.F32 q9,  q9, q1
222        VMUL.F32 q10, q10, q0
223        VMUL.F32 q11, q11, q1
224        VMUL.F32 q12, q12, q0
225        VMUL.F32 q13, q13, q1
226        VMUL.F32 q14, q14, q0
227        VMUL.F32 q15, q15, q1
228
229        VCVTN.S32.F32 q8,  q8
230        VCVTN.S32.F32 q9,  q9
231        VCVTN.S32.F32 q10, q10
232        VCVTN.S32.F32 q11, q11
233        VCVTN.S32.F32 q12, q12
234        VCVTN.S32.F32 q13, q13
235        VCVTN.S32.F32 q14, q14
236        VCVTN.S32.F32 q15, q15
237        VDUP.16 q0, d13[2]              // output_zero_point
238
239        VQMOVN.S32 d16, q8
240        VQMOVN.S32 d17, q9
241        VQMOVN.S32 d18, q10
242        VQMOVN.S32 d19, q11
243        VQMOVN.S32 d20, q12
244        VQMOVN.S32 d21, q13
245        VQMOVN.S32 d22, q14
246        VQMOVN.S32 d23, q15
247
248        VQADD.S16 q8,  q8, q0
249        VQADD.S16 q9,  q9, q0
250        VQADD.S16 q10, q10, q0
251        VQADD.S16 q11, q11, q0
252
253        VDUP.8  q12, d13[6]             // output_min
254
255        VQMOVN.S16 d0,  q8
256        VQMOVN.S16 d1,  q9
257        VQMOVN.S16 d2, q10
258        VQMOVN.S16 d3, q11
259
260        VDUP.8  q13, d13[7]             // output_min
261
262        VMAX.S8 q0, q0, q12
263        VMAX.S8 q1, q1, q12
264
265        SUBS    r1, r1, 8               // nc -= 8
266
267        VMIN.S8 q0, q0, q13
268        VMIN.S8 q1, q1, q13
269
270        # Store full 4 x 8
271        BLO     5f
272        VST1.8  {d3}, [r6], r7
273        VST1.8  {d2}, [r8], r7
274        VST1.8  {d1}, [r4], r7
275        VST1.8  {d0}, [r11], r7
276        SUB     r2, r2, r14             // a -= ks
277        BHI     0b
278
279        VPOP    {d8-d13}
280        ADD     sp, sp, 12              // skip pad, r2, r3
281        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
282
283        # Remainder prologue
284        .p2align 3
28540:
286        VLD1.8  {d4},  [r9]!            // B0
287        VLD1.8  {d0},  [r3]!            // A0
288        VLD1.8  {d5},  [r9]!            // B1
289        VLD1.8  {d6},  [r9]!            // B2
290        VLD1.8  {d1}, [r12]!            // A1
291        VLD1.8  {d7},  [r9]!            // B3
292
293        # Remainder- 4 bytes of A
2944:
295        VSDOT.S8 q8, q2, d0[0]
296        VLD1.32 {d2[0]}, [r10]!         // A2
297        VSDOT.S8 q9, q3, d0[0]
298        VLD1.32 {d3[0]},  [r0]!         // A3
299        VSDOT.S8 q10, q2, d1[0]
300        SUB     r3, r3, 4               // Rewind A0
301        VSDOT.S8 q11, q3, d1[0]
302        SUB     r12, r12, 4             // Rewind A1
303        VSDOT.S8 q12, q2, d2[0]
304        VSDOT.S8 q13, q3, d2[0]
305        VSDOT.S8 q14, q2, d3[0]
306        VSDOT.S8 q15, q3, d3[0]
307        B       3b
308
309        # Store odd width
310        .p2align 3
3115:
312        TST     r1, 4
313        BEQ     6f
314        VST1.32 {d3[0]}, [r6]!
315        VST1.32 {d2[0]}, [r8]!
316        VST1.32 {d1[0]}, [r4]!
317        VST1.32 {d0[0]}, [r11]!
318        VEXT.8  q0, q0, q0, 4
319        VEXT.8  q1, q1, q1, 4
3206:
321        TST     r1, 2
322        BEQ     7f
323        VST1.16 {d3[0]}, [r6]!
324        VST1.16 {d2[0]}, [r8]!
325        VST1.16 {d1[0]}, [r4]!
326        VST1.16 {d0[0]}, [r11]!
327        VEXT.8  q0, q0, q0, 2
328        VEXT.8  q1, q1, q1, 2
329
3307:
331        TST     r1, 1
332        BEQ     8f
333        VST1.8  {d3[0]}, [r6]
334        VST1.8  {d2[0]}, [r8]
335        VST1.8  {d1[0]}, [r4]
336        VST1.8  {d0[0]}, [r11]
337
3388:
339        VPOP    {d8-d13}
340        ADD     sp, sp, 12              // skip pad, r2, r3
341        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
342
343END_FUNCTION xnn_qc8_igemm_minmax_fp32_ukernel_4x8c4__aarch32_neondot_cortex_a55
344#endif  // __APPLE__
345
346#ifdef __ELF__
347.section ".note.GNU-stack","",%progbits
348#endif
349