xref: /aosp_15_r20/external/XNNPACK/src/f32-gemm/gen/4x8-minmax-aarch32-neon-cortex-a7.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/f32-gemm/4x8-minmax-aarch32-neon-cortex-a7.S.in
3//   Generator: tools/xngen
4//
5// Copyright 2020 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_cortex_a7(
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_cortex_a7
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        PLD     [r3,  0]                // Prefetch A
95        PLD     [r3, 64]
96        PLD     [r12,  0]
97        PLD     [r12, 64]
98        PLD     [r10,  0]
99        PLD     [r10, 64]
100        PLD     [r0,  0]
101        PLD     [r0, 64]
102        PLD     [r9,   0]               // Prefetch B
103        PLD     [r9,  64]
104        PLD     [r9, 128]
105        PLD     [r9, 192]
106        PLD     [r9, 256]
107        PLD     [r9, 320]
108        PLD     [r9, 384]
109        PLD     [r9, 448]
110        BLO     3f                      // less than 2 channels?
111
112        # Main loop - 2 floats of A (8 bytes)
1131:
114        VLD1.32 {d0}, [r3]!             // A0
115        VLDM    r9!, {d8-d11}           // B0
116        VLD1.32 {d1}, [r12]!            // A1
117        VLD1.32 {d2}, [r10]!            // A2
118        VLD1.32 {d3}, [ r0]!            // A3
119        VLDM    r9!, {d12-d15}          // B1
120        VMLA.F32 q8, q4, d0[0]
121        VMLA.F32 q9, q5, d0[0]
122        VMLA.F32 q10, q4, d1[0]
123        VMLA.F32 q13, q5, d2[0]
124        VMLA.F32 q11, q5, d1[0]
125        VMLA.F32 q12, q4, d2[0]
126        VMLA.F32 q14, q4, d3[0]
127        VMLA.F32 q15, q5, d3[0]
128        VMLA.F32 q8, q6, d0[1]
129        VMLA.F32 q9, q7, d0[1]
130        VMLA.F32 q10, q6, d1[1]
131        VMLA.F32 q11, q7, d1[1]
132        SUBS    r5, r5, 8
133        VMLA.F32 q12, q6, d2[1]
134        VMLA.F32 q13, q7, d2[1]
135        VMLA.F32 q14, q6, d3[1]
136        VMLA.F32 q15, q7, d3[1]
137        PLD     [r9, 448]               // Prefetch B
138        PLD     [r3, 128]               // Prefetch A0
139        PLD     [r12, 128]              // Prefetch A1
140        PLD     [r10, 128]              // Prefetch A2
141        PLD     [r0, 128]               // Prefetch A3
142        BHS     1b
143
144        # Is there a remainder?- 1 float of A (4 bytes)
145        TST     r5, 4
146        BNE     3f
147
1482:
149        # Clamp
150        VMAX.F32 q8,  q8, q2
151        SUBS    r1, r1, 8
152        VMAX.F32 q9,  q9, q2
153        VMAX.F32 q10, q10, q2
154        VMAX.F32 q11, q11, q2
155        VMAX.F32 q12, q12, q2
156        VMAX.F32 q13, q13, q2
157        VMAX.F32 q14, q14, q2
158        VMAX.F32 q15, q15, q2
159        VMIN.F32 q8,  q8, q3
160        VMIN.F32 q9,  q9, q3
161        VMIN.F32 q10, q10, q3
162        VMIN.F32 q11, q11, q3
163        VMIN.F32 q12, q12, q3
164        VMIN.F32 q13, q13, q3
165        VMIN.F32 q14, q14, q3
166        VMIN.F32 q15, q15, q3
167
168        # Store full 4 x 8
169        BLO     4f
170        VST1.32 {d16-d19}, [r11], r7
171        SUB     r0, r0, r2
172        VST1.32 {d20-d23}, [r4], r7
173        SUB     r10, r10, r2
174        VST1.32 {d24-d27}, [r8], r7
175        SUB     r12, r12, r2
176        VST1.32 {d28-d31}, [r6], r7
177        SUB     r3, r3, r2
178        BHI     0b
179
180        VPOP    {d8-d15}
181        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
182        BX      lr
183
1843:
185        # Remainder- 1 float of A (4 bytes)
186        VLDM    r3!,  {s0}              // A0
187        VLDM    r9!, {d8-d11}           // B0
188        VLDM    r12!, {s2}              // A1
189        VLDM    r10!, {s4}              // A2
190        VLDM    r0!, {s6}               // A3
191        VMLA.F32 q8, q4, d0[0]
192        VMLA.F32 q9, q5, d0[0]
193        VMLA.F32 q10, q4, d1[0]
194        VMLA.F32 q11, q5, d1[0]
195        VMLA.F32 q12, q4, d2[0]
196        VMLA.F32 q13, q5, d2[0]
197        VMLA.F32 q14, q4, d3[0]
198        VMLA.F32 q15, q5, d3[0]
199        B       2b
200
201        # Store odd width
2024:
203        TST     r1, 4
204        BEQ     5f
205        VST1.32 {d16-d17}, [r11]!
206        VST1.32 {d20-d21},  [r4]!
207        VMOV    q8,  q9
208        VMOV    q10, q11
209        VST1.32 {d24-d25},  [r8]!
210        VST1.32 {d28-d29},  [r6]!
211        VMOV    q12, q13
212        VMOV    q14, q15
213
2145:
215        TST     r1, 2
216        BEQ     6f
217        VST1.32 {d16}, [r11]!
218        VST1.32 {d20},  [r4]!
219        VMOV    d16, d17
220        VMOV    d20, d21
221        VST1.32 {d24},  [r8]!
222        VST1.32 {d28},  [r6]!
223        VMOV    d24, d25
224        VMOV    d28, d29
225
2266:
227        TST     r1, 1
228        BEQ     7f
229        VST1.32 {d16[0]}, [r11]
230        VST1.32 {d20[0]},  [r4]
231        VST1.32 {d24[0]},  [r8]
232        VST1.32 {d28[0]},  [r6]
233
2347:
235        VPOP    {d8-d15}
236        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
237        BX      lr
238
239END_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7
240
241#ifdef __ELF__
242.section ".note.GNU-stack","",%progbits
243#endif
244
245