xref: /aosp_15_r20/external/XNNPACK/src/f32-gemm/gen/4x8-minmax-aarch32-neon-ld64.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/f32-gemm/4x8-minmax-aarch32-neon-ld64.S.in
3//   Generator: tools/xngen
4//
5// Copyright 2019 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#include <xnnpack/assembly.h>
11
12.syntax unified
13
14// void xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_ld64(
15//     size_t mr,                            r0
16//     size_t nc,                            r1
17//     size_t kc,                            r2 -> r5
18//     const uint8_t*restrict a,             r3
19//     size_t a_stride,          sp + 96  -> (r7)
20//     const void*restrict w,    sp + 100 -> r9
21//     uint8_t*restrict c,       sp + 104 -> r11
22//     size_t cm_stride,         sp + 108 -> (r6)
23//     size_t cn_stride,         sp + 112 -> r7
24//     const union xnn_f32_minmax_params params)  sp + 116 -> (r7)
25
26// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
27
28// Register usage
29// A0   r3  d0
30// A1  r12  d1
31// A2  r10  d2
32// A3   r0  d3
33
34// B    r9  d8,  d9, d10, d11
35// B       d12, d13, d14, d15
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// Clamp (r5) d4 d5 d6 d7
43
44BEGIN_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_ld64
45        .arm
46#ifndef __APPLE__
47        .arch   armv7-a
48        .fpu    neon
49#endif
50        # Push 96 bytes
51        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
52        VPUSH   {d8-d15}                            // +64 = 96
53
54        LDR     r7, [sp, 96]            // a_stride
55        LDR     r11, [sp, 104]          // c
56        LDR     r6, [sp, 108]           // cm_stride
57        LDR     r9, [sp, 100]           // w
58        LDR     r5, [sp, 116]           // params
59
60        # Clamp A and C pointers
61        CMP     r0, 2                   // if mr >= 2
62        ADD     r12, r3, r7             //   a1 = a0 + a_stride
63        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
64        MOVLO   r12, r3                 // a1
65        MOVLO   r4, r11                 // c1
66                                        // if mr > 2
67        ADD     r10, r12, r7            //   a2 = a1 + a_stride
68        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
69        MOVLS   r10, r12                // a2
70        MOVLS   r8, r4                  // c2
71
72        CMP     r0, 4                   // if mr >=4
73        ADD     r0, r10, r7             //   a3 = a2 + a_stride
74        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
75        MOVLO   r0, r10                 // a3
76        MOVLO   r6, r8                  // c3
77
78        # Load min/max values
79        VLD1.32 {d4[], d5[]}, [r5]!
80        LDR     r7, [sp, 112]           // cn_stride
81        VLD1.32 {d6[], d7[]}, [r5]
82
830:
84        # Load initial bias from w into accumulators
85        VLDM    r9!, {d16-d19}          // Bias
86        SUBS    r5, r2, 8
87        VMOV    q10, q8
88        VMOV    q11, q9
89        VMOV    q12, q8
90        VMOV    q13, q9
91        VMOV    q14, q8
92        VMOV    q15, q9
93
94        BLO     3f                      // less than 2 channels?
95
96        # Main loop - 2 floats of A (8 bytes)
971:
98        VLD1.32 {d0}, [r3]!             // A0
99        VLDM    r9!, {d8-d11}           // B0
100        VLD1.32 {d1}, [r12]!            // A1
101        VLD1.32 {d2}, [r10]!            // A2
102        VLD1.32 {d3}, [ r0]!            // A3
103        VLDM    r9!, {d12-d15}          // B1
104
105        VMLA.F32 q8, q4, d0[0]
106        VMLA.F32 q9, q5, d0[0]
107        VMLA.F32 q10, q4, d1[0]
108        VMLA.F32 q13, q5, d2[0]
109        VMLA.F32 q11, q5, d1[0]
110        VMLA.F32 q12, q4, d2[0]
111        VMLA.F32 q14, q4, d3[0]
112        VMLA.F32 q15, q5, d3[0]
113        VMLA.F32 q8, q6, d0[1]
114        VMLA.F32 q9, q7, d0[1]
115        VMLA.F32 q10, q6, d1[1]
116        VMLA.F32 q11, q7, d1[1]
117        SUBS    r5, r5, 8
118        VMLA.F32 q12, q6, d2[1]
119        VMLA.F32 q13, q7, d2[1]
120        VMLA.F32 q14, q6, d3[1]
121        VMLA.F32 q15, q7, d3[1]
122        BHS     1b
123
124        # Is there a remainder?- 1 float of A (4 bytes)
125        TST     r5, 4
126        BNE     3f
127
1282:
129        # Clamp
130        VMAX.F32 q8,  q8, q2
131        SUBS    r1, r1, 8
132        VMAX.F32 q9,  q9, q2
133        VMAX.F32 q10, q10, q2
134        VMAX.F32 q11, q11, q2
135        VMAX.F32 q12, q12, q2
136        VMAX.F32 q13, q13, q2
137        VMAX.F32 q14, q14, q2
138        VMAX.F32 q15, q15, q2
139        VMIN.F32 q8,  q8, q3
140        VMIN.F32 q9,  q9, q3
141        VMIN.F32 q10, q10, q3
142        VMIN.F32 q11, q11, q3
143        VMIN.F32 q12, q12, q3
144        VMIN.F32 q13, q13, q3
145        VMIN.F32 q14, q14, q3
146        VMIN.F32 q15, q15, q3
147
148        # Store full 4 x 8
149        BLO     4f
150        VST1.32 {d16-d19}, [r11], r7
151        SUB     r0, r0, r2
152        VST1.32 {d20-d23}, [r4], r7
153        SUB     r10, r10, r2
154        VST1.32 {d24-d27}, [r8], r7
155        SUB     r12, r12, r2
156        VST1.32 {d28-d31}, [r6], r7
157        SUB     r3, r3, r2
158        BHI     0b
159
160        VPOP    {d8-d15}
161        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
162        BX      lr
163
1643:
165        # Remainder- 1 float of A (4 bytes)
166        VLDM    r3!,  {s0}              // A0
167        VLDM    r9!, {d8-d11}           // B0
168        VLDM    r12!, {s2}              // A1
169        VLDM    r10!, {s4}              // A2
170        VLDM    r0!, {s6}               // A3
171        VMLA.F32 q8, q4, d0[0]
172        VMLA.F32 q9, q5, d0[0]
173        VMLA.F32 q10, q4, d1[0]
174        VMLA.F32 q11, q5, d1[0]
175        VMLA.F32 q12, q4, d2[0]
176        VMLA.F32 q13, q5, d2[0]
177        VMLA.F32 q14, q4, d3[0]
178        VMLA.F32 q15, q5, d3[0]
179        B       2b
180
181        # Store odd width
1824:
183        TST     r1, 4
184        BEQ     5f
185        VST1.32 {d16-d17}, [r11]!
186        VST1.32 {d20-d21},  [r4]!
187        VMOV    q8,  q9
188        VMOV    q10, q11
189        VST1.32 {d24-d25},  [r8]!
190        VST1.32 {d28-d29},  [r6]!
191        VMOV    q12, q13
192        VMOV    q14, q15
193
1945:
195        TST     r1, 2
196        BEQ     6f
197        VST1.32 {d16}, [r11]!
198        VST1.32 {d20},  [r4]!
199        VMOV    d16, d17
200        VMOV    d20, d21
201        VST1.32 {d24},  [r8]!
202        VST1.32 {d28},  [r6]!
203        VMOV    d24, d25
204        VMOV    d28, d29
205
2066:
207        TST     r1, 1
208        BEQ     7f
209        VST1.32 {d16[0]}, [r11]
210        VST1.32 {d20[0]},  [r4]
211        VST1.32 {d24[0]},  [r8]
212        VST1.32 {d28[0]},  [r6]
213
2147:
215        VPOP    {d8-d15}
216        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
217        BX      lr
218
219END_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_ld64
220
221#ifdef __ELF__
222.section ".note.GNU-stack","",%progbits
223#endif
224
225