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