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[restrict XNN_MIN_ELEMENTS(1)])  sp + 116 -> (r7)
25
26
27// inner loop registers
28
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 floats 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 floats 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        VMOV         q8,  q9
187        VST1.32    {d20-d21},  [r4]!
188        VMOV        q10, q11
189        VST1.32    {d24-d25},  [r8]!
190        VMOV        q12, q13
191        VST1.32    {d28-d29},  [r6]!
192        VMOV        q14, q15
193
1945:
195        TST        r1, 2
196        BEQ        6f
197        VST1.32    {d16}, [r11]!
198        VMOV        d16, d17
199        VST1.32    {d20},  [r4]!
200        VMOV        d20, d21
201        VST1.32    {d24},  [r8]!
202        VMOV        d24, d25
203        VST1.32    {d28},  [r6]!
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