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