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_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) sp + 116 -> (r7) 25 26// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved. 27 28// Register usage 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_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 92 BLO 4f // less than 4 channels? 93 94 # Prologue 95 VLD1.32 {d0}, [r3]! // A0 96 VLDM r9!, {d8-d11} // B0 97 VLD1.32 {d1}, [r12]! // A1 98 VLD1.32 {d2}, [r10]! // A2 99 VLD1.32 {d3}, [ r0]! // A3 100 101 SUBS r5, r5, 16 102 BLO 2f // less than 4 channels? skip main loop 103 104 .p2align 3 105 106 # Main loop - 4 floats of A (16 bytes) 1071: 108 VMLA.F32 q8, q4, d0[0] 109 VLDM r9!, {d12-d15} // B1 110 VMLA.F32 q10, q4, d1[0] 111 VMLA.F32 q12, q4, d2[0] 112 VLD1.32 {d4}, [r3]! // A0 113 VMLA.F32 q14, q4, d3[0] 114 VMLA.F32 q9, q5, d0[0] 115 VLD1.32 {d5}, [r12]! // A1 116 VMLA.F32 q11, q5, d1[0] 117 VMLA.F32 q13, q5, d2[0] 118 VMLA.F32 q15, q5, d3[0] 119 VLD1.32 {d6}, [r10]! // A2 120 VMLA.F32 q8, q6, d0[1] 121 VMLA.F32 q10, q6, d1[1] 122 VLD1.32 {d7}, [ r0]! // A3 123 VMLA.F32 q12, q6, d2[1] 124 VMLA.F32 q14, q6, d3[1] 125 VLDM r9!, {d8-d11} // B0 126 VMLA.F32 q9, q7, d0[1] 127 VMLA.F32 q11, q7, d1[1] 128 VMLA.F32 q13, q7, d2[1] 129 VMLA.F32 q15, q7, d3[1] 130 131 VMLA.F32 q8, q4, d4[0] 132 VLDM r9!, {d12-d15} // B1 133 VMLA.F32 q10, q4, d5[0] 134 VMLA.F32 q12, q4, d6[0] 135 VLD1.32 {d0}, [r3]! // A0 136 VMLA.F32 q14, q4, d7[0] 137 VMLA.F32 q9, q5, d4[0] 138 VLD1.32 {d1}, [r12]! // A1 139 VMLA.F32 q11, q5, d5[0] 140 VMLA.F32 q13, q5, d6[0] 141 VLD1.32 {d2}, [r10]! // A2 142 VMLA.F32 q15, q5, d7[0] 143 VMLA.F32 q8, q6, d4[1] 144 VLD1.32 {d3}, [ r0]! // A3 145 VMLA.F32 q10, q6, d5[1] 146 VMLA.F32 q12, q6, d6[1] 147 VMLA.F32 q14, q6, d7[1] 148 VLDM r9!, {d8-d11} // B0 149 VMLA.F32 q9, q7, d4[1] 150 VMLA.F32 q11, q7, d5[1] 151 SUBS r5, r5, 16 152 VMLA.F32 q13, q7, d6[1] 153 VMLA.F32 q15, q7, d7[1] 154 BHS 1b 155 156 # Epilogue 1572: 158 VMLA.F32 q8, q4, d0[0] 159 VLDM r9!, {d12-d15} // B1 160 VMLA.F32 q10, q4, d1[0] 161 VMLA.F32 q12, q4, d2[0] 162 VLD1.32 {d4}, [r3]! // A0 163 VMLA.F32 q14, q4, d3[0] 164 VMLA.F32 q9, q5, d0[0] 165 VLD1.32 {d5}, [r12]! // A1 166 VMLA.F32 q11, q5, d1[0] 167 VMLA.F32 q13, q5, d2[0] 168 VMLA.F32 q15, q5, d3[0] 169 VLD1.32 {d6}, [r10]! // A2 170 VMLA.F32 q8, q6, d0[1] 171 VMLA.F32 q10, q6, d1[1] 172 VLD1.32 {d7}, [ r0]! // A3 173 VMLA.F32 q12, q6, d2[1] 174 VMLA.F32 q14, q6, d3[1] 175 VLDM r9!, {d8-d11} // B0 176 VMLA.F32 q9, q7, d0[1] 177 VMLA.F32 q11, q7, d1[1] 178 VMLA.F32 q13, q7, d2[1] 179 VMLA.F32 q15, q7, d3[1] 180 181 VMLA.F32 q8, q4, d4[0] 182 VLDM r9!, {d12-d15} // B1 183 VMLA.F32 q10, q4, d5[0] 184 VMLA.F32 q12, q4, d6[0] 185 VMLA.F32 q14, q4, d7[0] 186 VMLA.F32 q9, q5, d4[0] 187 VMLA.F32 q11, q5, d5[0] 188 VMLA.F32 q13, q5, d6[0] 189 VMLA.F32 q15, q5, d7[0] 190 VMLA.F32 q8, q6, d4[1] 191 VMLA.F32 q10, q6, d5[1] 192 VMLA.F32 q12, q6, d6[1] 193 VMLA.F32 q14, q6, d7[1] 194 VMLA.F32 q9, q7, d4[1] 195 VMLA.F32 q11, q7, d5[1] 196 TST r5, 15 197 VMLA.F32 q13, q7, d6[1] 198 VMLA.F32 q15, q7, d7[1] 199 200 # Is there a remainder?- 1 to 3 floats of A (4, 8 or 12 bytes) 201 BNE 4f 202 203 .p2align 3 2043: 205 # Load params pointer 206 LDR r5, [sp, 116] // params 207 208 # Load min/max values 209 VLD1.32 {d4[],d5[]}, [r5]! 210 SUBS r1, r1, 8 211 VLD1.32 {d6[],d7[]}, [r5] 212 213 # Clamp 214 VMAX.F32 q8, q8, q2 215 VMAX.F32 q9, q9, q2 216 VMAX.F32 q10, q10, q2 217 VMAX.F32 q11, q11, q2 218 VMAX.F32 q12, q12, q2 219 VMAX.F32 q13, q13, q2 220 VMAX.F32 q14, q14, q2 221 VMAX.F32 q15, q15, q2 222 VMIN.F32 q8, q8, q3 223 VMIN.F32 q9, q9, q3 224 VMIN.F32 q10, q10, q3 225 VMIN.F32 q11, q11, q3 226 VMIN.F32 q12, q12, q3 227 VMIN.F32 q13, q13, q3 228 VMIN.F32 q14, q14, q3 229 VMIN.F32 q15, q15, q3 230 231 # Store full 4 x 8 232 BLO 6f 233 VST1.32 {d16-d19}, [r11], r7 234 SUB r0, r0, r2 235 VST1.32 {d20-d23}, [r4], r7 236 SUB r10, r10, r2 237 VST1.32 {d24-d27}, [r8], r7 238 SUB r12, r12, r2 239 VST1.32 {d28-d31}, [r6], r7 240 SUB r3, r3, r2 241 BHI 0b 242 243 VPOP {d8-d15} 244 POP {r4, r5, r6, r7, r8, r9, r10, r11} 245 BX lr 246 247 .p2align 3 2484: 249 # Is there a remainder?- 2 floats of A (8 bytes) 250 TST r5, 8 251 BEQ 5f 252 253 # Remainder - 2 floats of A (8 bytes) 254 VLD1.32 {d0}, [r3]! // A0 255 VLDM r9!, {d8-d11} // B0 256 VLD1.32 {d1}, [r12]! // A1 257 VLD1.32 {d2}, [r10]! // A2 258 VLD1.32 {d3}, [ r0]! // A3 259 260 VMLA.F32 q8, q4, d0[0] 261 VMLA.F32 q9, q5, d0[0] 262 VMLA.F32 q10, q4, d1[0] 263 VMLA.F32 q11, q5, d1[0] 264 VLDM r9!, {d12-d15} // B1 265 VMLA.F32 q12, q4, d2[0] 266 VMLA.F32 q13, q5, d2[0] 267 VMLA.F32 q14, q4, d3[0] 268 VMLA.F32 q15, q5, d3[0] 269 VMLA.F32 q8, q6, d0[1] 270 VMLA.F32 q9, q7, d0[1] 271 VMLA.F32 q10, q6, d1[1] 272 VMLA.F32 q11, q7, d1[1] 273 VMLA.F32 q12, q6, d2[1] 274 VMLA.F32 q13, q7, d2[1] 275 VMLA.F32 q14, q6, d3[1] 276 VMLA.F32 q15, q7, d3[1] 277 278 # Is there a remainder?- 1 float of A (4 bytes) 279 TST r5, 4 280 BEQ 3b 281 2825: 283 # Remainder- 1 float of A (4 bytes) 284 VLDM r3!, {s0} // A0 285 VLDM r9!, {d8-d11} // B0 286 VLDM r12!, {s2} // A1 287 VLDM r10!, {s4} // A2 288 VLDM r0!, {s6} // A3 289 VMLA.F32 q8, q4, d0[0] 290 VMLA.F32 q9, q5, d0[0] 291 VMLA.F32 q10, q4, d1[0] 292 VMLA.F32 q11, q5, d1[0] 293 VMLA.F32 q12, q4, d2[0] 294 VMLA.F32 q13, q5, d2[0] 295 VMLA.F32 q14, q4, d3[0] 296 VMLA.F32 q15, q5, d3[0] 297 B 3b 298 299 # Store odd width 3006: 301 TST r1, 4 302 BEQ 7f 303 VST1.32 {d16-d17}, [r11]! 304 VST1.32 {d20-d21}, [r4]! 305 VMOV q8, q9 306 VMOV q10, q11 307 VST1.32 {d24-d25}, [r8]! 308 VST1.32 {d28-d29}, [r6]! 309 VMOV q12, q13 310 VMOV q14, q15 311 3127: 313 TST r1, 2 314 BEQ 8f 315 VST1.32 {d16}, [r11]! 316 VST1.32 {d20}, [r4]! 317 VMOV d16, d17 318 VMOV d20, d21 319 VST1.32 {d24}, [r8]! 320 VST1.32 {d28}, [r6]! 321 VMOV d24, d25 322 VMOV d28, d29 323 3248: 325 TST r1, 1 326 BEQ 9f 327 VST1.32 {d16[0]}, [r11] 328 VST1.32 {d20[0]}, [r4] 329 VST1.32 {d24[0]}, [r8] 330 VST1.32 {d28[0]}, [r6] 331 3329: 333 VPOP {d8-d15} 334 POP {r4, r5, r6, r7, r8, r9, r10, r11} 335 BX lr 336 337END_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_cortex_a75 338 339#ifdef __ELF__ 340.section ".note.GNU-stack","",%progbits 341#endif 342 343