• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Auto-generated file. Do not edit!
2//   Template: src/f32-igemm/4x8-minmax-aarch32-neon-cortex-a7.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_igemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7(
15//     size_t mr,                            r0
16//     size_t nc,                            r1
17//     size_t kc,                            r2 -> r5 -> sp + 68
18//     size_t ks,                            r3 -> sp + 72 -> r14
19//     const float**restrict a,  sp + 112 -> r2
20//     const void*restrict w,    sp + 116 -> r9
21//     uint8_t*restrict c,       sp + 120 -> r11
22//     size_t cm_stride,         sp + 124 -> (r6)
23//     size_t cn_stride,         sp + 128 -> (r7)
24//     size_t a_offset,          sp + 132 -> (r5)
25//     const float* zero,        sp + 136 -> (r7)
26//     minmax_params*params,     sp + 140 -> (r5)
27
28// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
29
30// Register usage
31// A0   r3  d0
32// A1  r12  d1
33// A2  r10  d2
34// A3   r0  d3
35
36// B    r9  d8,  d9, d10, d11
37// B       d12, d13, d14, d15
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// Clamp (r5) d4 d5 d6 d7
45
46BEGIN_FUNCTION xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7
47        .arm
48#ifndef __APPLE__
49        .arch   armv7-a
50        .fpu    neon
51#endif
52        # Push 112 bytes
53        # r2 will be reloaded in outer loop.  r3 is ks
54        PUSH    {r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}   // +44
55        SUB     sp, sp, 4                                        // 4
56        VPUSH   {d8-d15}                                         // +64 = 112
57
58        LDR     r11, [sp, 120]          // c
59        LDR     r6, [sp, 124]           // cm_stride
60        LDR     r2, [sp, 112]           // a
61        LDR     r9, [sp, 116]           // w
62        LDR     r5, [sp, 140]           // params
63        MOV     r14, r3                 // p = ks
64
65        # Clamp C pointers
66        CMP     r0, 2                   // if mr >= 2
67        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
68        MOVLO   r4, r11                 // c1
69                                        // if mr > 2
70        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
71        MOVLS   r8, r4                  // c2
72        CMP     r0, 4                   // if mr >=4
73        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
74        MOVLO   r6, r8                  // c3
75
76        # Load min/max values
77        VLD1.32 {d4[], d5[]}, [r5]!
78        VLD1.32 {d6[], d7[]}, [r5]
79
800:
81        # Load initial bias from w into accumulators
82        VLDM    r9!, {d16-d19}          // Bias
83        VMOV    q10, q8
84        VMOV    q11, q9
85        VMOV    q12, q8
86        VMOV    q13, q9
87        VMOV    q14, q8
88        VMOV    q15, q9
89
90        PLD     [r9,   0]               // Prefetch B
91        PLD     [r9,  64]
92        PLD     [r9, 128]
93        PLD     [r9, 192]
94        PLD     [r9, 256]
95        PLD     [r9, 320]
96        PLD     [r9, 384]
97        PLD     [r9, 448]
981:
99        # Load next 4 A pointers
100        LDR     r3, [r2,  0]
101        LDR     r12, [r2,  4]
102        LDR     r10, [r2,  8]
103        LDR     r0, [r2, 12]
104        ADD     r2, r2, 16
105
106        # Add a_offset
107        LDR     r5, [sp, 132]           // a_offset
108        LDR     r7, [sp, 136]           // zero
109        CMP     r3,  r7                 // if a0 == zero
110        ADD     r3,  r3, r5             // a0 += a_offset
111        MOVEQ   r3,  r7                 //   a0 = zero, else += a0 + a_offset
112        CMP     r12,  r7                // if a1 == zero
113        ADD     r12, r12, r5            // a1 += a_offset
114        MOVEQ   r12,  r7                //   a1 = zero, else += a1 + a_offset
115        CMP     r10,  r7                // if a2 == zero
116        ADD     r10, r10, r5            // a2 += a_offset
117        MOVEQ   r10,  r7                //   a2 = zero, else += a2 + a_offset
118        CMP     r0,  r7                 // if a3 == zero
119        ADD     r0,  r0, r5             // a3 += a_offset
120        LDR     r5, [sp, 68]            // kc
121        MOVEQ   r0,  r7                 //   a3 = zero, else += a3 + a_offset
122
123        PLD     [r3,  0]                // Prefetch A
124        PLD     [r3, 64]
125        PLD     [r12,  0]
126        PLD     [r12, 64]
127        PLD     [r10,  0]
128        PLD     [r10, 64]
129        PLD     [r0,  0]
130        PLD     [r0, 64]
131
132        SUBS    r5, r5, 8               // kc - 8
133        BLO     4f                      // less than 2 channels?
134
135        # Main loop - 2 floats of A (8 bytes)
1362:
137        VLD1.32 {d0}, [r3]!             // A0
138        VLDM    r9!, {d8-d11}           // B0
139        VLD1.32 {d1}, [r12]!            // A1
140        VLD1.32 {d2}, [r10]!            // A2
141        VLD1.32 {d3}, [ r0]!            // A3
142        VLDM    r9!, {d12-d15}          // B1
143
144        VMLA.F32 q8, q4, d0[0]
145        VMLA.F32 q9, q5, d0[0]
146        VMLA.F32 q10, q4, d1[0]
147        VMLA.F32 q11, q5, d1[0]
148        VMLA.F32 q12, q4, d2[0]
149        VMLA.F32 q13, q5, d2[0]
150        VMLA.F32 q14, q4, d3[0]
151        VMLA.F32 q15, q5, d3[0]
152        VMLA.F32 q8, q6, d0[1]
153        VMLA.F32 q9, q7, d0[1]
154        VMLA.F32 q10, q6, d1[1]
155        VMLA.F32 q11, q7, d1[1]
156        SUBS    r5, r5, 8
157        VMLA.F32 q12, q6, d2[1]
158        VMLA.F32 q13, q7, d2[1]
159        VMLA.F32 q14, q6, d3[1]
160        VMLA.F32 q15, q7, d3[1]
161        PLD     [r9, 448]               // Prefetch B
162        PLD     [r3, 128]               // Prefetch A0
163        PLD     [r12, 128]              // Prefetch A1
164        PLD     [r10, 128]              // Prefetch A2
165        PLD     [r0, 128]               // Prefetch A3
166        BHS     2b
167
168        # Is there a remainder?- 1 float of A (4 bytes)
169        TST     r5, 4
170        BNE     4f
171
1723:
173        # ks loop
174        SUBS    r14, r14, 16            // ks -= MR * sizeof(void*)
175        BHI     1b
176
177        LDR     r7, [sp, 128]           // cn_stride
178        LDR     r14, [sp, 72]           // p = ks
179
180        # Clamp
181        VMAX.F32 q8,  q8, q2
182        SUBS    r1, r1, 8
183        VMAX.F32 q9,  q9, q2
184        VMAX.F32 q10, q10, q2
185        VMAX.F32 q11, q11, q2
186        VMAX.F32 q12, q12, q2
187        VMAX.F32 q13, q13, q2
188        VMAX.F32 q14, q14, q2
189        VMAX.F32 q15, q15, q2
190        VMIN.F32 q8,  q8, q3
191        VMIN.F32 q9,  q9, q3
192        VMIN.F32 q10, q10, q3
193        VMIN.F32 q11, q11, q3
194        VMIN.F32 q12, q12, q3
195        VMIN.F32 q13, q13, q3
196        VMIN.F32 q14, q14, q3
197        VMIN.F32 q15, q15, q3
198
199        # Store full 4 x 8
200        BLO     5f
201        VST1.32 {d28-d31},  [r6], r7
202        VST1.32 {d24-d27},  [r8], r7
203        VST1.32 {d20-d23},  [r4], r7
204        VST1.32 {d16-d19}, [r11], r7
205        SUB     r2, r2, r14             // a -= ks
206        BHI     0b
207
208        VPOP    {d8-d15}
209        ADD     sp, sp, 12              // skip pad, r2, r3
210        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
211
2124:
213        # Remainder- 1 float of A (4 bytes)
214        VLDM    r3!, {s0}               // A0
215        VLDM    r9!, {d8-d11}           // B0
216        VLDM    r12!, {s2}              // A1
217        VLDM    r10!, {s4}              // A2
218        VLDM    r0!, {s6}               // A3
219        VMLA.F32 q8, q4, d0[0]
220        VMLA.F32 q9, q5, d0[0]
221        VMLA.F32 q10, q4, d1[0]
222        VMLA.F32 q11, q5, d1[0]
223        VMLA.F32 q12, q4, d2[0]
224        VMLA.F32 q13, q5, d2[0]
225        VMLA.F32 q14, q4, d3[0]
226        VMLA.F32 q15, q5, d3[0]
227        B       3b
228
229        # Store odd width
2305:
231        TST     r1, 4
232        BEQ     6f
233        VST1.32 {d28-d29},  [r6]!
234        VST1.32 {d24-d25},  [r8]!
235        VMOV    q14, q15
236        VMOV    q12, q13
237        VST1.32 {d20-d21},  [r4]!
238        VST1.32 {d16-d17}, [r11]!
239        VMOV    q10, q11
240        VMOV    q8,  q9
241
2426:
243        TST     r1, 2
244        BEQ     7f
245        VST1.32 {d28},  [r6]!
246        VST1.32 {d24},  [r8]!
247        VMOV    d28, d29
248        VMOV    d24, d25
249        VST1.32 {d20},  [r4]!
250        VST1.32 {d16}, [r11]!
251        VMOV    d20, d21
252        VMOV    d16, d17
253
2547:
255        TST     r1, 1
256        BEQ     8f
257        VST1.32 {d28[0]},  [r6]!
258        VST1.32 {d24[0]},  [r8]!
259        VST1.32 {d20[0]},  [r4]!
260        VST1.32 {d16[0]}, [r11]!
261
2628:
263        VPOP    {d8-d15}
264        ADD     sp, sp, 12              // skip pad, r2, r3
265        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
266
267END_FUNCTION xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_cortex_a7
268
269#ifdef __ELF__
270.section ".note.GNU-stack","",%progbits
271#endif
272