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_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neonv8_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_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 4 bytes 46// struct { 47// int16_t output_zero_point; d13[2] 48// int8_t output_min; d13[6] 49// int8_t output_max; d13[7] 50// } xnn_qs8_minmax_params.neonv8; 51 52BEGIN_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neonv8_mlal_lane_cortex_a53 53 # Push 96 bytes 54 PUSH {r2, r4, r5, r6, r7, r8, r9, r10, r11, lr} // 40 55 SUB sp, sp, 8 // +8 56 VPUSH {d8-d13} // +48 = 96 57 58 LDR r7, [sp, 96] // a_stride 59 LDR r11, [sp, 104] // c 60 LDR r6, [sp, 108] // cm_stride 61 LDR r9, [sp, 100] // w 62 LDR r5, [sp, 116] // params 63 64 # Clamp A and C pointers 65 CMP r0, 2 // if mr >= 2 66 ADD r12, r3, r7 // a1 = a0 + a_stride 67 ADD r4, r11, r6 // c1 = c0 + cm_stride 68 MOVLO r12, r3 // a1 69 MOVLO r4, r11 // c1 70 // if mr > 2 71 ADD r10, r12, r7 // a2 = a1 + a_stride 72 ADD r8, r4, r6 // c2 = c1 + cm_stride 73 MOVLS r10, r12 // a2 74 MOVLS r8, r4 // c2 75 76 CMP r0, 4 // if mr >=4 77 ADD r0, r10, r7 // a3 = a2 + a_stride 78 ADD r6, r8, r6 // c3 = c2 + cm_stride 79 MOVLO r0, r10 // a3 80 MOVLO r6, r8 // c3 81 82 # Load params values 83 VLD1.32 {d13[]}, [r5] // QC8 neonv8 params 84 LDR r7, [sp, 112] // cn_stride 85 86 87 .p2align 3 880: 89 # Load initial bias from w into accumulators 90 VLDM r9!, {d16-d19} // Bias 91 SUBS r5, r2, 8 // k = kc - 8 92 93 VMOV q10, q8 94 VMOV q11, q9 95 VMOV q12, q8 96 VMOV q13, q9 97 VMOV q14, q8 98 VMOV q15, q9 99 BLO 4f // less than 8 channels? 100 101 // Prologue - load 4A's and B0 102 VLD1.8 {d0}, [r3]! // A0 103 VLD1.8 {d2}, [r12]! // A1 104 VLD1.8 {d4}, [r10]! // A2 105 VLD1.8 {d6}, [r0]! // A3 106 VLD1.8 {d8}, [r9]! // B0 107 108 SUBS r5, r5, 8 // k = k - 8 109 BLO 2f // less than 8 channels? 110 111 // Main loop - 8 bytes 112 // 64 bytes for weights. 113 // 5 VMOVL = 4 A and 1 B = 5 cycles 114 // 7 blocks with VLD B, VMOVL, 8 VMLA = 10 cycles 115 // 1 blocks with VLD B, VMLA = 9 cycles 116 // total = 84 cycles 117 .p2align 3 1181: 119 // Extend - 5 cycles 120 VMOVL.S8 q0, d0 121 VMOVL.S8 q4, d8 122 VMOVL.S8 q1, d2 123 VMOVL.S8 q2, d4 124 VMOVL.S8 q3, d6 125 126 // BLOCK 0 - 10 cycles 127 VLD1.8 {d10}, [r9]! // B1 128 VMLAL.S16 q8, d8, d0[0] 129 VMLAL.S16 q9, d9, d0[0] 130 VMLAL.S16 q10, d8, d2[0] 131 VMLAL.S16 q11, d9, d2[0] 132 VMOVL.S8 q5, d10 133 VMLAL.S16 q12, d8, d4[0] 134 VMLAL.S16 q13, d9, d4[0] 135 VMLAL.S16 q14, d8, d6[0] 136 VMLAL.S16 q15, d9, d6[0] 137 138 // BLOCK 1 - 10 cycles 139 VLD1.8 {d8}, [r9]! // B2 140 VMLAL.S16 q8, d10, d0[1] 141 VMLAL.S16 q9, d11, d0[1] 142 VMLAL.S16 q10, d10, d2[1] 143 VMLAL.S16 q11, d11, d2[1] 144 VMOVL.S8 q4, d8 145 VMLAL.S16 q12, d10, d4[1] 146 VMLAL.S16 q13, d11, d4[1] 147 VMLAL.S16 q14, d10, d6[1] 148 VMLAL.S16 q15, d11, d6[1] 149 150 // BLOCK 2 - 10 cycles 151 VLD1.8 {d10}, [r9]! // B3 152 VMLAL.S16 q8, d8, d0[2] 153 VMLAL.S16 q9, d9, d0[2] 154 VMLAL.S16 q10, d8, d2[2] 155 VMLAL.S16 q11, d9, d2[2] 156 VMOVL.S8 q5, d10 157 VMLAL.S16 q12, d8, d4[2] 158 VMLAL.S16 q13, d9, d4[2] 159 VMLAL.S16 q14, d8, d6[2] 160 VMLAL.S16 q15, d9, d6[2] 161 162 // BLOCK 3 - 10 cycles 163 VLD1.8 {d8}, [r9]! // B4 164 VMLAL.S16 q8, d10, d0[3] 165 VMLAL.S16 q9, d11, d0[3] 166 VMLAL.S16 q10, d10, d2[3] 167 VMLAL.S16 q11, d11, d2[3] 168 VMOVL.S8 q4, d8 169 VMLAL.S16 q12, d10, d4[3] 170 LDR r2, [r3] // A0 low 171 VMLAL.S16 q13, d11, d4[3] 172 LDR r14, [r3, 4] // A0 high 173 VMLAL.S16 q14, d10, d6[3] 174 ADD r3, r3, 8 175 VMLAL.S16 q15, d11, d6[3] 176 177 // BLOCK 4 - 10 cycles 178 VLD1.8 {d10}, [r9]! // B5 179 VMOV d0, r2, r14 // A0 VMOV 180 VMLAL.S16 q8, d8, d1[0] 181 VMLAL.S16 q9, d9, d1[0] 182 VMLAL.S16 q10, d8, d3[0] 183 VMLAL.S16 q11, d9, d3[0] 184 VMOVL.S8 q5, d10 185 VMLAL.S16 q12, d8, d5[0] 186 LDR r2, [r12] // A1 low 187 VMLAL.S16 q13, d9, d5[0] 188 LDR r14, [r12, 4] // A1 high 189 VMLAL.S16 q14, d8, d7[0] 190 ADD r12, r12, 8 191 VMLAL.S16 q15, d9, d7[0] 192 193 // BLOCK 5 - 10 cycles 194 VLD1.8 {d8}, [r9]! // B6 195 VMOV d2, r2, r14 // A1 VMOV 196 VMLAL.S16 q8, d10, d1[1] 197 VMLAL.S16 q9, d11, d1[1] 198 VMLAL.S16 q10, d10, d3[1] 199 VMLAL.S16 q11, d11, d3[1] 200 VMOVL.S8 q4, d8 201 VMLAL.S16 q12, d10, d5[1] 202 LDR r2, [r10] // A2 low 203 VMLAL.S16 q13, d11, d5[1] 204 LDR r14, [r10, 4] // A2 high 205 VMLAL.S16 q14, d10, d7[1] 206 ADD r10, r10, 8 207 VMLAL.S16 q15, d11, d7[1] 208 209 // BLOCK 6 - 10 cycles 210 VLD1.8 {d10}, [r9]! // B7 211 VMOV d4, r2, r14 // A2 VMOV 212 VMLAL.S16 q8, d8, d1[2] 213 VMLAL.S16 q9, d9, d1[2] 214 VMLAL.S16 q10, d8, d3[2] 215 VMLAL.S16 q11, d9, d3[2] 216 VMOVL.S8 q5, d10 217 VMLAL.S16 q12, d8, d5[2] 218 LDR r2, [r0] // A3 low 219 VMLAL.S16 q13, d9, d5[2] 220 LDR r14, [r0, 4] // A3 high 221 VMLAL.S16 q14, d8, d7[2] 222 ADD r0, r0, 8 223 VMLAL.S16 q15, d9, d7[2] 224 225 // BLOCK 7 - 9 cycles 226 VLD1.8 {d8}, [r9]! // B0 227 VMOV d6, r2, r14 // A3 VMOV 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 LDR r2, [sp, 56] // kc 399 SUBS r1, r1, 8 400 401 VMIN.S8 q0, q0, q13 402 VMIN.S8 q1, q1, q13 403 404 # Store full 4 x 8 405 BLO 5f 406 VST1.8 {d0}, [r11], r7 407 SUB r3, r3, r2 408 VST1.8 {d1}, [r4], r7 409 SUB r12, r12, r2 410 VST1.8 {d2}, [r8], r7 411 SUB r10, r10, r2 412 VST1.8 {d3}, [r6], r7 413 SUB r0, r0, r2 414 BHI 0b 415 416 VPOP {d8-d13} 417 ADD sp, sp, 12 // skip pad of 8 + r2 418 POP {r4, r5, r6, r7, r8, r9, r10, r11, pc} 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, 12 // skip pad of 8 + r2 553 POP {r4, r5, r6, r7, r8, r9, r10, r11, pc} 554 555 556END_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neonv8_mlal_lane_cortex_a53 557 558#ifdef __ELF__ 559.section ".note.GNU-stack","",%progbits 560#endif 561 562