1// Auto-generated file. Do not edit! 2// Template: src/f32-igemm/4x8-aarch32-neon-cortex-a75.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_pld_cortex_a75( 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_pld_cortex_a75 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 MOV r14, r3 // p = ks 62 63 // Clamp C pointers 64 CMP r0, 2 // if mr >= 2 65 ADD r4, r11, r6 // c1 = c0 + cm_stride 66 MOVLO r4, r11 // c1 67 // if mr > 2 68 ADD r8, r4, r6 // c2 = c1 + cm_stride 69 MOVLS r8, r4 // c2 70 CMP r0, 4 // if mr >=4 71 ADD r6, r8, r6 // c3 = c2 + cm_stride 72 MOVLO r6, r8 // c3 73 74 .p2align 3 750: 76 # Load initial bias from w into accumulators 77 VLDM r9!, {d16-d19} // Bias 78 VMOV q10, q8 79 VMOV q11, q9 80 VMOV q12, q8 81 VMOV q13, q9 82 VMOV q14, q8 83 VMOV q15, q9 84 85 PLD [r9, 0] // Prefetch B 86 PLD [r9, 64] 87 PLD [r9, 128] 88 PLD [r9, 192] 89 PLD [r9, 256] 90 PLD [r9, 320] 91 PLD [r9, 384] 92 931: 94 # Load next 4 A pointers 95 LDR r3, [r2, 0] 96 LDR r12, [r2, 4] 97 LDR r10, [r2, 8] 98 LDR r0, [r2, 12] 99 ADD r2, r2, 16 100 101 // Add a_offset 102 LDR r5, [sp, 132] // a_offset 103 LDR r7, [sp, 136] // zero 104 CMP r3, r7 // if a0 == zero 105 ADD r3, r3, r5 // a0 += a_offset 106 MOVEQ r3, r7 // a0 = zero, else += a0 + a_offset 107 CMP r12, r7 // if a1 == zero 108 ADD r12, r12, r5 // a1 += a_offset 109 MOVEQ r12, r7 // a1 = zero, else += a1 + a_offset 110 CMP r10, r7 // if a2 == zero 111 ADD r10, r10, r5 // a2 += a_offset 112 MOVEQ r10, r7 // a2 = zero, else += a2 + a_offset 113 CMP r0, r7 // if a3 == zero 114 ADD r0, r0, r5 // a3 += a_offset 115 LDR r5, [sp, 68] // kc 116 MOVEQ r0, r7 // a3 = zero, else += a3 + a_offset 117 118 PLD [r3, 0] // Prefetch A 119 PLD [r3, 64] 120 PLD [r12, 0] 121 PLD [r12, 64] 122 PLD [r10, 0] 123 PLD [r10, 64] 124 PLD [r0, 0] 125 PLD [r0, 64] 126 127 SUBS r5, r5, 16 // kc - 16 128 BLO 5f // less than 4 channels? 129 130 // Prologue 131 VLD1.32 {d0}, [r3]! // A0 132 VLDM r9!, {d8-d11} // B0 133 VLD1.32 {d1}, [r12]! // A1 134 VLD1.32 {d2}, [r10]! // A2 135 VLD1.32 {d3}, [ r0]! // A3 136 137 SUBS r5, r5, 16 138 BLO 3f // less than 4 channels? skip main loop 139 140 .p2align 3 141 142 // Main loop - 4 floats of A (16 bytes) 1432: 144 VMLA.F32 q8, q4, d0[0] 145 VLDM r9!, {d12-d15} // B1 146 VMLA.F32 q10, q4, d1[0] 147 VMLA.F32 q12, q4, d2[0] 148 VLD1.32 {d4}, [r3]! // A0 149 VMLA.F32 q14, q4, d3[0] 150 VMLA.F32 q9, q5, d0[0] 151 VLD1.32 {d5}, [r12]! // A1 152 VMLA.F32 q11, q5, d1[0] 153 VMLA.F32 q13, q5, d2[0] 154 VMLA.F32 q15, q5, d3[0] 155 VLD1.32 {d6}, [r10]! // A2 156 VMLA.F32 q8, q6, d0[1] 157 VMLA.F32 q10, q6, d1[1] 158 VLD1.32 {d7}, [ r0]! // A3 159 VMLA.F32 q12, q6, d2[1] 160 VMLA.F32 q14, q6, d3[1] 161 VLDM r9!, {d8-d11} // B0 162 VMLA.F32 q9, q7, d0[1] 163 VMLA.F32 q11, q7, d1[1] 164 VMLA.F32 q13, q7, d2[1] 165 VMLA.F32 q15, q7, d3[1] 166 167 VMLA.F32 q8, q4, d4[0] 168 VLDM r9!, {d12-d15} // B1 169 VMLA.F32 q10, q4, d5[0] 170 PLD [r3, 128] // Prefetch A0 171 VMLA.F32 q12, q4, d6[0] 172 VLD1.32 {d0}, [r3]! // A0 173 VMLA.F32 q14, q4, d7[0] 174 PLD [r12, 128] // Prefetch A1 175 VMLA.F32 q9, q5, d4[0] 176 VLD1.32 {d1}, [r12]! // A1 177 VMLA.F32 q11, q5, d5[0] 178 PLD [r10, 128] // Prefetch A2 179 VMLA.F32 q13, q5, d6[0] 180 VLD1.32 {d2}, [r10]! // A2 181 VMLA.F32 q15, q5, d7[0] 182 PLD [r0, 128] // Prefetch A3 183 VMLA.F32 q8, q6, d4[1] 184 VLD1.32 {d3}, [ r0]! // A3 185 VMLA.F32 q10, q6, d5[1] 186 PLD [r9, 352] // Prefetch B 187 VMLA.F32 q12, q6, d6[1] 188 PLD [r9, 416] // Prefetch B 189 VMLA.F32 q14, q6, d7[1] 190 VLDM r9!, {d8-d11} // B0 191 VMLA.F32 q9, q7, d4[1] 192 VMLA.F32 q11, q7, d5[1] 193 SUBS r5, r5, 16 194 VMLA.F32 q13, q7, d6[1] 195 VMLA.F32 q15, q7, d7[1] 196 BHS 2b 197 198 // Epilogue 1993: 200 VMLA.F32 q8, q4, d0[0] 201 VLDM r9!, {d12-d15} // B1 202 VMLA.F32 q10, q4, d1[0] 203 VMLA.F32 q12, q4, d2[0] 204 VLD1.32 {d4}, [r3]! // A0 205 VMLA.F32 q14, q4, d3[0] 206 VMLA.F32 q9, q5, d0[0] 207 VLD1.32 {d5}, [r12]! // A1 208 VMLA.F32 q11, q5, d1[0] 209 VMLA.F32 q13, q5, d2[0] 210 VMLA.F32 q15, q5, d3[0] 211 VLD1.32 {d6}, [r10]! // A2 212 VMLA.F32 q8, q6, d0[1] 213 VMLA.F32 q10, q6, d1[1] 214 VLD1.32 {d7}, [ r0]! // A3 215 VMLA.F32 q12, q6, d2[1] 216 VMLA.F32 q14, q6, d3[1] 217 VLDM r9!, {d8-d11} // B0 218 VMLA.F32 q9, q7, d0[1] 219 VMLA.F32 q11, q7, d1[1] 220 VMLA.F32 q13, q7, d2[1] 221 VMLA.F32 q15, q7, d3[1] 222 223 VMLA.F32 q8, q4, d4[0] 224 VLDM r9!, {d12-d15} // B1 225 VMLA.F32 q10, q4, d5[0] 226 VMLA.F32 q12, q4, d6[0] 227 VMLA.F32 q14, q4, d7[0] 228 VMLA.F32 q9, q5, d4[0] 229 VMLA.F32 q11, q5, d5[0] 230 VMLA.F32 q13, q5, d6[0] 231 VMLA.F32 q15, q5, d7[0] 232 VMLA.F32 q8, q6, d4[1] 233 VMLA.F32 q10, q6, d5[1] 234 VMLA.F32 q12, q6, d6[1] 235 VMLA.F32 q14, q6, d7[1] 236 VMLA.F32 q9, q7, d4[1] 237 VMLA.F32 q11, q7, d5[1] 238 VMLA.F32 q13, q7, d6[1] 239 VMLA.F32 q15, q7, d7[1] 240 241 // Is there a remainder?- 1 to 3 floats of A (4, 8 or 12 bytes) 242 TST r5, 12 243 BNE 5f 244 245 .p2align 3 2464: 247 # ks loop 248 SUBS r14, r14, 16 // ks -= MR * sizeof(void*) 249 BHI 1b 250 251 // Load params pointer 252 LDR r5, [sp, 140] // params 253 LDR r7, [sp, 128] // cn_stride 254 LDR r14, [sp, 72] // p = ks 255 256 // Load min/max values 257 VLD1.32 {d4[],d5[]}, [r5]! 258 SUBS r1, r1, 8 259 VLD1.32 {d6[],d7[]}, [r5] 260 261 // Clamp 262 VMAX.F32 q8, q8, q2 263 VMAX.F32 q9, q9, q2 264 VMAX.F32 q10, q10, q2 265 VMAX.F32 q11, q11, q2 266 VMAX.F32 q12, q12, q2 267 VMAX.F32 q13, q13, q2 268 VMAX.F32 q14, q14, q2 269 VMAX.F32 q15, q15, q2 270 VMIN.F32 q8, q8, q3 271 VMIN.F32 q9, q9, q3 272 VMIN.F32 q10, q10, q3 273 VMIN.F32 q11, q11, q3 274 VMIN.F32 q12, q12, q3 275 VMIN.F32 q13, q13, q3 276 VMIN.F32 q14, q14, q3 277 VMIN.F32 q15, q15, q3 278 279 // Store full 4 x 8 280 BLO 7f 281 VST1.32 {d28-d31}, [r6], r7 282 VST1.32 {d24-d27}, [r8], r7 283 VST1.32 {d20-d23}, [r4], r7 284 VST1.32 {d16-d19}, [r11], r7 285 SUB r2, r2, r14 // a -= ks 286 BHI 0b 287 288 VPOP {d8-d15} 289 ADD sp, sp, 12 // skip pad, r2, r3 290 POP {r4, r5, r6, r7, r8, r9, r10, r11, pc} 291 292 .p2align 3 2935: 294 // Is there a remainder?- 2 floats of A (8 bytes) 295 TST r5, 8 296 BEQ 6f 297 298 // Remainder - 2 floats of A (8 bytes) 299 VLD1.32 {d0}, [r3]! // A0 300 VLDM r9!, {d8-d11} // B0 301 VLD1.32 {d1}, [r12]! // A1 302 VLD1.32 {d2}, [r10]! // A2 303 VLD1.32 {d3}, [ r0]! // A3 304 305 VMLA.F32 q8, q4, d0[0] 306 VMLA.F32 q9, q5, d0[0] 307 VMLA.F32 q10, q4, d1[0] 308 VMLA.F32 q11, q5, d1[0] 309 VLDM r9!, {d12-d15} // B1 310 VMLA.F32 q12, q4, d2[0] 311 VMLA.F32 q13, q5, d2[0] 312 VMLA.F32 q14, q4, d3[0] 313 VMLA.F32 q15, q5, d3[0] 314 VMLA.F32 q8, q6, d0[1] 315 VMLA.F32 q9, q7, d0[1] 316 VMLA.F32 q10, q6, d1[1] 317 VMLA.F32 q11, q7, d1[1] 318 VMLA.F32 q12, q6, d2[1] 319 VMLA.F32 q13, q7, d2[1] 320 VMLA.F32 q14, q6, d3[1] 321 VMLA.F32 q15, q7, d3[1] 322 323 // Is there a remainder?- 1 floats of A (4 bytes) 324 TST r5, 4 325 BEQ 4b 326 3276: 328 // Remainder- 1 floats of A (4 bytes) 329 VLDM r3!, {s0} // A0 330 VLDM r9!, {d8-d11} // B0 331 VLDM r12!, {s2} // A1 332 VLDM r10!, {s4} // A2 333 VLDM r0!, {s6} // A3 334 VMLA.F32 q8, q4, d0[0] 335 VMLA.F32 q9, q5, d0[0] 336 VMLA.F32 q10, q4, d1[0] 337 VMLA.F32 q11, q5, d1[0] 338 VMLA.F32 q12, q4, d2[0] 339 VMLA.F32 q13, q5, d2[0] 340 VMLA.F32 q14, q4, d3[0] 341 VMLA.F32 q15, q5, d3[0] 342 B 4b 343 344 // Store odd width 3457: 346 TST r1, 4 347 BEQ 8f 348 VST1.32 {d28-d29}, [r6]! 349 VMOV q14, q15 350 VST1.32 {d24-d25}, [r8]! 351 VMOV q12, q13 352 VST1.32 {d20-d21}, [r4]! 353 VMOV q10, q11 354 VST1.32 {d16-d17}, [r11]! 355 VMOV q8, q9 356 3578: 358 TST r1, 2 359 BEQ 9f 360 VST1.32 {d28}, [r6]! 361 VMOV d28, d29 362 VST1.32 {d24}, [r8]! 363 VMOV d24, d25 364 VST1.32 {d20}, [r4]! 365 VMOV d20, d21 366 VST1.32 {d16}, [r11]! 367 VMOV d16, d17 368 3699: 370 TST r1, 1 371 BEQ 10f 372 VST1.32 {d28[0]}, [r6]! 373 VST1.32 {d24[0]}, [r8]! 374 VST1.32 {d20[0]}, [r4]! 375 VST1.32 {d16[0]}, [r11]! 376 37710: 378 VPOP {d8-d15} 379 ADD sp, sp, 12 // skip pad, r2, r3 380 POP {r4, r5, r6, r7, r8, r9, r10, r11, pc} 381 382END_FUNCTION xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_pld_cortex_a75 383 384#ifdef __ELF__ 385.section ".note.GNU-stack","",%progbits 386#endif 387