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