xref: /aosp_15_r20/external/XNNPACK/src/f32-gemm/4x8-minmax-aarch32-neon-cortex-a7.S.in (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Copyright 2020 Google LLC
2//
3// This source code is licensed under the BSD-style license found in the
4// LICENSE file in the root directory of this source tree.
5
6#include <xnnpack/assembly.h>
7
8.syntax unified
9
10# LINT.IfChange
11// void xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7(
12//     size_t mr,                            r0
13//     size_t nc,                            r1
14//     size_t kc,                            r2 -> r5
15//     const uint8_t*restrict a,             r3
16//     size_t a_stride,          sp + 96  -> (r7)
17//     const void*restrict w,    sp + 100 -> r9
18//     uint8_t*restrict c,       sp + 104 -> r11
19//     size_t cm_stride,         sp + 108 -> (r6)
20//     size_t cn_stride,         sp + 112 -> r7
21//     const union xnn_f32_minmax_params params)  sp + 116 -> (r7)
22
23// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
24
25// Register usage
26// A0   r3  d0
27// A1  r12  d1
28// A2  r10  d2
29// A3   r0  d3
30
31// B    r9  d8,  d9, d10, d11
32// B       d12, d13, d14, d15
33
34// C0  r11 d16-d17  q8  d18-d19  q9
35// C1   r4 d20-d21 q10  d22-d23 q11
36// C2   r8 d24-d25 q12  d26-d27 q13
37// C3   r6 d28-d29 q14  d30-d31 q15
38
39// Clamp (r5) d4 d5 d6 d7
40
41BEGIN_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7
42        .arm
43#ifndef __APPLE__
44        .arch   armv7-a
45        .fpu    neon
46#endif
47        # Push 96 bytes
48        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
49        VPUSH   {d8-d15}                            // +64 = 96
50
51        LDR     r7, [sp, 96]            // a_stride
52        LDR     r11, [sp, 104]          // c
53        LDR     r6, [sp, 108]           // cm_stride
54        LDR     r9, [sp, 100]           // w
55        LDR     r5, [sp, 116]           // params
56
57        # Clamp A and C pointers
58        CMP     r0, 2                   // if mr >= 2
59        ADD     r12, r3, r7             //   a1 = a0 + a_stride
60        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
61        MOVLO   r12, r3                 // a1
62        MOVLO   r4, r11                 // c1
63                                        // if mr > 2
64        ADD     r10, r12, r7            //   a2 = a1 + a_stride
65        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
66        MOVLS   r10, r12                // a2
67        MOVLS   r8, r4                  // c2
68
69        CMP     r0, 4                   // if mr >=4
70        ADD     r0, r10, r7             //   a3 = a2 + a_stride
71        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
72        MOVLO   r0, r10                 // a3
73        MOVLO   r6, r8                  // c3
74
75        # Load min/max values
76        VLD1.32 {d4[], d5[]}, [r5]!
77        LDR     r7, [sp, 112]           // cn_stride
78        VLD1.32 {d6[], d7[]}, [r5]
79
800:
81        # Load initial bias from w into accumulators
82        VLDM    r9!, {d16-d19}          // Bias
83        SUBS    r5, r2, 8
84        VMOV    q10, q8
85        VMOV    q11, q9
86        VMOV    q12, q8
87        VMOV    q13, q9
88        VMOV    q14, q8
89        VMOV    q15, q9
90
91        $if PREFETCH:
92          PLD     [r3,  0]                // Prefetch A
93          PLD     [r3, 64]
94          PLD     [r12,  0]
95          PLD     [r12, 64]
96          PLD     [r10,  0]
97          PLD     [r10, 64]
98          PLD     [r0,  0]
99          PLD     [r0, 64]
100          PLD     [r9,   0]               // Prefetch B
101          PLD     [r9,  64]
102          PLD     [r9, 128]
103          PLD     [r9, 192]
104          PLD     [r9, 256]
105          PLD     [r9, 320]
106          PLD     [r9, 384]
107          PLD     [r9, 448]
108        BLO     3f                      // less than 2 channels?
109
110        # Main loop - 2 floats of A (8 bytes)
1111:
112        VLD1.32 {d0}, [r3]!             // A0
113        VLDM    r9!, {d8-d11}           // B0
114        VLD1.32 {d1}, [r12]!            // A1
115        VLD1.32 {d2}, [r10]!            // A2
116        VLD1.32 {d3}, [ r0]!            // A3
117        VLDM    r9!, {d12-d15}          // B1
118        VMLA.F32 q8, q4, d0[0]
119        VMLA.F32 q9, q5, d0[0]
120        VMLA.F32 q10, q4, d1[0]
121        VMLA.F32 q13, q5, d2[0]
122        VMLA.F32 q11, q5, d1[0]
123        VMLA.F32 q12, q4, d2[0]
124        VMLA.F32 q14, q4, d3[0]
125        VMLA.F32 q15, q5, d3[0]
126        VMLA.F32 q8, q6, d0[1]
127        VMLA.F32 q9, q7, d0[1]
128        VMLA.F32 q10, q6, d1[1]
129        VMLA.F32 q11, q7, d1[1]
130        SUBS    r5, r5, 8
131        VMLA.F32 q12, q6, d2[1]
132        VMLA.F32 q13, q7, d2[1]
133        VMLA.F32 q14, q6, d3[1]
134        VMLA.F32 q15, q7, d3[1]
135        $if PREFETCH:
136          PLD     [r9, 448]               // Prefetch B
137          PLD     [r3, 128]               // Prefetch A0
138          PLD     [r12, 128]              // Prefetch A1
139          PLD     [r10, 128]              // Prefetch A2
140          PLD     [r0, 128]               // Prefetch A3
141        BHS     1b
142
143        # Is there a remainder?- 1 float of A (4 bytes)
144        TST     r5, 4
145        BNE     3f
146
1472:
148        # Clamp
149        VMAX.F32 q8,  q8, q2
150        SUBS    r1, r1, 8
151        VMAX.F32 q9,  q9, q2
152        VMAX.F32 q10, q10, q2
153        VMAX.F32 q11, q11, q2
154        VMAX.F32 q12, q12, q2
155        VMAX.F32 q13, q13, q2
156        VMAX.F32 q14, q14, q2
157        VMAX.F32 q15, q15, q2
158        VMIN.F32 q8,  q8, q3
159        VMIN.F32 q9,  q9, q3
160        VMIN.F32 q10, q10, q3
161        VMIN.F32 q11, q11, q3
162        VMIN.F32 q12, q12, q3
163        VMIN.F32 q13, q13, q3
164        VMIN.F32 q14, q14, q3
165        VMIN.F32 q15, q15, q3
166
167        # Store full 4 x 8
168        BLO     4f
169        VST1.32 {d16-d19}, [r11], r7
170        SUB     r0, r0, r2
171        VST1.32 {d20-d23}, [r4], r7
172        SUB     r10, r10, r2
173        VST1.32 {d24-d27}, [r8], r7
174        SUB     r12, r12, r2
175        VST1.32 {d28-d31}, [r6], r7
176        SUB     r3, r3, r2
177        BHI     0b
178
179        VPOP    {d8-d15}
180        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
181        BX      lr
182
1833:
184        # Remainder- 1 float of A (4 bytes)
185        VLDM    r3!,  {s0}              // A0
186        VLDM    r9!, {d8-d11}           // B0
187        VLDM    r12!, {s2}              // A1
188        VLDM    r10!, {s4}              // A2
189        VLDM    r0!, {s6}               // A3
190        VMLA.F32 q8, q4, d0[0]
191        VMLA.F32 q9, q5, d0[0]
192        VMLA.F32 q10, q4, d1[0]
193        VMLA.F32 q11, q5, d1[0]
194        VMLA.F32 q12, q4, d2[0]
195        VMLA.F32 q13, q5, d2[0]
196        VMLA.F32 q14, q4, d3[0]
197        VMLA.F32 q15, q5, d3[0]
198        B       2b
199
200        # Store odd width
2014:
202        TST     r1, 4
203        BEQ     5f
204        VST1.32 {d16-d17}, [r11]!
205        VST1.32 {d20-d21},  [r4]!
206        VMOV    q8,  q9
207        VMOV    q10, q11
208        VST1.32 {d24-d25},  [r8]!
209        VST1.32 {d28-d29},  [r6]!
210        VMOV    q12, q13
211        VMOV    q14, q15
212
2135:
214        TST     r1, 2
215        BEQ     6f
216        VST1.32 {d16}, [r11]!
217        VST1.32 {d20},  [r4]!
218        VMOV    d16, d17
219        VMOV    d20, d21
220        VST1.32 {d24},  [r8]!
221        VST1.32 {d28},  [r6]!
222        VMOV    d24, d25
223        VMOV    d28, d29
224
2256:
226        TST     r1, 1
227        BEQ     7f
228        VST1.32 {d16[0]}, [r11]
229        VST1.32 {d20[0]},  [r4]
230        VST1.32 {d24[0]},  [r8]
231        VST1.32 {d28[0]},  [r6]
232
2337:
234        VPOP    {d8-d15}
235        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
236        BX      lr
237
238END_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7
239# LINT.ThenChange(4x8-aarch32-neon-cortex-a7.cc)
240
241#ifdef __ELF__
242.section ".note.GNU-stack","",%progbits
243#endif
244
245