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