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