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