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