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