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_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_output_params params[restrict static 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_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 r9, [sp, 100] // w 56 LDR r11, [sp, 104] // c 57 LDR r6, [sp, 108] // cm_stride 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 801: 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 106 BLO 4f // less than 4 channels? 107 108 // Prologue 109 VLD1.32 {d0}, [r3]! // A0 110 VLDM r9!, {d8-d11} // B0 111 VLD1.32 {d1}, [r12]! // A1 112 VLD1.32 {d2}, [r10]! // A2 113 VLD1.32 {d3}, [ r0]! // A3 114 115 SUBS r5, r5, 16 116 BLO 3f // less than 4 channels? skip main loop 117 118 .p2align 3 119 120 // Main loop - 4 floats of A (16 bytes) 1212: 122 VMLA.F32 q8, q4, d0[0] 123 VLDM r9!, {d12-d15} // B1 124 VMLA.F32 q10, q4, d1[0] 125 VMLA.F32 q12, q4, d2[0] 126 VLD1.32 {d4}, [r3]! // A0 127 VMLA.F32 q14, q4, d3[0] 128 VMLA.F32 q9, q5, d0[0] 129 VLD1.32 {d5}, [r12]! // A1 130 VMLA.F32 q11, q5, d1[0] 131 VMLA.F32 q13, q5, d2[0] 132 VMLA.F32 q15, q5, d3[0] 133 VLD1.32 {d6}, [r10]! // A2 134 VMLA.F32 q8, q6, d0[1] 135 VMLA.F32 q10, q6, d1[1] 136 VLD1.32 {d7}, [ r0]! // A3 137 VMLA.F32 q12, q6, d2[1] 138 VMLA.F32 q14, q6, d3[1] 139 VLDM r9!, {d8-d11} // B0 140 VMLA.F32 q9, q7, d0[1] 141 VMLA.F32 q11, q7, d1[1] 142 VMLA.F32 q13, q7, d2[1] 143 VMLA.F32 q15, q7, d3[1] 144 145 VMLA.F32 q8, q4, d4[0] 146 VLDM r9!, {d12-d15} // B1 147 VMLA.F32 q10, q4, d5[0] 148 PLD [r3, 128] // Prefetch A0 149 VMLA.F32 q12, q4, d6[0] 150 VLD1.32 {d0}, [r3]! // A0 151 VMLA.F32 q14, q4, d7[0] 152 PLD [r12, 128] // Prefetch A1 153 VMLA.F32 q9, q5, d4[0] 154 VLD1.32 {d1}, [r12]! // A1 155 VMLA.F32 q11, q5, d5[0] 156 PLD [r10, 128] // Prefetch A2 157 VMLA.F32 q13, q5, d6[0] 158 VLD1.32 {d2}, [r10]! // A2 159 VMLA.F32 q15, q5, d7[0] 160 PLD [r0, 128] // Prefetch A3 161 VMLA.F32 q8, q6, d4[1] 162 VLD1.32 {d3}, [ r0]! // A3 163 VMLA.F32 q10, q6, d5[1] 164 PLD [r9, 384] // Prefetch B 165 VMLA.F32 q12, q6, d6[1] 166 PLD [r9, 448] // Prefetch B 167 VMLA.F32 q14, q6, d7[1] 168 VLDM r9!, {d8-d11} // B0 169 VMLA.F32 q9, q7, d4[1] 170 VMLA.F32 q11, q7, d5[1] 171 SUBS r5, r5, 16 172 VMLA.F32 q13, q7, d6[1] 173 VMLA.F32 q15, q7, d7[1] 174 BHS 2b 175 176 // Epilogue 1773: 178 VMLA.F32 q8, q4, d0[0] 179 VLDM r9!, {d12-d15} // B1 180 VMLA.F32 q10, q4, d1[0] 181 VMLA.F32 q12, q4, d2[0] 182 VLD1.32 {d4}, [r3]! // A0 183 VMLA.F32 q14, q4, d3[0] 184 VMLA.F32 q9, q5, d0[0] 185 VLD1.32 {d5}, [r12]! // A1 186 VMLA.F32 q11, q5, d1[0] 187 VMLA.F32 q13, q5, d2[0] 188 VMLA.F32 q15, q5, d3[0] 189 VLD1.32 {d6}, [r10]! // A2 190 VMLA.F32 q8, q6, d0[1] 191 VMLA.F32 q10, q6, d1[1] 192 VLD1.32 {d7}, [ r0]! // A3 193 VMLA.F32 q12, q6, d2[1] 194 VMLA.F32 q14, q6, d3[1] 195 VLDM r9!, {d8-d11} // B0 196 VMLA.F32 q9, q7, d0[1] 197 VMLA.F32 q11, q7, d1[1] 198 VMLA.F32 q13, q7, d2[1] 199 VMLA.F32 q15, q7, d3[1] 200 201 VMLA.F32 q8, q4, d4[0] 202 VLDM r9!, {d12-d15} // B1 203 VMLA.F32 q10, q4, d5[0] 204 VMLA.F32 q12, q4, d6[0] 205 VMLA.F32 q14, q4, d7[0] 206 VMLA.F32 q9, q5, d4[0] 207 VMLA.F32 q11, q5, d5[0] 208 VMLA.F32 q13, q5, d6[0] 209 VMLA.F32 q15, q5, d7[0] 210 VMLA.F32 q8, q6, d4[1] 211 VMLA.F32 q10, q6, d5[1] 212 VMLA.F32 q12, q6, d6[1] 213 VMLA.F32 q14, q6, d7[1] 214 VMLA.F32 q9, q7, d4[1] 215 VMLA.F32 q11, q7, d5[1] 216 VMLA.F32 q13, q7, d6[1] 217 VMLA.F32 q15, q7, d7[1] 218 2194: 220 // Is there a remainder?- 1 to 3 floats of A (4, 8 or 12 bytes) 221 TST r5, 12 222 BNE 7f 223 224 .p2align 3 2255: 226 // Load params pointer 227 LDR r5, [sp, 116] // clamping_params 228 229 // Load clamping_params values 230 VLD1.32 {d4[],d5[]}, [r5]! 231 SUBS r1, r1, 8 232 VLD1.32 {d6[],d7[]}, [r5] 233 234 // Clamp 235 VMIN.F32 q8, q8, q2 236 VMIN.F32 q9, q9, q2 237 VMIN.F32 q10, q10, q2 238 VMIN.F32 q11, q11, q2 239 VMIN.F32 q12, q12, q2 240 VMIN.F32 q13, q13, q2 241 VMIN.F32 q14, q14, q2 242 VMIN.F32 q15, q15, q2 243 VMAX.F32 q8, q8, q3 244 VMAX.F32 q9, q9, q3 245 VMAX.F32 q10, q10, q3 246 VMAX.F32 q11, q11, q3 247 VMAX.F32 q12, q12, q3 248 VMAX.F32 q13, q13, q3 249 VMAX.F32 q14, q14, q3 250 VMAX.F32 q15, q15, q3 251 252 // Store full 4 x 8 253 BLO 10f 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 1b 263 2646: 265 VPOP {d8-d15} 266 POP {r4, r5, r6, r7, r8, r9, r10, r11} 267 BX lr 268 269 .p2align 3 2707: 271 // Is there a remainder?- 2 floats of A (8 bytes) 272 TST r5, 8 273 BEQ 8f 274 275 // Remainder - 2 floats of A (8 bytes) 276 VLD1.32 {d0}, [r3]! // A0 277 VLDM r9!, {d8-d11} // B0 278 VLD1.32 {d1}, [r12]! // A1 279 VLD1.32 {d2}, [r10]! // A2 280 VLD1.32 {d3}, [ r0]! // A3 281 282 VMLA.F32 q8, q4, d0[0] 283 VMLA.F32 q9, q5, d0[0] 284 VMLA.F32 q10, q4, d1[0] 285 VMLA.F32 q11, q5, d1[0] 286 VLDM r9!, {d12-d15} // B1 287 VMLA.F32 q12, q4, d2[0] 288 VMLA.F32 q13, q5, d2[0] 289 VMLA.F32 q14, q4, d3[0] 290 VMLA.F32 q15, q5, d3[0] 291 VMLA.F32 q8, q6, d0[1] 292 VMLA.F32 q9, q7, d0[1] 293 VMLA.F32 q10, q6, d1[1] 294 VMLA.F32 q11, q7, d1[1] 295 VMLA.F32 q12, q6, d2[1] 296 VMLA.F32 q13, q7, d2[1] 297 VMLA.F32 q14, q6, d3[1] 298 VMLA.F32 q15, q7, d3[1] 2998: 300 // Is there a remainder?- 1 floats of A (4 bytes) 301 TST r5, 4 302 BEQ 5b 303 3049: 305 // Remainder- 1 floats of A (4 bytes) 306 VLDM r3!, {s0} // A0 307 VLDM r9!, {d8-d11} // B0 308 VLDM r12!, {s2} // A1 309 VLDM r10!, {s4} // A2 310 VLDM r0!, {s6} // A3 311 VMLA.F32 q8, q4, d0[0] 312 VMLA.F32 q9, q5, d0[0] 313 VMLA.F32 q10, q4, d1[0] 314 VMLA.F32 q11, q5, d1[0] 315 VMLA.F32 q12, q4, d2[0] 316 VMLA.F32 q13, q5, d2[0] 317 VMLA.F32 q14, q4, d3[0] 318 VMLA.F32 q15, q5, d3[0] 319 B 5b 320 321// Store odd width 32210: 323 TST r1, 4 324 BEQ 11f 325 VST1.32 {d16-d17}, [r11]! 326 VMOV q8, q9 327 VST1.32 {d20-d21}, [r4]! 328 VMOV q10, q11 329 VST1.32 {d24-d25}, [r8]! 330 VMOV q12, q13 331 VST1.32 {d28-d29}, [r6]! 332 VMOV q14, q15 333 33411: 335 TST r1, 2 336 BEQ 12f 337 VST1.32 {d16}, [r11]! 338 VMOV d16, d17 339 VST1.32 {d20}, [r4]! 340 VMOV d20, d21 341 VST1.32 {d24}, [r8]! 342 VMOV d24, d25 343 VST1.32 {d28}, [r6]! 344 VMOV d28, d29 345 34612: 347 TST r1, 1 348 BEQ 13f 349 VST1.32 {d16[0]}, [r11] 350 VST1.32 {d20[0]}, [r4] 351 VST1.32 {d24[0]}, [r8] 352 VST1.32 {d28[0]}, [r6] 353 35413: 355 VPOP {d8-d15} 356 POP {r4, r5, r6, r7, r8, r9, r10, r11} 357 BX lr 358 359END_FUNCTION xnn_f32_gemm_ukernel_4x8__aarch32_neon_pld_cortex_a75 360 361#ifdef __ELF__ 362.section ".note.GNU-stack","",%progbits 363#endif 364 365 366 367