1// Auto-generated file. Do not edit! 2// Template: src/qs8-igemm/4x8-aarch32-neon-mlal-lane-ld64.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_igemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_prfm_ld64 16// size_t mr, (r0) 17// size_t nc, r1 18// size_t kc, (r2) -> r5 -> sp + 44 19// size_t ks, (r3) -> sp + 48 -> r14 20// const int8_t**restrict a, sp + 88 -> r2 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// size_t a_offset, sp + 108 -> (r5) 26// const int8_t* zero, sp + 112 -> (r7) 27// xnn_qs8_minmax_params*params); sp + 116 -> (r5) 28 29// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved. 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 d10-d11 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 d13-d15 45 46// params structure is 10 bytes 47// struct { 48// float magic_bias; d12[0] 49// int32_t magic_bias_less_output_zero_point; d12[1] 50// int8_t output_min; d13[6] 51// int8_t output_max; d13[7] 52// } xnn_qs8_minmax_params.neon; 53 54BEGIN_FUNCTION xnn_qc8_igemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_prfm_ld64 55 # Push 88 bytes 56 # r2 will be reloaded in outer loop. r3 is ks 57 PUSH {r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr} // +44 58 SUB sp, sp, 12 // +12 59 VPUSH {d10-d13} // +32 = 88 60 61 LDR r11, [sp, 96] // c 62 LDR r6, [sp, 100] // cm_stride 63 LDR r2, [sp, 88] // a 64 LDR r9, [sp, 92] // w 65 LDR r5, [sp, 116] // params 66 MOV r14, r3 // p = ks 67 68 # Clamp C pointers 69 CMP r0, 2 // if mr >= 2 70 ADD r4, r11, r6 // c1 = c0 + cm_stride 71 MOVLO r4, r11 // c1 72 // if mr > 2 73 ADD r8, r4, r6 // c2 = c1 + cm_stride 74 MOVLS r8, r4 // c2 75 CMP r0, 4 // if mr >=4 76 ADD r6, r8, r6 // c3 = c2 + cm_stride 77 MOVLO r6, r8 // c3 78 79 # Load params values 80 VLDM r5!, {d12} // QC8 neon params 81 VLD1.16 {d13[]}, [r5] 82 83 PLD [r9, 64] // Prefetch B 84 PLD [r9, 128] 85 PLD [r9, 192] 86 PLD [r9, 256] 87 PLD [r9, 320] 88 PLD [r9, 384] 89 90 .p2align 3 910: 92 # Load initial bias from w into accumulators 93 VLDM r9!, {d16-d19} // Bias 94 VMOV q10, q8 95 VMOV q11, q9 96 VMOV q12, q8 97 VMOV q13, q9 98 VMOV q14, q8 99 VMOV q15, q9 100 101 .p2align 3 1021: 103 # Load next 4 A pointers 104 LDR r3, [r2, 0] 105 LDR r12, [r2, 4] 106 LDR r10, [r2, 8] 107 LDR r0, [r2, 12] 108 ADD r2, r2, 16 109 110 PLD [r3, 64] 111 PLD [r12, 64] 112 PLD [r10, 64] 113 PLD [r0, 64] 114 115 # Add a_offset 116 LDR r5, [sp, 108] // a_offset 117 LDR r7, [sp, 112] // zero 118 CMP r3, r7 // if a0 == zero 119 ADD r3, r3, r5 // a0 += a_offset 120 MOVEQ r3, r7 // a0 = zero, else += a0 + a_offset 121 CMP r12, r7 // if a1 == zero 122 ADD r12, r12, r5 // a1 += a_offset 123 MOVEQ r12, r7 // a1 = zero, else += a1 + a_offset 124 CMP r10, r7 // if a2 == zero 125 ADD r10, r10, r5 // a2 += a_offset 126 MOVEQ r10, r7 // a2 = zero, else += a2 + a_offset 127 CMP r0, r7 // if a3 == zero 128 ADD r0, r0, r5 // a3 += a_offset 129 LDR r5, [sp, 44] // kc 130 MOVEQ r0, r7 // a3 = zero, else += a3 + a_offset 131 132 SUBS r5, r5, 8 // kc - 8 133 BLO 4f // less than 8 channels? 134 135 # Main loop - 8 bytes 136 # 64 bytes for weights. 137 .p2align 3 1382: 139 VLD1.8 {d0}, [r3]! // A0 140 VLD1.8 {d10}, [r9]! // B 141 VLD1.8 {d2}, [r12]! // A1 142 VLD1.8 {d4}, [r10]! // A2 143 VLD1.8 {d6}, [r0]! // A3 144 SUBS r5, r5, 8 145 PLD [r3, 128] 146 VMOVL.S8 q0, d0 147 PLD [r12, 128] 148 VMOVL.S8 q5, d10 149 PLD [r10, 128] 150 VMOVL.S8 q1, d2 151 PLD [r0, 128] 152 VMOVL.S8 q2, d4 153 PLD [r9, 448] 154 VMOVL.S8 q3, d6 155 VMLAL.S16 q8, d10, d0[0] 156 VMLAL.S16 q9, d11, d0[0] 157 VMLAL.S16 q10, d10, d2[0] 158 VMLAL.S16 q11, d11, d2[0] 159 VMLAL.S16 q12, d10, d4[0] 160 VMLAL.S16 q13, d11, d4[0] 161 VMLAL.S16 q14, d10, d6[0] 162 VMLAL.S16 q15, d11, d6[0] 163 164 VLD1.8 {d10}, [r9]! 165 VMOVL.S8 q5, d10 166 VMLAL.S16 q8, d10, d0[1] 167 VMLAL.S16 q9, d11, d0[1] 168 VMLAL.S16 q10, d10, d2[1] 169 VMLAL.S16 q11, d11, d2[1] 170 VMLAL.S16 q12, d10, d4[1] 171 VMLAL.S16 q13, d11, d4[1] 172 VMLAL.S16 q14, d10, d6[1] 173 VMLAL.S16 q15, d11, d6[1] 174 175 VLD1.8 {d10}, [r9]! 176 VMOVL.S8 q5, d10 177 VMLAL.S16 q8, d10, d0[2] 178 VMLAL.S16 q9, d11, d0[2] 179 VMLAL.S16 q10, d10, d2[2] 180 VMLAL.S16 q11, d11, d2[2] 181 VMLAL.S16 q12, d10, d4[2] 182 VMLAL.S16 q13, d11, d4[2] 183 VMLAL.S16 q14, d10, d6[2] 184 VMLAL.S16 q15, d11, d6[2] 185 186 VLD1.8 {d10}, [r9]! 187 VMOVL.S8 q5, d10 188 VMLAL.S16 q8, d10, d0[3] 189 VMLAL.S16 q9, d11, d0[3] 190 VMLAL.S16 q10, d10, d2[3] 191 VMLAL.S16 q11, d11, d2[3] 192 VMLAL.S16 q12, d10, d4[3] 193 VMLAL.S16 q13, d11, d4[3] 194 VMLAL.S16 q14, d10, d6[3] 195 VMLAL.S16 q15, d11, d6[3] 196 197 VLD1.8 {d10}, [r9]! 198 VMOVL.S8 q5, d10 199 VMLAL.S16 q8, d10, d1[0] 200 VMLAL.S16 q9, d11, d1[0] 201 VMLAL.S16 q10, d10, d3[0] 202 VMLAL.S16 q11, d11, d3[0] 203 VMLAL.S16 q12, d10, d5[0] 204 VMLAL.S16 q13, d11, d5[0] 205 VMLAL.S16 q14, d10, d7[0] 206 VMLAL.S16 q15, d11, d7[0] 207 208 VLD1.8 {d10}, [r9]! 209 VMOVL.S8 q5, d10 210 VMLAL.S16 q8, d10, d1[1] 211 VMLAL.S16 q9, d11, d1[1] 212 VMLAL.S16 q10, d10, d3[1] 213 VMLAL.S16 q11, d11, d3[1] 214 VMLAL.S16 q12, d10, d5[1] 215 VMLAL.S16 q13, d11, d5[1] 216 VMLAL.S16 q14, d10, d7[1] 217 VMLAL.S16 q15, d11, d7[1] 218 219 VLD1.8 {d10}, [r9]! 220 VMOVL.S8 q5, d10 221 VMLAL.S16 q8, d10, d1[2] 222 VMLAL.S16 q9, d11, d1[2] 223 VMLAL.S16 q10, d10, d3[2] 224 VMLAL.S16 q11, d11, d3[2] 225 VMLAL.S16 q12, d10, d5[2] 226 VMLAL.S16 q13, d11, d5[2] 227 VMLAL.S16 q14, d10, d7[2] 228 VMLAL.S16 q15, d11, d7[2] 229 230 VLD1.8 {d10}, [r9]! 231 VMOVL.S8 q5, d10 232 VMLAL.S16 q8, d10, d1[3] 233 VMLAL.S16 q9, d11, d1[3] 234 VMLAL.S16 q10, d10, d3[3] 235 VMLAL.S16 q11, d11, d3[3] 236 VMLAL.S16 q12, d10, d5[3] 237 VMLAL.S16 q13, d11, d5[3] 238 VMLAL.S16 q14, d10, d7[3] 239 VMLAL.S16 q15, d11, d7[3] 240 BHS 2b 241 242 # Is there a remainder?- 1-7 bytes of A 243 ADDS r5, r5, 8 244 BNE 4f 245 2463: 247 # ks loop 248 SUBS r14, r14, 16 // ks -= MR * sizeof(void*) 249 BHI 1b 250 251 LDR r7, [sp, 104] // cn_stride 252 LDR r14, [sp, 48] // p = ks 253 254 # QC8 FP32 quantization 255 VLD1.8 {q0-q1}, [r9]! 256 257 VDUP.32 q2, d12[0] // magic_bias 258 VDUP.32 q3, d12[1] // magic_bias_less_output_zero_point 259 260 VCVT.F32.S32 q8, q8 261 VCVT.F32.S32 q9, q9 262 VCVT.F32.S32 q10, q10 263 VCVT.F32.S32 q11, q11 264 VCVT.F32.S32 q12, q12 265 VCVT.F32.S32 q13, q13 266 VCVT.F32.S32 q14, q14 267 VCVT.F32.S32 q15, q15 268 269 VMUL.F32 q8, q8, q0 // multiplier 270 VMUL.F32 q9, q9, q1 271 VMUL.F32 q10, q10, q0 272 VMUL.F32 q11, q11, q1 273 VMUL.F32 q12, q12, q0 274 VMUL.F32 q13, q13, q1 275 VMUL.F32 q14, q14, q0 276 VMUL.F32 q15, q15, q1 277 278 VADD.F32 q8, q8, q2 // magic_bias 279 VADD.F32 q9, q9, q2 280 VADD.F32 q10, q10, q2 281 VADD.F32 q11, q11, q2 282 VADD.F32 q12, q12, q2 283 VADD.F32 q13, q13, q2 284 VADD.F32 q14, q14, q2 285 VADD.F32 q15, q15, q2 286 287 VQSUB.S32 q8, q8, q3 // magic_bias_less_output_zero_point 288 VQSUB.S32 q9, q9, q3 289 VQSUB.S32 q10, q10, q3 290 VQSUB.S32 q11, q11, q3 291 VQSUB.S32 q12, q12, q3 292 VQSUB.S32 q13, q13, q3 293 VQSUB.S32 q14, q14, q3 294 VQSUB.S32 q15, q15, q3 295 296 297 VQMOVN.S32 d16, q8 298 VQMOVN.S32 d17, q9 299 VQMOVN.S32 d18, q10 300 VQMOVN.S32 d19, q11 301 VQMOVN.S32 d20, q12 302 VQMOVN.S32 d21, q13 303 VQMOVN.S32 d22, q14 304 VQMOVN.S32 d23, q15 305 306 307 VDUP.8 q12, d13[6] // output_min 308 309 VQMOVN.S16 d0, q8 310 VQMOVN.S16 d1, q9 311 VQMOVN.S16 d2, q10 312 VQMOVN.S16 d3, q11 313 314 VDUP.8 q13, d13[7] // output_max 315 316 VMAX.S8 q0, q0, q12 317 VMAX.S8 q1, q1, q12 318 319 SUBS r1, r1, 8 // nc -= 8 320 321 VMIN.S8 q0, q0, q13 322 VMIN.S8 q1, q1, q13 323 324 # Store full 4 x 8 325 BLO 5f 326 VST1.8 {d3}, [r6], r7 327 VST1.8 {d2}, [r8], r7 328 VST1.8 {d1}, [r4], r7 329 VST1.8 {d0}, [r11], r7 330 SUB r2, r2, r14 // a -= ks 331 BHI 0b 332 333 VPOP {d10-d13} 334 ADD sp, sp, 20 // skip pad of 12, r2, r3 335 POP {r4, r5, r6, r7, r8, r9, r10, r11, pc} 336 337 # Remainder- 1 to 7 bytes of A 338 .p2align 3 3394: 340 AND r5, r5, 7 // kc remainder 1 to 7 341 342 VLD1.8 {d0}, [r3] 343 VLD1.8 {d10}, [r9]! 344 VLD1.8 {d2}, [r12] 345 VLD1.8 {d4}, [r10] 346 VLD1.8 {d6}, [r0] 347 348 VMOVL.S8 q0, d0 349 VMOVL.S8 q5, d10 350 VMOVL.S8 q1, d2 351 VMOVL.S8 q2, d4 352 VMOVL.S8 q3, d6 353 VMLAL.S16 q8, d10, d0[0] 354 VMLAL.S16 q9, d11, d0[0] 355 VMLAL.S16 q10, d10, d2[0] 356 VMLAL.S16 q11, d11, d2[0] 357 VMLAL.S16 q12, d10, d4[0] 358 VMLAL.S16 q13, d11, d4[0] 359 VMLAL.S16 q14, d10, d6[0] 360 VMLAL.S16 q15, d11, d6[0] 361 CMP r5, 2 362 BLO 3b 363 364 VLD1.8 {d10}, [r9]! 365 VMOVL.S8 q5, d10 366 VMLAL.S16 q8, d10, d0[1] 367 VMLAL.S16 q9, d11, d0[1] 368 VMLAL.S16 q10, d10, d2[1] 369 VMLAL.S16 q11, d11, d2[1] 370 VMLAL.S16 q12, d10, d4[1] 371 VMLAL.S16 q13, d11, d4[1] 372 VMLAL.S16 q14, d10, d6[1] 373 VMLAL.S16 q15, d11, d6[1] 374 BEQ 3b 375 376 VLD1.8 {d10}, [r9]! 377 VMOVL.S8 q5, d10 378 VMLAL.S16 q8, d10, d0[2] 379 VMLAL.S16 q9, d11, d0[2] 380 VMLAL.S16 q10, d10, d2[2] 381 VMLAL.S16 q11, d11, d2[2] 382 VMLAL.S16 q12, d10, d4[2] 383 VMLAL.S16 q13, d11, d4[2] 384 VMLAL.S16 q14, d10, d6[2] 385 VMLAL.S16 q15, d11, d6[2] 386 CMP r5, 4 387 BLO 3b 388 389 VLD1.8 {d10}, [r9]! 390 VMOVL.S8 q5, d10 391 VMLAL.S16 q8, d10, d0[3] 392 VMLAL.S16 q9, d11, d0[3] 393 VMLAL.S16 q10, d10, d2[3] 394 VMLAL.S16 q11, d11, d2[3] 395 VMLAL.S16 q12, d10, d4[3] 396 VMLAL.S16 q13, d11, d4[3] 397 VMLAL.S16 q14, d10, d6[3] 398 VMLAL.S16 q15, d11, d6[3] 399 BEQ 3b 400 401 VLD1.8 {d10}, [r9]! 402 VMOVL.S8 q5, d10 403 VMLAL.S16 q8, d10, d1[0] 404 VMLAL.S16 q9, d11, d1[0] 405 VMLAL.S16 q10, d10, d3[0] 406 VMLAL.S16 q11, d11, d3[0] 407 VMLAL.S16 q12, d10, d5[0] 408 VMLAL.S16 q13, d11, d5[0] 409 VMLAL.S16 q14, d10, d7[0] 410 VMLAL.S16 q15, d11, d7[0] 411 CMP r5, 6 412 BLO 3b 413 414 VLD1.8 {d10}, [r9]! 415 VMOVL.S8 q5, d10 416 VMLAL.S16 q8, d10, d1[1] 417 VMLAL.S16 q9, d11, d1[1] 418 VMLAL.S16 q10, d10, d3[1] 419 VMLAL.S16 q11, d11, d3[1] 420 VMLAL.S16 q12, d10, d5[1] 421 VMLAL.S16 q13, d11, d5[1] 422 VMLAL.S16 q14, d10, d7[1] 423 VMLAL.S16 q15, d11, d7[1] 424 BEQ 3b 425 426 VLD1.8 {d10}, [r9]! 427 VMOVL.S8 q5, d10 428 VMLAL.S16 q8, d10, d1[2] 429 VMLAL.S16 q9, d11, d1[2] 430 VMLAL.S16 q10, d10, d3[2] 431 VMLAL.S16 q11, d11, d3[2] 432 VMLAL.S16 q12, d10, d5[2] 433 VMLAL.S16 q13, d11, d5[2] 434 VMLAL.S16 q14, d10, d7[2] 435 VMLAL.S16 q15, d11, d7[2] 436 B 3b 437 438 # Store odd width 439 .p2align 3 4405: 441 TST r1, 4 442 BEQ 6f 443 VST1.32 {d3[0]}, [r6]! 444 VST1.32 {d2[0]}, [r8]! 445 VST1.32 {d1[0]}, [r4]! 446 VST1.32 {d0[0]}, [r11]! 447 VEXT.8 q1, q1, q1, 4 448 VEXT.8 q0, q0, q0, 4 4496: 450 TST r1, 2 451 BEQ 7f 452 VST1.16 {d3[0]}, [r6]! 453 VST1.16 {d2[0]}, [r8]! 454 VST1.16 {d1[0]}, [r4]! 455 VST1.16 {d0[0]}, [r11]! 456 VEXT.8 q1, q1, q1, 2 457 VEXT.8 q0, q0, q0, 2 458 4597: 460 TST r1, 1 461 BEQ 8f 462 VST1.8 {d3[0]}, [r6] 463 VST1.8 {d2[0]}, [r8] 464 VST1.8 {d1[0]}, [r4] 465 VST1.8 {d0[0]}, [r11] 466 4678: 468 VPOP {d10-d13} 469 ADD sp, sp, 20 // skip pad of 12, r2, r3 470 POP {r4, r5, r6, r7, r8, r9, r10, r11, pc} 471 472END_FUNCTION xnn_qc8_igemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_prfm_ld64 473#ifdef __ELF__ 474.section ".note.GNU-stack","",%progbits 475#endif 476