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