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