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_qu8_gemm_minmax_rndnu_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 uint8_t*restrict a, r3 20// size_t a_stride, sp + 88 -> (r7) 21// const void*restrict w, sp + 92 -> r9 22// uint8_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_conv_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 20 bytes 47# struct { 48# uint8_t kernel_zero_point[4]; d14 49# int32_t right_pre_shift; d12[0] 50# int32_t multiplier; d12[1] 51# int32_t right_post_shift; d13[0] 52# int16_t output_zero_point; d13[2] 53# uint8_t output_min; d13[6] 54# uint8_t output_max; d13[7] 55# } rndnu_neon; 56 57BEGIN_FUNCTION xnn_qu8_gemm_minmax_rndnu_ukernel_4x8__aarch32_neon_mlal_lane_cortex_a7 58 # Push 88 bytes 59 PUSH {r4, r5, r6, r7, r8, r9, r10, r11} // 32 60 VPUSH {d8-d14} // +56 = 88 61 62 LDR r7, [sp, 88] // a_stride 63 LDR r11, [sp, 96] // c 64 LDR r6, [sp, 100] // cm_stride 65 LDR r9, [sp, 92] // w 66 LDR r5, [sp, 108] // params 67 68 # Clamp A and C pointers 69 CMP r0, 2 // if mr >= 2 70 ADD r12, r3, r7 // a1 = a0 + a_stride 71 ADD r4, r11, r6 // c1 = c0 + cm_stride 72 MOVLO r12, r3 // a1 73 MOVLO r4, r11 // c1 74 // if mr > 2 75 ADD r10, r12, r7 // a2 = a1 + a_stride 76 ADD r8, r4, r6 // c2 = c1 + cm_stride 77 MOVLS r10, r12 // a2 78 MOVLS r8, r4 // c2 79 80 CMP r0, 4 // if mr >=4 81 ADD r0, r10, r7 // a3 = a2 + a_stride 82 ADD r6, r8, r6 // c3 = c2 + cm_stride 83 MOVLO r0, r10 // a3 84 MOVLO r6, r8 // c3 85 86 # Load params values 87 VLD1.32 {d14[]}, [r5]! // QU8 kernel_zero_point 88 VLDM r5, {d12-d13} // RNDNU params 89 LDR r7, [sp, 104] // cn_stride 90 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 VMOV q11, q9 100 VMOV q12, q8 101 VMOV q13, q9 102 VMOV q14, q8 103 VMOV q15, q9 104 BLO 4f // less than 8 channels? 105 106 // Prologue - load 4A's and B0 107 VLD1.8 {d0}, [r3]! // A0 108 VLD1.8 {d2}, [r12]! // A1 109 VLD1.8 {d4}, [r10]! // A2 110 VLD1.8 {d6}, [r0]! // A3 111 VLD1.8 {d8}, [r9]! // B0 112 113 SUBS r5, r5, 8 // k = k - 8 114 BLO 2f // less than 8 channels? 115 116 // Main loop - 8 bytes 117 // 64 bytes for weights. 118 // 5 VMOVL = 4 A and 1 B = 5 cycles 119 // 7 blocks with VLD B, VMOVL, 8 VMLA = 10 cycles 120 // 1 blocks with VLD B, VMLA = 9 cycles 121 // total = 84 cycles 122 .p2align 3 1231: 124 // Extend - 5 cycles 125 VMOVL.U8 q0, d0 126 VSUBL.U8 q4, d8, d14 127 VMOVL.U8 q1, d2 128 VMOVL.U8 q2, d4 129 VMOVL.U8 q3, d6 130 131 // BLOCK 0 - 10 cycles 132 VLD1.8 {d10}, [r9]! // B1 133 VMLAL.S16 q8, d8, d0[0] 134 VMLAL.S16 q9, d9, d0[0] 135 VMLAL.S16 q10, d8, d2[0] 136 VMLAL.S16 q11, d9, d2[0] 137 VSUBL.U8 q5, d10, d14 138 VMLAL.S16 q12, d8, d4[0] 139 VMLAL.S16 q13, d9, d4[0] 140 VMLAL.S16 q14, d8, d6[0] 141 VMLAL.S16 q15, d9, d6[0] 142 143 // BLOCK 1 - 10 cycles 144 VLD1.8 {d8}, [r9]! // B2 145 VMLAL.S16 q8, d10, d0[1] 146 VMLAL.S16 q9, d11, d0[1] 147 VMLAL.S16 q10, d10, d2[1] 148 VMLAL.S16 q11, d11, d2[1] 149 VSUBL.U8 q4, d8, d14 150 VMLAL.S16 q12, d10, d4[1] 151 VMLAL.S16 q13, d11, d4[1] 152 VMLAL.S16 q14, d10, d6[1] 153 VMLAL.S16 q15, d11, d6[1] 154 155 // BLOCK 2 - 10 cycles 156 VLD1.8 {d10}, [r9]! // B3 157 VMLAL.S16 q8, d8, d0[2] 158 VMLAL.S16 q9, d9, d0[2] 159 VMLAL.S16 q10, d8, d2[2] 160 VMLAL.S16 q11, d9, d2[2] 161 VSUBL.U8 q5, d10, d14 162 VMLAL.S16 q12, d8, d4[2] 163 VMLAL.S16 q13, d9, d4[2] 164 VMLAL.S16 q14, d8, d6[2] 165 VMLAL.S16 q15, d9, d6[2] 166 167 // BLOCK 3 - 10 cycles 168 VLD1.8 {d8}, [r9]! // B4 169 VMLAL.S16 q8, d10, d0[3] 170 VMLAL.S16 q9, d11, d0[3] 171 VMLAL.S16 q10, d10, d2[3] 172 VMLAL.S16 q11, d11, d2[3] 173 VLD1.8 {d0}, [r3]! // A0 174 VSUBL.U8 q4, d8, d14 175 VMLAL.S16 q12, d10, d4[3] 176 VMLAL.S16 q13, d11, d4[3] 177 VMLAL.S16 q14, d10, d6[3] 178 VMLAL.S16 q15, d11, d6[3] 179 180 // BLOCK 4 - 10 cycles 181 VLD1.8 {d10}, [r9]! // B5 182 VMLAL.S16 q8, d8, d1[0] 183 VMLAL.S16 q9, d9, d1[0] 184 VMLAL.S16 q10, d8, d3[0] 185 VMLAL.S16 q11, d9, d3[0] 186 VLD1.8 {d2}, [r12]! // A1 187 VSUBL.U8 q5, d10, d14 188 VMLAL.S16 q12, d8, d5[0] 189 VMLAL.S16 q13, d9, d5[0] 190 VMLAL.S16 q14, d8, d7[0] 191 VMLAL.S16 q15, d9, d7[0] 192 193 // BLOCK 5 - 10 cycles 194 VLD1.8 {d8}, [r9]! // B6 195 VMLAL.S16 q8, d10, d1[1] 196 VMLAL.S16 q9, d11, d1[1] 197 VMLAL.S16 q10, d10, d3[1] 198 VMLAL.S16 q11, d11, d3[1] 199 VLD1.8 {d4}, [r10]! // A2 200 VSUBL.U8 q4, d8, d14 201 VMLAL.S16 q12, d10, d5[1] 202 VMLAL.S16 q13, d11, d5[1] 203 VMLAL.S16 q14, d10, d7[1] 204 VMLAL.S16 q15, d11, d7[1] 205 206 // BLOCK 6 - 10 cycles 207 VLD1.8 {d10}, [r9]! // B7 208 VMLAL.S16 q8, d8, d1[2] 209 VMLAL.S16 q9, d9, d1[2] 210 VMLAL.S16 q10, d8, d3[2] 211 VMLAL.S16 q11, d9, d3[2] 212 VLD1.8 {d6}, [r0]! // A3 213 VSUBL.U8 q5, d10, d14 214 VMLAL.S16 q12, d8, d5[2] 215 VMLAL.S16 q13, d9, d5[2] 216 VMLAL.S16 q14, d8, d7[2] 217 VMLAL.S16 q15, d9, d7[2] 218 219 // BLOCK 7 - 9 cycles 220 VLD1.8 {d8}, [r9]! // B0 221 VMLAL.S16 q8, d10, d1[3] 222 VMLAL.S16 q9, d11, d1[3] 223 VMLAL.S16 q10, d10, d3[3] 224 VMLAL.S16 q11, d11, d3[3] 225 VMLAL.S16 q12, d10, d5[3] 226 VMLAL.S16 q13, d11, d5[3] 227 SUBS r5, r5, 8 228 VMLAL.S16 q14, d10, d7[3] 229 VMLAL.S16 q15, d11, d7[3] 230 BHS 1b 231 232 // Epilogue 233 234 .p2align 3 2352: 236 VMOVL.U8 q0, d0 237 VSUBL.U8 q4, d8, d14 238 VMOVL.U8 q1, d2 239 VMOVL.U8 q2, d4 240 VMOVL.U8 q3, d6 241 242 VLD1.8 {d10}, [r9]! // B1 243 VMLAL.S16 q8, d8, d0[0] 244 VMLAL.S16 q9, d9, d0[0] 245 VMLAL.S16 q10, d8, d2[0] 246 VMLAL.S16 q11, d9, d2[0] 247 VSUBL.U8 q5, d10, d14 248 VMLAL.S16 q12, d8, d4[0] 249 VMLAL.S16 q13, d9, d4[0] 250 VMLAL.S16 q14, d8, d6[0] 251 VMLAL.S16 q15, d9, d6[0] 252 253 VLD1.8 {d8}, [r9]! // B2 254 VMLAL.S16 q8, d10, d0[1] 255 VMLAL.S16 q9, d11, d0[1] 256 VMLAL.S16 q10, d10, d2[1] 257 VMLAL.S16 q11, d11, d2[1] 258 VSUBL.U8 q4, d8, d14 259 VMLAL.S16 q12, d10, d4[1] 260 VMLAL.S16 q13, d11, d4[1] 261 VMLAL.S16 q14, d10, d6[1] 262 VMLAL.S16 q15, d11, d6[1] 263 264 VLD1.8 {d10}, [r9]! // B3 265 VMLAL.S16 q8, d8, d0[2] 266 VMLAL.S16 q9, d9, d0[2] 267 VMLAL.S16 q10, d8, d2[2] 268 VMLAL.S16 q11, d9, d2[2] 269 VSUBL.U8 q5, d10, d14 270 VMLAL.S16 q12, d8, d4[2] 271 VMLAL.S16 q13, d9, d4[2] 272 VMLAL.S16 q14, d8, d6[2] 273 VMLAL.S16 q15, d9, d6[2] 274 275 VLD1.8 {d8}, [r9]! // B4 276 VMLAL.S16 q8, d10, d0[3] 277 VMLAL.S16 q9, d11, d0[3] 278 VMLAL.S16 q10, d10, d2[3] 279 VMLAL.S16 q11, d11, d2[3] 280 VSUBL.U8 q4, d8, d14 281 VMLAL.S16 q12, d10, d4[3] 282 VMLAL.S16 q13, d11, d4[3] 283 VMLAL.S16 q14, d10, d6[3] 284 VMLAL.S16 q15, d11, d6[3] 285 286 VLD1.8 {d10}, [r9]! // B5 287 VMLAL.S16 q8, d8, d1[0] 288 VMLAL.S16 q9, d9, d1[0] 289 VMLAL.S16 q10, d8, d3[0] 290 VMLAL.S16 q11, d9, d3[0] 291 VSUBL.U8 q5, d10, d14 292 VMLAL.S16 q12, d8, d5[0] 293 VMLAL.S16 q13, d9, d5[0] 294 VMLAL.S16 q14, d8, d7[0] 295 VMLAL.S16 q15, d9, d7[0] 296 297 VLD1.8 {d8}, [r9]! // B6 298 VMLAL.S16 q8, d10, d1[1] 299 VMLAL.S16 q9, d11, d1[1] 300 VMLAL.S16 q10, d10, d3[1] 301 VMLAL.S16 q11, d11, d3[1] 302 VSUBL.U8 q4, d8, d14 303 VMLAL.S16 q12, d10, d5[1] 304 VMLAL.S16 q13, d11, d5[1] 305 VMLAL.S16 q14, d10, d7[1] 306 VMLAL.S16 q15, d11, d7[1] 307 308 VLD1.8 {d10}, [r9]! // B7 309 VMLAL.S16 q8, d8, d1[2] 310 VMLAL.S16 q9, d9, d1[2] 311 VMLAL.S16 q10, d8, d3[2] 312 VMLAL.S16 q11, d9, d3[2] 313 VSUBL.U8 q5, d10, d14 314 VMLAL.S16 q12, d8, d5[2] 315 VMLAL.S16 q13, d9, d5[2] 316 VMLAL.S16 q14, d8, d7[2] 317 VMLAL.S16 q15, d9, d7[2] 318 319 VMLAL.S16 q8, d10, d1[3] 320 VMLAL.S16 q9, d11, d1[3] 321 VMLAL.S16 q10, d10, d3[3] 322 VMLAL.S16 q11, d11, d3[3] 323 VMLAL.S16 q12, d10, d5[3] 324 VMLAL.S16 q13, d11, d5[3] 325 ADDS r5, r5, 8 326 VMLAL.S16 q14, d10, d7[3] 327 VMLAL.S16 q15, d11, d7[3] 328 329 # Is there a remainder?- 1-7 bytes of A 330 BNE 4f 331 3323: 333 # RNDNU quantization 334 VDUP.32 q0, d12[0] // right_pre_shift 335 336 VQSHL.S32 q8, q8, q0 337 VQSHL.S32 q9, q9, q0 338 VQSHL.S32 q10, q10, q0 339 VQSHL.S32 q11, q11, q0 340 VQSHL.S32 q12, q12, q0 341 VQSHL.S32 q13, q13, q0 342 VQSHL.S32 q14, q14, q0 343 VQSHL.S32 q15, q15, q0 344 345 VDUP.32 q2, d13[0] // right_post_shift 346 347 VQDMULH.S32 q8, q8, d12[1] // multiplier 348 VQDMULH.S32 q9, q9, d12[1] 349 VQDMULH.S32 q10, q10, d12[1] 350 VQDMULH.S32 q11, q11, d12[1] 351 VQDMULH.S32 q12, q12, d12[1] 352 VQDMULH.S32 q13, q13, d12[1] 353 VQDMULH.S32 q14, q14, d12[1] 354 VQDMULH.S32 q15, q15, d12[1] 355 356 VRSHL.S32 q8, q8, q2 357 VRSHL.S32 q9, q9, q2 358 VRSHL.S32 q10, q10, q2 359 VRSHL.S32 q11, q11, q2 360 VRSHL.S32 q12, q12, q2 361 VRSHL.S32 q13, q13, q2 362 VRSHL.S32 q14, q14, q2 363 VRSHL.S32 q15, q15, q2 364 365 VDUP.16 q0, d13[2] // output_zero_point 366 367 VQMOVN.S32 d16, q8 368 VQMOVN.S32 d17, q9 369 VQMOVN.S32 d18, q10 370 VQMOVN.S32 d19, q11 371 VQMOVN.S32 d20, q12 372 VQMOVN.S32 d21, q13 373 VQMOVN.S32 d22, q14 374 VQMOVN.S32 d23, q15 375 376 VQADD.S16 q8, q8, q0 377 VQADD.S16 q9, q9, q0 378 VQADD.S16 q10, q10, q0 379 VQADD.S16 q11, q11, q0 380 381 VDUP.8 q12, d13[6] // output_min 382 383 VQMOVUN.S16 d0, q8 384 VQMOVUN.S16 d1, q9 385 VQMOVUN.S16 d2, q10 386 VQMOVUN.S16 d3, q11 387 388 VDUP.8 q13, d13[7] // output_max 389 390 VMAX.U8 q0, q0, q12 391 VMAX.U8 q1, q1, q12 392 393 SUBS r1, r1, 8 394 395 VMIN.U8 q0, q0, q13 396 VMIN.U8 q1, q1, q13 397 398 # Store full 4 x 8 399 BLO 5f 400 VST1.8 {d0}, [r11], r7 401 SUB r3, r3, r2 402 VST1.8 {d1}, [r4], r7 403 SUB r12, r12, r2 404 VST1.8 {d2}, [r8], r7 405 SUB r10, r10, r2 406 VST1.8 {d3}, [r6], r7 407 SUB r0, r0, r2 408 BHI 0b 409 410 VPOP {d8-d14} 411 POP {r4, r5, r6, r7, r8, r9, r10, r11} 412 BX lr 413 414 # Remainder- 1 to 7 bytes of A 415 .p2align 3 4164: 417 AND r5, r5, 7 // kc remainder 1 to 7 418 419 VLD1.8 {d0}, [r3], r5 420 VLD1.8 {d8}, [r9]! 421 VLD1.8 {d2}, [r12], r5 422 VLD1.8 {d4}, [r10], r5 423 VLD1.8 {d6}, [r0], r5 424 425 VMOVL.U8 q0, d0 426 VSUBL.U8 q4, d8, d14 427 VMOVL.U8 q1, d2 428 VMOVL.U8 q2, d4 429 VMOVL.U8 q3, d6 430 VMLAL.S16 q8, d8, d0[0] 431 VMLAL.S16 q9, d9, d0[0] 432 VMLAL.S16 q10, d8, d2[0] 433 VMLAL.S16 q11, d9, d2[0] 434 VMLAL.S16 q12, d8, d4[0] 435 VMLAL.S16 q13, d9, d4[0] 436 VMLAL.S16 q14, d8, d6[0] 437 VMLAL.S16 q15, d9, d6[0] 438 CMP r5, 2 439 BLO 3b 440 441 VLD1.8 {d8}, [r9]! 442 VSUBL.U8 q4, d8, d14 443 VMLAL.S16 q8, d8, d0[1] 444 VMLAL.S16 q9, d9, d0[1] 445 VMLAL.S16 q10, d8, d2[1] 446 VMLAL.S16 q11, d9, d2[1] 447 VMLAL.S16 q12, d8, d4[1] 448 VMLAL.S16 q13, d9, d4[1] 449 VMLAL.S16 q14, d8, d6[1] 450 VMLAL.S16 q15, d9, d6[1] 451 BEQ 3b 452 453 VLD1.8 {d8}, [r9]! 454 VSUBL.U8 q4, d8, d14 455 VMLAL.S16 q8, d8, d0[2] 456 VMLAL.S16 q9, d9, d0[2] 457 VMLAL.S16 q10, d8, d2[2] 458 VMLAL.S16 q11, d9, d2[2] 459 VMLAL.S16 q12, d8, d4[2] 460 VMLAL.S16 q13, d9, d4[2] 461 VMLAL.S16 q14, d8, d6[2] 462 VMLAL.S16 q15, d9, d6[2] 463 CMP r5, 4 464 BLO 3b 465 466 VLD1.8 {d8}, [r9]! 467 VSUBL.U8 q4, d8, d14 468 VMLAL.S16 q8, d8, d0[3] 469 VMLAL.S16 q9, d9, d0[3] 470 VMLAL.S16 q10, d8, d2[3] 471 VMLAL.S16 q11, d9, d2[3] 472 VMLAL.S16 q12, d8, d4[3] 473 VMLAL.S16 q13, d9, d4[3] 474 VMLAL.S16 q14, d8, d6[3] 475 VMLAL.S16 q15, d9, d6[3] 476 BEQ 3b 477 478 VLD1.8 {d8}, [r9]! 479 VSUBL.U8 q4, d8, d14 480 VMLAL.S16 q8, d8, d1[0] 481 VMLAL.S16 q9, d9, d1[0] 482 VMLAL.S16 q10, d8, d3[0] 483 VMLAL.S16 q11, d9, d3[0] 484 VMLAL.S16 q12, d8, d5[0] 485 VMLAL.S16 q13, d9, d5[0] 486 VMLAL.S16 q14, d8, d7[0] 487 VMLAL.S16 q15, d9, d7[0] 488 CMP r5, 6 489 BLO 3b 490 491 VLD1.8 {d8}, [r9]! 492 VSUBL.U8 q4, d8, d14 493 VMLAL.S16 q8, d8, d1[1] 494 VMLAL.S16 q9, d9, d1[1] 495 VMLAL.S16 q10, d8, d3[1] 496 VMLAL.S16 q11, d9, d3[1] 497 VMLAL.S16 q12, d8, d5[1] 498 VMLAL.S16 q13, d9, d5[1] 499 VMLAL.S16 q14, d8, d7[1] 500 VMLAL.S16 q15, d9, d7[1] 501 BEQ 3b 502 503 VLD1.8 {d8}, [r9]! 504 VSUBL.U8 q4, d8, d14 505 VMLAL.S16 q8, d8, d1[2] 506 VMLAL.S16 q9, d9, d1[2] 507 VMLAL.S16 q10, d8, d3[2] 508 VMLAL.S16 q11, d9, d3[2] 509 VMLAL.S16 q12, d8, d5[2] 510 VMLAL.S16 q13, d9, d5[2] 511 VMLAL.S16 q14, d8, d7[2] 512 VMLAL.S16 q15, d9, d7[2] 513 B 3b 514 515 # Store odd width 516 .p2align 3 5175: 518 TST r1, 4 519 BEQ 6f 520 VST1.32 {d0[0]}, [r11]! 521 VST1.32 {d1[0]}, [r4]! 522 VST1.32 {d2[0]}, [r8]! 523 VST1.32 {d3[0]}, [r6]! 524 VEXT.8 q0, q0, q0, 4 525 VEXT.8 q1, q1, q1, 4 5266: 527 TST r1, 2 528 BEQ 7f 529 VST1.16 {d0[0]}, [r11]! 530 VST1.16 {d1[0]}, [r4]! 531 VST1.16 {d2[0]}, [r8]! 532 VST1.16 {d3[0]}, [r6]! 533 VEXT.8 q0, q0, q0, 2 534 VEXT.8 q1, q1, q1, 2 535 5367: 537 TST r1, 1 538 BEQ 8f 539 VST1.8 {d0[0]}, [r11] 540 VST1.8 {d1[0]}, [r4] 541 VST1.8 {d2[0]}, [r8] 542 VST1.8 {d3[0]}, [r6] 543 5448: 545 VPOP {d8-d14} 546 POP {r4, r5, r6, r7, r8, r9, r10, r11} 547 BX lr 548 549END_FUNCTION xnn_qu8_gemm_minmax_rndnu_ukernel_4x8__aarch32_neon_mlal_lane_cortex_a7 550 551#ifdef __ELF__ 552.section ".note.GNU-stack","",%progbits 553#endif 554 555