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