1// Auto-generated file. Do not edit! 2// Template: src/qs8-gemm/4x8-aarch32-neon-mlal-lane-cortex-a7.S.in 3// Generator: tools/xngen 4// 5// Copyright 2021 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 11#include <xnnpack/assembly.h> 12 13.syntax unified 14 15// void xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neonv8_mlal_lane_prfm_cortex_a35( 16// size_t mr, r0 17// size_t nc, r1 18// size_t kc, (r2) -> r5 19// const int8_t*restrict a, r3 20// size_t a_stride, sp + 88 -> (r7) 21// const void*restrict w, sp + 92 -> r9 22// int8_t*restrict c, sp + 96 -> r11 23// size_t cm_stride, sp + 100 -> (r6) 24// size_t cn_stride, sp + 104 -> r7 25// xnn_qs8_minmax_params params) sp + 108 -> (r5) 26 27// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved. 28 29// Based on cortex_a53 microkernel but with Neon loads 30 31// Register usage 32// A0 r3 d0-d1 q0 33// A1 r12 d2-d3 q1 34// A2 r10 d4-d5 q2 35// A3 r0 d6-d7 q3 36 37// B r9 d8-d9 q4 q5 38 39// C0 r11 d16-d17 q8 d18-d19 q9 40// C1 r4 d20-d21 q10 d22-d23 q11 41// C2 r8 d24-d25 q12 d26-d27 q13 42// C3 r6 d28-d29 q14 d30-d31 q15 43 44// Unused d15 45 46// params structure is 4 bytes 47// struct { 48// int16_t output_zero_point; d13[2] 49// int8_t output_min; d13[6] 50// int8_t output_max; d13[7] 51// } xnn_qs8_minmax_params.neonv8; 52 53BEGIN_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neonv8_mlal_lane_prfm_cortex_a35 54 # Push 88 bytes 55 PUSH {r4, r5, r6, r7, r8, r9, r10, r11} // 32 56 SUB sp, sp, 8 // +8 57 VPUSH {d8-d13} // +48 = 88 58 59 LDR r7, [sp, 88] // a_stride 60 LDR r11, [sp, 96] // c 61 LDR r6, [sp, 100] // cm_stride 62 LDR r9, [sp, 92] // w 63 LDR r5, [sp, 108] // params 64 65 # Clamp A and C pointers 66 CMP r0, 2 // if mr >= 2 67 ADD r12, r3, r7 // a1 = a0 + a_stride 68 ADD r4, r11, r6 // c1 = c0 + cm_stride 69 MOVLO r12, r3 // a1 70 MOVLO r4, r11 // c1 71 // if mr > 2 72 ADD r10, r12, r7 // a2 = a1 + a_stride 73 ADD r8, r4, r6 // c2 = c1 + cm_stride 74 MOVLS r10, r12 // a2 75 MOVLS r8, r4 // c2 76 77 CMP r0, 4 // if mr >=4 78 ADD r0, r10, r7 // a3 = a2 + a_stride 79 ADD r6, r8, r6 // c3 = c2 + cm_stride 80 MOVLO r0, r10 // a3 81 MOVLO r6, r8 // c3 82 83 # Load params values 84 VLD1.32 {d13[]}, [r5] // QC8 neonv8 params 85 LDR r7, [sp, 104] // cn_stride 86 87 PLD [r9, 64] // Prefetch B 88 PLD [r9, 128] 89 PLD [r9, 192] 90 PLD [r9, 256] 91 PLD [r9, 320] 92 PLD [r9, 384] 93 94 .p2align 3 950: 96 # Load initial bias from w into accumulators 97 VLDM r9!, {d16-d19} // Bias 98 SUBS r5, r2, 8 // k = kc - 8 99 100 VMOV q10, q8 101 PLD [r3, 64] // Prefetch A 102 VMOV q11, q9 103 PLD [r12, 64] 104 VMOV q12, q8 105 PLD [r10, 64] 106 VMOV q13, q9 107 PLD [r0, 64] 108 VMOV q14, q8 109 VMOV q15, q9 110 BLO 4f // less than 8 channels? 111 112 // Prologue - load 4A's and B0 113 VLD1.8 {d0}, [r3]! // A0 114 VLD1.8 {d2}, [r12]! // A1 115 VLD1.8 {d4}, [r10]! // A2 116 VLD1.8 {d6}, [r0]! // A3 117 VLD1.8 {d8}, [r9]! // B0 118 119 SUBS r5, r5, 8 // k = k - 8 120 BLO 2f // less than 8 channels? 121 122 // Main loop - 8 bytes 123 // 64 bytes for weights. 124 // 5 VMOVL = 4 A and 1 B = 5 cycles 125 // 7 blocks with VLD B, VMOVL, 8 VMLA = 10 cycles 126 // 1 blocks with VLD B, VMLA = 9 cycles 127 // total = 84 cycles 128 .p2align 3 1291: 130 // Extend - 5 cycles 131 VMOVL.S8 q0, d0 132 VMOVL.S8 q4, d8 133 PLD [r9, 448] 134 VMOVL.S8 q1, d2 135 VMOVL.S8 q2, d4 136 VMOVL.S8 q3, d6 137 138 // BLOCK 0 - 10 cycles 139 VLD1.8 {d10}, [r9]! // B1 140 VMLAL.S16 q8, d8, d0[0] 141 VMLAL.S16 q9, d9, d0[0] 142 VMLAL.S16 q10, d8, d2[0] 143 VMLAL.S16 q11, d9, d2[0] 144 VMOVL.S8 q5, d10 145 VMLAL.S16 q12, d8, d4[0] 146 VMLAL.S16 q13, d9, d4[0] 147 VMLAL.S16 q14, d8, d6[0] 148 VMLAL.S16 q15, d9, d6[0] 149 150 // BLOCK 1 - 10 cycles 151 VLD1.8 {d8}, [r9]! // B2 152 VMLAL.S16 q8, d10, d0[1] 153 VMLAL.S16 q9, d11, d0[1] 154 VMLAL.S16 q10, d10, d2[1] 155 VMLAL.S16 q11, d11, d2[1] 156 VMOVL.S8 q4, d8 157 VMLAL.S16 q12, d10, d4[1] 158 VMLAL.S16 q13, d11, d4[1] 159 VMLAL.S16 q14, d10, d6[1] 160 VMLAL.S16 q15, d11, d6[1] 161 162 // BLOCK 2 - 10 cycles 163 VLD1.8 {d10}, [r9]! // B3 164 VMLAL.S16 q8, d8, d0[2] 165 VMLAL.S16 q9, d9, d0[2] 166 VMLAL.S16 q10, d8, d2[2] 167 VMLAL.S16 q11, d9, d2[2] 168 VMOVL.S8 q5, d10 169 VMLAL.S16 q12, d8, d4[2] 170 VMLAL.S16 q13, d9, d4[2] 171 VMLAL.S16 q14, d8, d6[2] 172 VMLAL.S16 q15, d9, d6[2] 173 174 // BLOCK 3 - 10 cycles 175 VLD1.8 {d8}, [r9]! // B4 176 VMLAL.S16 q8, d10, d0[3] 177 VMLAL.S16 q9, d11, d0[3] 178 VMLAL.S16 q10, d10, d2[3] 179 VMLAL.S16 q11, d11, d2[3] 180 VLD1.8 {d0}, [r3]! // A0 181 VMOVL.S8 q4, d8 182 VMLAL.S16 q12, d10, d4[3] 183 VMLAL.S16 q13, d11, d4[3] 184 VMLAL.S16 q14, d10, d6[3] 185 VMLAL.S16 q15, d11, d6[3] 186 187 // BLOCK 4 - 10 cycles 188 VLD1.8 {d10}, [r9]! // B5 189 VMLAL.S16 q8, d8, d1[0] 190 VMLAL.S16 q9, d9, d1[0] 191 VMLAL.S16 q10, d8, d3[0] 192 VMLAL.S16 q11, d9, d3[0] 193 VLD1.8 {d2}, [r12]! // A1 194 VMOVL.S8 q5, d10 195 VMLAL.S16 q12, d8, d5[0] 196 VMLAL.S16 q13, d9, d5[0] 197 VMLAL.S16 q14, d8, d7[0] 198 VMLAL.S16 q15, d9, d7[0] 199 200 // BLOCK 5 - 10 cycles 201 VLD1.8 {d8}, [r9]! // B6 202 VMLAL.S16 q8, d10, d1[1] 203 VMLAL.S16 q9, d11, d1[1] 204 VMLAL.S16 q10, d10, d3[1] 205 VMLAL.S16 q11, d11, d3[1] 206 VLD1.8 {d4}, [r10]! // A2 207 VMOVL.S8 q4, d8 208 VMLAL.S16 q12, d10, d5[1] 209 VMLAL.S16 q13, d11, d5[1] 210 VMLAL.S16 q14, d10, d7[1] 211 VMLAL.S16 q15, d11, d7[1] 212 213 // BLOCK 6 - 10 cycles 214 VLD1.8 {d10}, [r9]! // B7 215 VMLAL.S16 q8, d8, d1[2] 216 VMLAL.S16 q9, d9, d1[2] 217 VMLAL.S16 q10, d8, d3[2] 218 VMLAL.S16 q11, d9, d3[2] 219 VLD1.8 {d6}, [r0]! // A3 220 VMOVL.S8 q5, d10 221 VMLAL.S16 q12, d8, d5[2] 222 VMLAL.S16 q13, d9, d5[2] 223 VMLAL.S16 q14, d8, d7[2] 224 VMLAL.S16 q15, d9, d7[2] 225 226 // BLOCK 7 - 9 cycles 227 VLD1.8 {d8}, [r9]! // B0 228 VMLAL.S16 q8, d10, d1[3] 229 VMLAL.S16 q9, d11, d1[3] 230 VMLAL.S16 q10, d10, d3[3] 231 VMLAL.S16 q11, d11, d3[3] 232 VMLAL.S16 q12, d10, d5[3] 233 VMLAL.S16 q13, d11, d5[3] 234 SUBS r5, r5, 8 235 VMLAL.S16 q14, d10, d7[3] 236 VMLAL.S16 q15, d11, d7[3] 237 BHS 1b 238 239 // Epilogue 240 241 .p2align 3 2422: 243 VMOVL.S8 q0, d0 244 VMOVL.S8 q4, d8 245 VMOVL.S8 q1, d2 246 VMOVL.S8 q2, d4 247 VMOVL.S8 q3, d6 248 249 VLD1.8 {d10}, [r9]! // B1 250 VMLAL.S16 q8, d8, d0[0] 251 VMLAL.S16 q9, d9, d0[0] 252 VMLAL.S16 q10, d8, d2[0] 253 VMLAL.S16 q11, d9, d2[0] 254 VMOVL.S8 q5, d10 255 VMLAL.S16 q12, d8, d4[0] 256 VMLAL.S16 q13, d9, d4[0] 257 VMLAL.S16 q14, d8, d6[0] 258 VMLAL.S16 q15, d9, d6[0] 259 260 VLD1.8 {d8}, [r9]! // B2 261 VMLAL.S16 q8, d10, d0[1] 262 VMLAL.S16 q9, d11, d0[1] 263 VMLAL.S16 q10, d10, d2[1] 264 VMLAL.S16 q11, d11, d2[1] 265 VMOVL.S8 q4, d8 266 VMLAL.S16 q12, d10, d4[1] 267 VMLAL.S16 q13, d11, d4[1] 268 VMLAL.S16 q14, d10, d6[1] 269 VMLAL.S16 q15, d11, d6[1] 270 271 VLD1.8 {d10}, [r9]! // B3 272 VMLAL.S16 q8, d8, d0[2] 273 VMLAL.S16 q9, d9, d0[2] 274 VMLAL.S16 q10, d8, d2[2] 275 VMLAL.S16 q11, d9, d2[2] 276 VMOVL.S8 q5, d10 277 VMLAL.S16 q12, d8, d4[2] 278 VMLAL.S16 q13, d9, d4[2] 279 VMLAL.S16 q14, d8, d6[2] 280 VMLAL.S16 q15, d9, d6[2] 281 282 VLD1.8 {d8}, [r9]! // B4 283 VMLAL.S16 q8, d10, d0[3] 284 VMLAL.S16 q9, d11, d0[3] 285 VMLAL.S16 q10, d10, d2[3] 286 VMLAL.S16 q11, d11, d2[3] 287 VMOVL.S8 q4, d8 288 VMLAL.S16 q12, d10, d4[3] 289 VMLAL.S16 q13, d11, d4[3] 290 VMLAL.S16 q14, d10, d6[3] 291 VMLAL.S16 q15, d11, d6[3] 292 293 VLD1.8 {d10}, [r9]! // B5 294 VMLAL.S16 q8, d8, d1[0] 295 VMLAL.S16 q9, d9, d1[0] 296 VMLAL.S16 q10, d8, d3[0] 297 VMLAL.S16 q11, d9, d3[0] 298 VMOVL.S8 q5, d10 299 VMLAL.S16 q12, d8, d5[0] 300 VMLAL.S16 q13, d9, d5[0] 301 VMLAL.S16 q14, d8, d7[0] 302 VMLAL.S16 q15, d9, d7[0] 303 304 VLD1.8 {d8}, [r9]! // B6 305 VMLAL.S16 q8, d10, d1[1] 306 VMLAL.S16 q9, d11, d1[1] 307 VMLAL.S16 q10, d10, d3[1] 308 VMLAL.S16 q11, d11, d3[1] 309 VMOVL.S8 q4, d8 310 VMLAL.S16 q12, d10, d5[1] 311 VMLAL.S16 q13, d11, d5[1] 312 VMLAL.S16 q14, d10, d7[1] 313 VMLAL.S16 q15, d11, d7[1] 314 315 VLD1.8 {d10}, [r9]! // B7 316 VMLAL.S16 q8, d8, d1[2] 317 VMLAL.S16 q9, d9, d1[2] 318 VMLAL.S16 q10, d8, d3[2] 319 VMLAL.S16 q11, d9, d3[2] 320 VMOVL.S8 q5, d10 321 VMLAL.S16 q12, d8, d5[2] 322 VMLAL.S16 q13, d9, d5[2] 323 VMLAL.S16 q14, d8, d7[2] 324 VMLAL.S16 q15, d9, d7[2] 325 326 VMLAL.S16 q8, d10, d1[3] 327 VMLAL.S16 q9, d11, d1[3] 328 VMLAL.S16 q10, d10, d3[3] 329 VMLAL.S16 q11, d11, d3[3] 330 VMLAL.S16 q12, d10, d5[3] 331 VMLAL.S16 q13, d11, d5[3] 332 ADDS r5, r5, 8 333 VMLAL.S16 q14, d10, d7[3] 334 VMLAL.S16 q15, d11, d7[3] 335 336 # Is there a remainder?- 1-7 bytes of A 337 BNE 4f 338 3393: 340 # QC8 FP32 quantization 341 VLD1.8 {q0-q1}, [r9]! 342 343 VCVT.F32.S32 q8, q8 344 VCVT.F32.S32 q9, q9 345 VCVT.F32.S32 q10, q10 346 VCVT.F32.S32 q11, q11 347 VCVT.F32.S32 q12, q12 348 VCVT.F32.S32 q13, q13 349 VCVT.F32.S32 q14, q14 350 VCVT.F32.S32 q15, q15 351 352 VMUL.F32 q8, q8, q0 // multiplier 353 VMUL.F32 q9, q9, q1 354 VMUL.F32 q10, q10, q0 355 VMUL.F32 q11, q11, q1 356 VMUL.F32 q12, q12, q0 357 VMUL.F32 q13, q13, q1 358 VMUL.F32 q14, q14, q0 359 VMUL.F32 q15, q15, q1 360 361 VCVTN.S32.F32 q8, q8 362 VCVTN.S32.F32 q9, q9 363 VCVTN.S32.F32 q10, q10 364 VCVTN.S32.F32 q11, q11 365 VCVTN.S32.F32 q12, q12 366 VCVTN.S32.F32 q13, q13 367 VCVTN.S32.F32 q14, q14 368 VCVTN.S32.F32 q15, q15 369 370 VDUP.16 q0, d13[2] // output_zero_point 371 372 VQMOVN.S32 d16, q8 373 VQMOVN.S32 d17, q9 374 VQMOVN.S32 d18, q10 375 VQMOVN.S32 d19, q11 376 VQMOVN.S32 d20, q12 377 VQMOVN.S32 d21, q13 378 VQMOVN.S32 d22, q14 379 VQMOVN.S32 d23, q15 380 381 VQADD.S16 q8, q8, q0 382 VQADD.S16 q9, q9, q0 383 VQADD.S16 q10, q10, q0 384 VQADD.S16 q11, q11, q0 385 386 VDUP.8 q12, d13[6] // output_min 387 388 VQMOVN.S16 d0, q8 389 VQMOVN.S16 d1, q9 390 VQMOVN.S16 d2, q10 391 VQMOVN.S16 d3, q11 392 393 VDUP.8 q13, d13[7] // output_max 394 395 VMAX.S8 q0, q0, q12 396 VMAX.S8 q1, q1, q12 397 398 SUBS r1, r1, 8 399 400 VMIN.S8 q0, q0, q13 401 VMIN.S8 q1, q1, q13 402 403 # Store full 4 x 8 404 BLO 5f 405 VST1.8 {d0}, [r11], r7 406 SUB r3, r3, r2 407 VST1.8 {d1}, [r4], r7 408 SUB r12, r12, r2 409 VST1.8 {d2}, [r8], r7 410 SUB r10, r10, r2 411 VST1.8 {d3}, [r6], r7 412 SUB r0, r0, r2 413 BHI 0b 414 415 VPOP {d8-d13} 416 ADD sp, sp, 8 // skip d14 417 POP {r4, r5, r6, r7, r8, r9, r10, r11} 418 BX lr 419 420 # Remainder- 1 to 7 bytes of A 421 .p2align 3 4224: 423 AND r5, r5, 7 // kc remainder 1 to 7 424 425 VLD1.8 {d0}, [r3], r5 426 VLD1.8 {d8}, [r9]! 427 VLD1.8 {d2}, [r12], r5 428 VLD1.8 {d4}, [r10], r5 429 VLD1.8 {d6}, [r0], r5 430 431 VMOVL.S8 q0, d0 432 VMOVL.S8 q4, d8 433 VMOVL.S8 q1, d2 434 VMOVL.S8 q2, d4 435 VMOVL.S8 q3, d6 436 VMLAL.S16 q8, d8, d0[0] 437 VMLAL.S16 q9, d9, d0[0] 438 VMLAL.S16 q10, d8, d2[0] 439 VMLAL.S16 q11, d9, d2[0] 440 VMLAL.S16 q12, d8, d4[0] 441 VMLAL.S16 q13, d9, d4[0] 442 VMLAL.S16 q14, d8, d6[0] 443 VMLAL.S16 q15, d9, d6[0] 444 CMP r5, 2 445 BLO 3b 446 447 VLD1.8 {d8}, [r9]! 448 VMOVL.S8 q4, d8 449 VMLAL.S16 q8, d8, d0[1] 450 VMLAL.S16 q9, d9, d0[1] 451 VMLAL.S16 q10, d8, d2[1] 452 VMLAL.S16 q11, d9, d2[1] 453 VMLAL.S16 q12, d8, d4[1] 454 VMLAL.S16 q13, d9, d4[1] 455 VMLAL.S16 q14, d8, d6[1] 456 VMLAL.S16 q15, d9, d6[1] 457 BEQ 3b 458 459 VLD1.8 {d8}, [r9]! 460 VMOVL.S8 q4, d8 461 VMLAL.S16 q8, d8, d0[2] 462 VMLAL.S16 q9, d9, d0[2] 463 VMLAL.S16 q10, d8, d2[2] 464 VMLAL.S16 q11, d9, d2[2] 465 VMLAL.S16 q12, d8, d4[2] 466 VMLAL.S16 q13, d9, d4[2] 467 VMLAL.S16 q14, d8, d6[2] 468 VMLAL.S16 q15, d9, d6[2] 469 CMP r5, 4 470 BLO 3b 471 472 VLD1.8 {d8}, [r9]! 473 VMOVL.S8 q4, d8 474 VMLAL.S16 q8, d8, d0[3] 475 VMLAL.S16 q9, d9, d0[3] 476 VMLAL.S16 q10, d8, d2[3] 477 VMLAL.S16 q11, d9, d2[3] 478 VMLAL.S16 q12, d8, d4[3] 479 VMLAL.S16 q13, d9, d4[3] 480 VMLAL.S16 q14, d8, d6[3] 481 VMLAL.S16 q15, d9, d6[3] 482 BEQ 3b 483 484 VLD1.8 {d8}, [r9]! 485 VMOVL.S8 q4, d8 486 VMLAL.S16 q8, d8, d1[0] 487 VMLAL.S16 q9, d9, d1[0] 488 VMLAL.S16 q10, d8, d3[0] 489 VMLAL.S16 q11, d9, d3[0] 490 VMLAL.S16 q12, d8, d5[0] 491 VMLAL.S16 q13, d9, d5[0] 492 VMLAL.S16 q14, d8, d7[0] 493 VMLAL.S16 q15, d9, d7[0] 494 CMP r5, 6 495 BLO 3b 496 497 VLD1.8 {d8}, [r9]! 498 VMOVL.S8 q4, d8 499 VMLAL.S16 q8, d8, d1[1] 500 VMLAL.S16 q9, d9, d1[1] 501 VMLAL.S16 q10, d8, d3[1] 502 VMLAL.S16 q11, d9, d3[1] 503 VMLAL.S16 q12, d8, d5[1] 504 VMLAL.S16 q13, d9, d5[1] 505 VMLAL.S16 q14, d8, d7[1] 506 VMLAL.S16 q15, d9, d7[1] 507 BEQ 3b 508 509 VLD1.8 {d8}, [r9]! 510 VMOVL.S8 q4, d8 511 VMLAL.S16 q8, d8, d1[2] 512 VMLAL.S16 q9, d9, d1[2] 513 VMLAL.S16 q10, d8, d3[2] 514 VMLAL.S16 q11, d9, d3[2] 515 VMLAL.S16 q12, d8, d5[2] 516 VMLAL.S16 q13, d9, d5[2] 517 VMLAL.S16 q14, d8, d7[2] 518 VMLAL.S16 q15, d9, d7[2] 519 B 3b 520 521 # Store odd width 522 .p2align 3 5235: 524 TST r1, 4 525 BEQ 6f 526 VST1.32 {d0[0]}, [r11]! 527 VST1.32 {d1[0]}, [r4]! 528 VST1.32 {d2[0]}, [r8]! 529 VST1.32 {d3[0]}, [r6]! 530 VEXT.8 q0, q0, q0, 4 531 VEXT.8 q1, q1, q1, 4 5326: 533 TST r1, 2 534 BEQ 7f 535 VST1.16 {d0[0]}, [r11]! 536 VST1.16 {d1[0]}, [r4]! 537 VST1.16 {d2[0]}, [r8]! 538 VST1.16 {d3[0]}, [r6]! 539 VEXT.8 q0, q0, q0, 2 540 VEXT.8 q1, q1, q1, 2 541 5427: 543 TST r1, 1 544 BEQ 8f 545 VST1.8 {d0[0]}, [r11] 546 VST1.8 {d1[0]}, [r4] 547 VST1.8 {d2[0]}, [r8] 548 VST1.8 {d3[0]}, [r6] 549 5508: 551 VPOP {d8-d13} 552 ADD sp, sp, 8 // skip d14 553 POP {r4, r5, r6, r7, r8, r9, r10, r11} 554 BX lr 555 556END_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neonv8_mlal_lane_prfm_cortex_a35 557 558#ifdef __ELF__ 559.section ".note.GNU-stack","",%progbits 560#endif 561 562