1// Auto-generated file. Do not edit! 2// Template: src/qs8-gemm/4x8-aarch32-neon-mlal-lane-cortex-a7.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_cortex_a7( 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 + 88 -> (r7) 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// xnn_qs8_minmax_params params) sp + 108 -> (r5) 26 27// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved. 28 29// Based on cortex_a53 microkernel but with Neon loads 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 d8-d9 q4 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 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_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_cortex_a7 55 # Push 88 bytes 56 PUSH {r4, r5, r6, r7, r8, r9, r10, r11} // 32 57 SUB sp, sp, 8 // +8 58 VPUSH {d8-d13} // +48 = 88 59 60 LDR r7, [sp, 88] // a_stride 61 LDR r11, [sp, 96] // c 62 LDR r6, [sp, 100] // cm_stride 63 LDR r9, [sp, 92] // w 64 LDR r5, [sp, 108] // 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 VLDM r5!, {d12} // QC8 neon params 86 VLD1.16 {d13[]}, [r5] // output_min/max 87 LDR r7, [sp, 104] // 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 4f // less than 8 channels? 103 104 // Prologue - load 4A's and B0 105 VLD1.8 {d0}, [r3]! // A0 106 VLD1.8 {d2}, [r12]! // A1 107 VLD1.8 {d4}, [r10]! // A2 108 VLD1.8 {d6}, [r0]! // A3 109 VLD1.8 {d8}, [r9]! // B0 110 111 SUBS r5, r5, 8 // k = k - 8 112 BLO 2f // less than 8 channels? 113 114 // Main loop - 8 bytes 115 // 64 bytes for weights. 116 // 5 VMOVL = 4 A and 1 B = 5 cycles 117 // 7 blocks with VLD B, VMOVL, 8 VMLA = 10 cycles 118 // 1 blocks with VLD B, VMLA = 9 cycles 119 // total = 84 cycles 120 .p2align 3 1211: 122 // Extend - 5 cycles 123 VMOVL.S8 q0, d0 124 VMOVL.S8 q4, d8 125 VMOVL.S8 q1, d2 126 VMOVL.S8 q2, d4 127 VMOVL.S8 q3, d6 128 129 // BLOCK 0 - 10 cycles 130 VLD1.8 {d10}, [r9]! // B1 131 VMLAL.S16 q8, d8, d0[0] 132 VMLAL.S16 q9, d9, d0[0] 133 VMLAL.S16 q10, d8, d2[0] 134 VMLAL.S16 q11, d9, d2[0] 135 VMOVL.S8 q5, d10 136 VMLAL.S16 q12, d8, d4[0] 137 VMLAL.S16 q13, d9, d4[0] 138 VMLAL.S16 q14, d8, d6[0] 139 VMLAL.S16 q15, d9, d6[0] 140 141 // BLOCK 1 - 10 cycles 142 VLD1.8 {d8}, [r9]! // B2 143 VMLAL.S16 q8, d10, d0[1] 144 VMLAL.S16 q9, d11, d0[1] 145 VMLAL.S16 q10, d10, d2[1] 146 VMLAL.S16 q11, d11, d2[1] 147 VMOVL.S8 q4, d8 148 VMLAL.S16 q12, d10, d4[1] 149 VMLAL.S16 q13, d11, d4[1] 150 VMLAL.S16 q14, d10, d6[1] 151 VMLAL.S16 q15, d11, d6[1] 152 153 // BLOCK 2 - 10 cycles 154 VLD1.8 {d10}, [r9]! // B3 155 VMLAL.S16 q8, d8, d0[2] 156 VMLAL.S16 q9, d9, d0[2] 157 VMLAL.S16 q10, d8, d2[2] 158 VMLAL.S16 q11, d9, d2[2] 159 VMOVL.S8 q5, d10 160 VMLAL.S16 q12, d8, d4[2] 161 VMLAL.S16 q13, d9, d4[2] 162 VMLAL.S16 q14, d8, d6[2] 163 VMLAL.S16 q15, d9, d6[2] 164 165 // BLOCK 3 - 10 cycles 166 VLD1.8 {d8}, [r9]! // B4 167 VMLAL.S16 q8, d10, d0[3] 168 VMLAL.S16 q9, d11, d0[3] 169 VMLAL.S16 q10, d10, d2[3] 170 VMLAL.S16 q11, d11, d2[3] 171 VLD1.8 {d0}, [r3]! // A0 172 VMOVL.S8 q4, d8 173 VMLAL.S16 q12, d10, d4[3] 174 VMLAL.S16 q13, d11, d4[3] 175 VMLAL.S16 q14, d10, d6[3] 176 VMLAL.S16 q15, d11, d6[3] 177 178 // BLOCK 4 - 10 cycles 179 VLD1.8 {d10}, [r9]! // B5 180 VMLAL.S16 q8, d8, d1[0] 181 VMLAL.S16 q9, d9, d1[0] 182 VMLAL.S16 q10, d8, d3[0] 183 VMLAL.S16 q11, d9, d3[0] 184 VLD1.8 {d2}, [r12]! // A1 185 VMOVL.S8 q5, d10 186 VMLAL.S16 q12, d8, d5[0] 187 VMLAL.S16 q13, d9, d5[0] 188 VMLAL.S16 q14, d8, d7[0] 189 VMLAL.S16 q15, d9, d7[0] 190 191 // BLOCK 5 - 10 cycles 192 VLD1.8 {d8}, [r9]! // B6 193 VMLAL.S16 q8, d10, d1[1] 194 VMLAL.S16 q9, d11, d1[1] 195 VMLAL.S16 q10, d10, d3[1] 196 VMLAL.S16 q11, d11, d3[1] 197 VLD1.8 {d4}, [r10]! // A2 198 VMOVL.S8 q4, d8 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 // BLOCK 6 - 10 cycles 205 VLD1.8 {d10}, [r9]! // B7 206 VMLAL.S16 q8, d8, d1[2] 207 VMLAL.S16 q9, d9, d1[2] 208 VMLAL.S16 q10, d8, d3[2] 209 VMLAL.S16 q11, d9, d3[2] 210 VLD1.8 {d6}, [r0]! // A3 211 VMOVL.S8 q5, d10 212 VMLAL.S16 q12, d8, d5[2] 213 VMLAL.S16 q13, d9, d5[2] 214 VMLAL.S16 q14, d8, d7[2] 215 VMLAL.S16 q15, d9, d7[2] 216 217 // BLOCK 7 - 9 cycles 218 VLD1.8 {d8}, [r9]! // B0 219 VMLAL.S16 q8, d10, d1[3] 220 VMLAL.S16 q9, d11, d1[3] 221 VMLAL.S16 q10, d10, d3[3] 222 VMLAL.S16 q11, d11, d3[3] 223 VMLAL.S16 q12, d10, d5[3] 224 VMLAL.S16 q13, d11, d5[3] 225 SUBS r5, r5, 8 226 VMLAL.S16 q14, d10, d7[3] 227 VMLAL.S16 q15, d11, d7[3] 228 BHS 1b 229 230 // Epilogue 231 232 .p2align 3 2332: 234 VMOVL.S8 q0, d0 235 VMOVL.S8 q4, d8 236 VMOVL.S8 q1, d2 237 VMOVL.S8 q2, d4 238 VMOVL.S8 q3, d6 239 240 VLD1.8 {d10}, [r9]! // B1 241 VMLAL.S16 q8, d8, d0[0] 242 VMLAL.S16 q9, d9, d0[0] 243 VMLAL.S16 q10, d8, d2[0] 244 VMLAL.S16 q11, d9, d2[0] 245 VMOVL.S8 q5, d10 246 VMLAL.S16 q12, d8, d4[0] 247 VMLAL.S16 q13, d9, d4[0] 248 VMLAL.S16 q14, d8, d6[0] 249 VMLAL.S16 q15, d9, d6[0] 250 251 VLD1.8 {d8}, [r9]! // B2 252 VMLAL.S16 q8, d10, d0[1] 253 VMLAL.S16 q9, d11, d0[1] 254 VMLAL.S16 q10, d10, d2[1] 255 VMLAL.S16 q11, d11, d2[1] 256 VMOVL.S8 q4, d8 257 VMLAL.S16 q12, d10, d4[1] 258 VMLAL.S16 q13, d11, d4[1] 259 VMLAL.S16 q14, d10, d6[1] 260 VMLAL.S16 q15, d11, d6[1] 261 262 VLD1.8 {d10}, [r9]! // B3 263 VMLAL.S16 q8, d8, d0[2] 264 VMLAL.S16 q9, d9, d0[2] 265 VMLAL.S16 q10, d8, d2[2] 266 VMLAL.S16 q11, d9, d2[2] 267 VMOVL.S8 q5, d10 268 VMLAL.S16 q12, d8, d4[2] 269 VMLAL.S16 q13, d9, d4[2] 270 VMLAL.S16 q14, d8, d6[2] 271 VMLAL.S16 q15, d9, d6[2] 272 273 VLD1.8 {d8}, [r9]! // B4 274 VMLAL.S16 q8, d10, d0[3] 275 VMLAL.S16 q9, d11, d0[3] 276 VMLAL.S16 q10, d10, d2[3] 277 VMLAL.S16 q11, d11, d2[3] 278 VMOVL.S8 q4, d8 279 VMLAL.S16 q12, d10, d4[3] 280 VMLAL.S16 q13, d11, d4[3] 281 VMLAL.S16 q14, d10, d6[3] 282 VMLAL.S16 q15, d11, d6[3] 283 284 VLD1.8 {d10}, [r9]! // B5 285 VMLAL.S16 q8, d8, d1[0] 286 VMLAL.S16 q9, d9, d1[0] 287 VMLAL.S16 q10, d8, d3[0] 288 VMLAL.S16 q11, d9, d3[0] 289 VMOVL.S8 q5, d10 290 VMLAL.S16 q12, d8, d5[0] 291 VMLAL.S16 q13, d9, d5[0] 292 VMLAL.S16 q14, d8, d7[0] 293 VMLAL.S16 q15, d9, d7[0] 294 295 VLD1.8 {d8}, [r9]! // B6 296 VMLAL.S16 q8, d10, d1[1] 297 VMLAL.S16 q9, d11, d1[1] 298 VMLAL.S16 q10, d10, d3[1] 299 VMLAL.S16 q11, d11, d3[1] 300 VMOVL.S8 q4, d8 301 VMLAL.S16 q12, d10, d5[1] 302 VMLAL.S16 q13, d11, d5[1] 303 VMLAL.S16 q14, d10, d7[1] 304 VMLAL.S16 q15, d11, d7[1] 305 306 VLD1.8 {d10}, [r9]! // B7 307 VMLAL.S16 q8, d8, d1[2] 308 VMLAL.S16 q9, d9, d1[2] 309 VMLAL.S16 q10, d8, d3[2] 310 VMLAL.S16 q11, d9, d3[2] 311 VMOVL.S8 q5, d10 312 VMLAL.S16 q12, d8, d5[2] 313 VMLAL.S16 q13, d9, d5[2] 314 VMLAL.S16 q14, d8, d7[2] 315 VMLAL.S16 q15, d9, d7[2] 316 317 VMLAL.S16 q8, d10, d1[3] 318 VMLAL.S16 q9, d11, d1[3] 319 VMLAL.S16 q10, d10, d3[3] 320 VMLAL.S16 q11, d11, d3[3] 321 VMLAL.S16 q12, d10, d5[3] 322 VMLAL.S16 q13, d11, d5[3] 323 ADDS r5, r5, 8 324 VMLAL.S16 q14, d10, d7[3] 325 VMLAL.S16 q15, d11, d7[3] 326 327 # Is there a remainder?- 1-7 bytes of A 328 BNE 4f 329 3303: 331 # QC8 FP32 quantization 332 VLD1.8 {q0-q1}, [r9]! 333 334 VDUP.32 q2, d12[0] // magic_bias 335 VDUP.32 q3, d12[1] // magic_bias_less_output_zero_point 336 337 VCVT.F32.S32 q8, q8 338 VCVT.F32.S32 q9, q9 339 VCVT.F32.S32 q10, q10 340 VCVT.F32.S32 q11, q11 341 VCVT.F32.S32 q12, q12 342 VCVT.F32.S32 q13, q13 343 VCVT.F32.S32 q14, q14 344 VCVT.F32.S32 q15, q15 345 346 VMUL.F32 q8, q8, q0 // multiplier 347 VMUL.F32 q9, q9, q1 348 VMUL.F32 q10, q10, q0 349 VMUL.F32 q11, q11, q1 350 VMUL.F32 q12, q12, q0 351 VMUL.F32 q13, q13, q1 352 VMUL.F32 q14, q14, q0 353 VMUL.F32 q15, q15, q1 354 355 VADD.F32 q8, q8, q2 // magic_bias 356 VADD.F32 q9, q9, q2 357 VADD.F32 q10, q10, q2 358 VADD.F32 q11, q11, q2 359 VADD.F32 q12, q12, q2 360 VADD.F32 q13, q13, q2 361 VADD.F32 q14, q14, q2 362 VADD.F32 q15, q15, q2 363 364 VQSUB.S32 q8, q8, q3 // magic_bias_less_output_zero_point 365 VQSUB.S32 q9, q9, q3 366 VQSUB.S32 q10, q10, q3 367 VQSUB.S32 q11, q11, q3 368 VQSUB.S32 q12, q12, q3 369 VQSUB.S32 q13, q13, q3 370 VQSUB.S32 q14, q14, q3 371 VQSUB.S32 q15, q15, q3 372 373 374 VQMOVN.S32 d16, q8 375 VQMOVN.S32 d17, q9 376 VQMOVN.S32 d18, q10 377 VQMOVN.S32 d19, q11 378 VQMOVN.S32 d20, q12 379 VQMOVN.S32 d21, q13 380 VQMOVN.S32 d22, q14 381 VQMOVN.S32 d23, q15 382 383 384 VDUP.8 q12, d13[6] // output_min 385 386 VQMOVN.S16 d0, q8 387 VQMOVN.S16 d1, q9 388 VQMOVN.S16 d2, q10 389 VQMOVN.S16 d3, q11 390 391 VDUP.8 q13, d13[7] // output_max 392 393 VMAX.S8 q0, q0, q12 394 VMAX.S8 q1, q1, q12 395 396 SUBS r1, r1, 8 397 398 VMIN.S8 q0, q0, q13 399 VMIN.S8 q1, q1, q13 400 401 # Store full 4 x 8 402 BLO 5f 403 VST1.8 {d0}, [r11], r7 404 SUB r3, r3, r2 405 VST1.8 {d1}, [r4], r7 406 SUB r12, r12, r2 407 VST1.8 {d2}, [r8], r7 408 SUB r10, r10, r2 409 VST1.8 {d3}, [r6], r7 410 SUB r0, r0, r2 411 BHI 0b 412 413 VPOP {d8-d13} 414 ADD sp, sp, 8 // skip d14 415 POP {r4, r5, r6, r7, r8, r9, r10, r11} 416 BX lr 417 418 # Remainder- 1 to 7 bytes of A 419 .p2align 3 4204: 421 AND r5, r5, 7 // kc remainder 1 to 7 422 423 VLD1.8 {d0}, [r3], r5 424 VLD1.8 {d8}, [r9]! 425 VLD1.8 {d2}, [r12], r5 426 VLD1.8 {d4}, [r10], r5 427 VLD1.8 {d6}, [r0], r5 428 429 VMOVL.S8 q0, d0 430 VMOVL.S8 q4, d8 431 VMOVL.S8 q1, d2 432 VMOVL.S8 q2, d4 433 VMOVL.S8 q3, d6 434 VMLAL.S16 q8, d8, d0[0] 435 VMLAL.S16 q9, d9, d0[0] 436 VMLAL.S16 q10, d8, d2[0] 437 VMLAL.S16 q11, d9, d2[0] 438 VMLAL.S16 q12, d8, d4[0] 439 VMLAL.S16 q13, d9, d4[0] 440 VMLAL.S16 q14, d8, d6[0] 441 VMLAL.S16 q15, d9, d6[0] 442 CMP r5, 2 443 BLO 3b 444 445 VLD1.8 {d8}, [r9]! 446 VMOVL.S8 q4, d8 447 VMLAL.S16 q8, d8, d0[1] 448 VMLAL.S16 q9, d9, d0[1] 449 VMLAL.S16 q10, d8, d2[1] 450 VMLAL.S16 q11, d9, d2[1] 451 VMLAL.S16 q12, d8, d4[1] 452 VMLAL.S16 q13, d9, d4[1] 453 VMLAL.S16 q14, d8, d6[1] 454 VMLAL.S16 q15, d9, d6[1] 455 BEQ 3b 456 457 VLD1.8 {d8}, [r9]! 458 VMOVL.S8 q4, d8 459 VMLAL.S16 q8, d8, d0[2] 460 VMLAL.S16 q9, d9, d0[2] 461 VMLAL.S16 q10, d8, d2[2] 462 VMLAL.S16 q11, d9, d2[2] 463 VMLAL.S16 q12, d8, d4[2] 464 VMLAL.S16 q13, d9, d4[2] 465 VMLAL.S16 q14, d8, d6[2] 466 VMLAL.S16 q15, d9, d6[2] 467 CMP r5, 4 468 BLO 3b 469 470 VLD1.8 {d8}, [r9]! 471 VMOVL.S8 q4, d8 472 VMLAL.S16 q8, d8, d0[3] 473 VMLAL.S16 q9, d9, d0[3] 474 VMLAL.S16 q10, d8, d2[3] 475 VMLAL.S16 q11, d9, d2[3] 476 VMLAL.S16 q12, d8, d4[3] 477 VMLAL.S16 q13, d9, d4[3] 478 VMLAL.S16 q14, d8, d6[3] 479 VMLAL.S16 q15, d9, d6[3] 480 BEQ 3b 481 482 VLD1.8 {d8}, [r9]! 483 VMOVL.S8 q4, d8 484 VMLAL.S16 q8, d8, d1[0] 485 VMLAL.S16 q9, d9, d1[0] 486 VMLAL.S16 q10, d8, d3[0] 487 VMLAL.S16 q11, d9, d3[0] 488 VMLAL.S16 q12, d8, d5[0] 489 VMLAL.S16 q13, d9, d5[0] 490 VMLAL.S16 q14, d8, d7[0] 491 VMLAL.S16 q15, d9, d7[0] 492 CMP r5, 6 493 BLO 3b 494 495 VLD1.8 {d8}, [r9]! 496 VMOVL.S8 q4, d8 497 VMLAL.S16 q8, d8, d1[1] 498 VMLAL.S16 q9, d9, d1[1] 499 VMLAL.S16 q10, d8, d3[1] 500 VMLAL.S16 q11, d9, d3[1] 501 VMLAL.S16 q12, d8, d5[1] 502 VMLAL.S16 q13, d9, d5[1] 503 VMLAL.S16 q14, d8, d7[1] 504 VMLAL.S16 q15, d9, d7[1] 505 BEQ 3b 506 507 VLD1.8 {d8}, [r9]! 508 VMOVL.S8 q4, d8 509 VMLAL.S16 q8, d8, d1[2] 510 VMLAL.S16 q9, d9, d1[2] 511 VMLAL.S16 q10, d8, d3[2] 512 VMLAL.S16 q11, d9, d3[2] 513 VMLAL.S16 q12, d8, d5[2] 514 VMLAL.S16 q13, d9, d5[2] 515 VMLAL.S16 q14, d8, d7[2] 516 VMLAL.S16 q15, d9, d7[2] 517 B 3b 518 519 # Store odd width 520 .p2align 3 5215: 522 TST r1, 4 523 BEQ 6f 524 VST1.32 {d0[0]}, [r11]! 525 VST1.32 {d1[0]}, [r4]! 526 VST1.32 {d2[0]}, [r8]! 527 VST1.32 {d3[0]}, [r6]! 528 VEXT.8 q0, q0, q0, 4 529 VEXT.8 q1, q1, q1, 4 5306: 531 TST r1, 2 532 BEQ 7f 533 VST1.16 {d0[0]}, [r11]! 534 VST1.16 {d1[0]}, [r4]! 535 VST1.16 {d2[0]}, [r8]! 536 VST1.16 {d3[0]}, [r6]! 537 VEXT.8 q0, q0, q0, 2 538 VEXT.8 q1, q1, q1, 2 539 5407: 541 TST r1, 1 542 BEQ 8f 543 VST1.8 {d0[0]}, [r11] 544 VST1.8 {d1[0]}, [r4] 545 VST1.8 {d2[0]}, [r8] 546 VST1.8 {d3[0]}, [r6] 547 5488: 549 VPOP {d8-d13} 550 ADD sp, sp, 8 // skip d14 551 POP {r4, r5, r6, r7, r8, r9, r10, r11} 552 BX lr 553 554END_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_cortex_a7 555 556#ifdef __ELF__ 557.section ".note.GNU-stack","",%progbits 558#endif 559 560