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