"Fossies" - the Fresh Open Source Software Archive

Member "pytorch-1.8.2/aten/src/ATen/native/quantized/cpu/qnnpack/src/q8gemm/4x8-aarch32-neon.S" (23 Jul 2021, 18744 Bytes) of package /linux/misc/pytorch-1.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PowerPC Assembler source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Copyright (c) Facebook, Inc. and its affiliates.
    3  * All rights reserved.
    4  *
    5  * This source code is licensed under the BSD-style license found in the
    6  * LICENSE file in the root directory of this source tree.
    7  */
    8 
    9 #include <qnnpack/assembly.h>
   10 #include <requantization/runtime-assembly.h>
   11 
   12 .syntax unified
   13 
   14 #  Args passed via 4 registers (16 bytes)
   15 #  r0: mr
   16 #  r1: nr
   17 #  r2: k
   18 #  r3: a
   19 #
   20 
   21 #  Args passed via stack.
   22 #  TOS
   23 #  |-----------|
   24 #  |a_stride   | 0
   25 #  |w          | 4
   26 #  |c          | 8
   27 #  |c_stride   | 12
   28 #  |out ch indx| 16
   29 #  |params     | 20
   30 #  |-----------|
   31 #  
   32 
   33 #  After loading w pointer in ip reg.
   34 #  And after pushing r4-r9 and d8-d15 on stack
   35 #  |-----------|
   36 #  |d8 - d15   | 0
   37 #  |r4 - r9    | 64
   38 #  |a_stride   | 88
   39 #  |w          | 92
   40 #  |c          | 96
   41 #  |c_stride   | 100
   42 #  |out ch indx| 104
   43 #  |params     | 108
   44 #  |-----------|
   45 #  
   46 
   47 #
   48 # New Struct for pytorch_qnnp_conv_quantization_params
   49 # kernel zp             : 0 offset
   50 # input zp              : 2
   51 # requantization_scale  : 4
   52 # output zp             : 8
   53 # output max            : 10
   54 # output min            : 11
   55 # vfmin                 : 12
   56 # vfmax                 : 16
   57 # vfmagic               : 20
   58 # vimagic               : 24
   59 #
   60 
   61 # void pytorch_q8gemm_ukernel_4x8__aarch32_neon(
   62 #     size_t mr,
   63 #     size_t nr,
   64 #     size_t k,
   65 #     const uint8_t*restrict a,
   66 #     size_t a_stride,
   67 #     const void*restrict w,
   68 #     uint8_t*restrict c,
   69 #     size_t c_stride,
   70 #     size_t output_channel_index,
   71 #     const union pytorch_qnnp_conv_quantization_params quantization_params[restrict static 1])
   72 BEGIN_FUNCTION pytorch_q8gemm_ukernel_4x8__aarch32_neon
   73     .arm
   74 #ifndef __APPLE__
   75     .arch armv7-a
   76     .fpu neon
   77 #endif
   78     # Load w
   79     # - ip = w
   80     LDR ip, [sp, 4]
   81     PUSH {r4, r5, r6, r7, r8, r9}
   82 
   83     # Load quantization params
   84     # - r7 = quantization_params
   85     LDR r7, [sp, 44]
   86     VPUSH {d8-d15}
   87 
   88     # Load bias0123, bias4567
   89     VLDM ip!, {d16-d19}
   90 
   91     # Load output channel index
   92     LDR r5, [sp, 104]
   93     # Load pointer to per channel zero points array
   94     # Post-index: After load increment r7 by 4
   95     LDR r4, [r7], #4
   96     # Load a_zero_point:
   97     # - d14 = a_zero_point
   98     VLD1.8 {d14[]}, [r7]
   99 
  100     # Load a_stride
  101     # - r6 = a_stride
  102     LDR r9, [sp, 88]
  103 
  104     # Byte offset of output channel index for requant scale.
  105     LSL r6, r5, 2
  106     # Load pointer to per channel requant scale
  107     # Register offset, load r7+4
  108     LDR r8, [r7, 4]
  109     # Add output_channel_index to the b_zero_point pointer
  110     ADD r4, r4, r5
  111     # Load b_zero_point:
  112     # - d15 = b_zero_point
  113     VLD1.8 {d15}, [r4]
  114 
  115     # add 8 bytes to get to vfmax
  116     ADD r7, r7, 12
  117 
  118     CMP r0, 2
  119     ADD r4, r3, r9
  120 
  121     # Store in r8 pointer from where to load requant scale.
  122     ADD r8, r8, r6
  123 
  124     MOVLO r4, r3
  125 
  126     ADD r5, r4, r9
  127 
  128     # q10 := vacc1x0123
  129     VMOV.I32 q10, q8
  130     MOVLS r5, r4
  131     # q11 := vacc1x4567
  132     VMOV.I32 q11, q9
  133     ADD r6, r5, r9
  134     # q12 := vacc2x0123
  135     VMOV.I32 q12, q8
  136     CMP r0, 4
  137     # q13 := vacc2x4567
  138     VMOV.I32 q13, q9
  139     MOVNE r6, r5
  140     # q14 := vacc3x0123
  141     VMOV.I32 q14, q8
  142     SUBS r2, r2, 8
  143     # q15 := vacc3x4567
  144     VMOV.I32 q15, q9
  145     BLO 1f
  146 
  147     .p2align 5
  148 0:
  149     # Load a0
  150     # - d1 = a0
  151     VLD1.8 {d1}, [r3]!
  152 
  153     # Load a1
  154     # - d3 = a1
  155     VLD1.8 {d3}, [r4]!
  156 
  157     # Load b0-b7 (channel 0)
  158     # - d9 = b0-b7
  159     VLD1.8 {d9}, [ip:64]!
  160 
  161     # Load a2
  162     # - d5 = a2
  163     VLD1.8 {d5}, [r5]!
  164 
  165     # q0 = va0 = a0
  166     SUB_ZERO_POINT q0, d1, d14
  167 
  168     # Load a3
  169     # - d7 = a3
  170     VLD1.8 {d7}, [r6]!
  171 
  172     # q1 = va1 = a1
  173     SUB_ZERO_POINT q1, d3, d14
  174 
  175     # q4 = b0:7 - b_zero_point
  176     # - d8 = vb0123 (channel 0)
  177     # - d9 = vb4567 (channel 0)
  178     VSUBL.U8 q4, d9, d15
  179 
  180     # q2 = va2 = a2
  181     SUB_ZERO_POINT q2, d5, d14
  182     # q3 = va3 = a3
  183     SUB_ZERO_POINT q3, d7, d14
  184 
  185     ### Channel 0 ###
  186 
  187     # Load b0-b7 (channel 1)
  188     # - d11 = b0-b7
  189     VLD1.8 {d11}, [ip:64]!
  190 
  191     # vacc0x0123 += vb0123 * va0[0]
  192     VMLAL.S16 q8, d8, d0[0]
  193     # vacc0x4567 += vb4567 * va0[0]
  194     VMLAL.S16 q9, d9, d0[0]
  195 
  196     # vacc1x0123 += vb0123 * va1[0]
  197     VMLAL.S16 q10, d8, d2[0]
  198     # vacc1x4567 += vb4567 * va1[0]
  199     VMLAL.S16 q11, d9, d2[0]
  200 
  201     # vacc2x0123 += vb0123 * va2[0]
  202     VMLAL.S16 q12, d8, d4[0]
  203     # vacc2x4567 += vb4567 * va2[0]
  204     VMLAL.S16 q13, d9, d4[0]
  205 
  206     # q5 = b0:7 - b_zero_point
  207     # - d10 = vb0123 (channel 1)
  208     # - d11 = vb4567 (channel 1)
  209     VSUBL.U8 q5, d11, d15
  210 
  211     # vacc3x0123 += vb0123 * va3[0]
  212     VMLAL.S16 q14, d8, d6[0]
  213     # vacc3x4567 += vb4567 * va3[0]
  214     VMLAL.S16 q15, d9, d6[0]
  215 
  216     ### Channel 1 ###
  217 
  218     # Load b0-b7 (channel 2)
  219     # - d9 = b0-b7
  220     VLD1.8 {d9}, [ip:64]!
  221 
  222     # vacc0x0123 += vb0123 * va0[1]
  223     VMLAL.S16 q8, d10, d0[1]
  224     # vacc0x4567 += vb4567 * va0[1]
  225     VMLAL.S16 q9, d11, d0[1]
  226 
  227     # vacc1x0123 += vb0123 * va1[1]
  228     VMLAL.S16 q10, d10, d2[1]
  229     # vacc1x4567 += vb4567 * va1[1]
  230     VMLAL.S16 q11, d11, d2[1]
  231 
  232     # vacc2x0123 += vb0123 * va2[1]
  233     VMLAL.S16 q12, d10, d4[1]
  234     # vacc2x4567 += vb4567 * va2[1]
  235     VMLAL.S16 q13, d11, d4[1]
  236 
  237     # q4 = b0:7 - b_zero_point
  238     # - d8 = vb0123 (channel 2)
  239     # - d9 = vb4567 (channel 2)
  240     VSUBL.U8 q4, d9, d15
  241 
  242     # vacc3x0123 += vb0123 * va3[1]
  243     VMLAL.S16 q14, d10, d6[1]
  244     # vacc3x4567 += vb4567 * va3[1]
  245     VMLAL.S16 q15, d11, d6[1]
  246 
  247     ### Channel 2 ###
  248 
  249     # Load b0-b7 (channel 3)
  250     # - d11 = b0-b7
  251     VLD1.8 {d11}, [ip:64]!
  252 
  253     # vacc0x0123 += vb0123 * va0[2]
  254     VMLAL.S16 q8, d8, d0[2]
  255     # vacc0x4567 += vb4567 * va0[2]
  256     VMLAL.S16 q9, d9, d0[2]
  257 
  258     # vacc1x0123 += vb0123 * va1[2]
  259     VMLAL.S16 q10, d8, d2[2]
  260     # vacc1x4567 += vb4567 * va1[2]
  261     VMLAL.S16 q11, d9, d2[2]
  262 
  263     # vacc2x0123 += vb0123 * va2[2]
  264     VMLAL.S16 q12, d8, d4[2]
  265     # vacc2x4567 += vb4567 * va2[2]
  266     VMLAL.S16 q13, d9, d4[2]
  267 
  268     # q5 = b0:7 - b_zero_point
  269     # - d10 = vb0123 (channel 3)
  270     # - d11 = vb4567 (channel 3)
  271     VSUBL.U8 q5, d11, d15
  272 
  273     # vacc3x0123 += vb0123 * va3[2]
  274     VMLAL.S16 q14, d8, d6[2]
  275     # vacc3x4567 += vb4567 * va3[2]
  276     VMLAL.S16 q15, d9, d6[2]
  277 
  278     ### Channel 3 ###
  279 
  280     # Load b0-b7 (channel 4)
  281     # - d9 = b0-b7
  282     VLD1.8 {d9}, [ip:64]!
  283 
  284     # vacc0x0123 += vb0123 * va0[3]
  285     VMLAL.S16 q8, d10, d0[3]
  286     # vacc0x4567 += vb4567 * va0[3]
  287     VMLAL.S16 q9, d11, d0[3]
  288 
  289     # vacc1x0123 += vb0123 * va1[3]
  290     VMLAL.S16 q10, d10, d2[3]
  291     # vacc1x4567 += vb4567 * va1[3]
  292     VMLAL.S16 q11, d11, d2[3]
  293 
  294     # vacc2x0123 += vb0123 * va2[3]
  295     VMLAL.S16 q12, d10, d4[3]
  296     # vacc2x4567 += vb4567 * va2[3]
  297     VMLAL.S16 q13, d11, d4[3]
  298 
  299     # q5 = b0:7 - b_zero_point
  300     # - d10 = vb0123 (channel 4)
  301     # - d11 = vb4567 (channel 4)
  302     VSUBL.U8 q4, d9, d15
  303 
  304     # vacc3x0123 += vb0123 * va3[3]
  305     VMLAL.S16 q14, d10, d6[3]
  306     # vacc3x4567 += vb4567 * va3[3]
  307     VMLAL.S16 q15, d11, d6[3]
  308 
  309     ### Channel 4 ###
  310 
  311     # Load b0-b7 (channel 5)
  312     # - d11 = b0-b7
  313     VLD1.8 {d11}, [ip:64]!
  314 
  315     # vacc0x0123 += vb0123 * va0[4]
  316     VMLAL.S16 q8, d8, d1[0]
  317     # vacc0x4567 += vb4567 * va0[4]
  318     VMLAL.S16 q9, d9, d1[0]
  319 
  320     # vacc1x0123 += vb0123 * va1[4]
  321     VMLAL.S16 q10, d8, d3[0]
  322     # vacc1x4567 += vb4567 * va1[4]
  323     VMLAL.S16 q11, d9, d3[0]
  324 
  325     # vacc2x0123 += vb0123 * va2[4]
  326     VMLAL.S16 q12, d8, d5[0]
  327     # vacc2x4567 += vb4567 * va2[4]
  328     VMLAL.S16 q13, d9, d5[0]
  329 
  330     # q4 = b0:7 - b_zero_point
  331     # - d8 = vb0123 (channel 5)
  332     # - d9 = vb4567 (channel 5)
  333     VSUBL.U8 q5, d11, d15
  334 
  335     # vacc3x0123 += vb0123 * va3[4]
  336     VMLAL.S16 q14, d8, d7[0]
  337     # vacc3x4567 += vb4567 * va3[4]
  338     VMLAL.S16 q15, d9, d7[0]
  339 
  340     ### Channel 5 ###
  341 
  342     # Load b0-b7 (channel 6)
  343     # - d9 = b0-b7
  344     VLD1.8 {d9}, [ip:64]!
  345 
  346     # vacc0x0123 += vb0123 * va0[5]
  347     VMLAL.S16 q8, d10, d1[1]
  348     # vacc0x4567 += vb4567 * va0[5]
  349     VMLAL.S16 q9, d11, d1[1]
  350 
  351     # vacc1x0123 += vb0123 * va1[5]
  352     VMLAL.S16 q10, d10, d3[1]
  353     # vacc1x4567 += vb4567 * va1[5]
  354     VMLAL.S16 q11, d11, d3[1]
  355 
  356     # vacc2x0123 += vb0123 * va2[5]
  357     VMLAL.S16 q12, d10, d5[1]
  358     # vacc2x4567 += vb4567 * va2[5]
  359     VMLAL.S16 q13, d11, d5[1]
  360 
  361     # q4 = b0:7 - b_zero_point
  362     # - d8 = vb0123 (channel 6)
  363     # - d9 = vb4567 (channel 6)
  364     VSUBL.U8 q4, d9, d15
  365 
  366     # vacc3x0123 += vb0123 * va3[5]
  367     VMLAL.S16 q14, d10, d7[1]
  368     # vacc3x4567 += vb4567 * va3[5]
  369     VMLAL.S16 q15, d11, d7[1]
  370 
  371     ### Channel 6 ###
  372 
  373     # Load b0-b7 (channel 7)
  374     # - d11 = b0-b7
  375     VLD1.8 {d11}, [ip:64]!
  376 
  377     # vacc0x0123 += vb0123 * va0[6]
  378     VMLAL.S16 q8, d8, d1[2]
  379     # vacc0x4567 += vb4567 * va0[6]
  380     VMLAL.S16 q9, d9, d1[2]
  381 
  382     # vacc1x0123 += vb0123 * va1[6]
  383     VMLAL.S16 q10, d8, d3[2]
  384     # vacc1x4567 += vb4567 * va1[6]
  385     VMLAL.S16 q11, d9, d3[2]
  386 
  387     # vacc2x0123 += vb0123 * va2[6]
  388     VMLAL.S16 q12, d8, d5[2]
  389 
  390     # q5 = b0:7 - b_zero_point
  391     # - d10 = vb0123 (channel 7)
  392     # - d11 = vb4567 (channel 7)
  393     VSUBL.U8 q5, d11, d15
  394 
  395     # vacc2x4567 += vb4567 * va2[6]
  396     VMLAL.S16 q13, d9, d5[2]
  397 
  398     # vacc3x0123 += vb0123 * va3[6]
  399     VMLAL.S16 q14, d8, d7[2]
  400     # vacc3x4567 += vb4567 * va3[6]
  401     VMLAL.S16 q15, d9, d7[2]
  402 
  403     ### Channel 8 ###
  404     SUBS r2, r2, 8
  405 
  406     # vacc0x0123 += vb0123 * va0[7]
  407     VMLAL.S16 q8, d10, d1[3]
  408     # vacc0x4567 += vb4567 * va0[7]
  409     VMLAL.S16 q9, d11, d1[3]
  410 
  411     # vacc1x0123 += vb0123 * va1[7]
  412     VMLAL.S16 q10, d10, d3[3]
  413     # vacc1x4567 += vb4567 * va1[7]
  414     VMLAL.S16 q11, d11, d3[3]
  415 
  416     # vacc2x0123 += vb0123 * va2[7]
  417     VMLAL.S16 q12, d10, d5[3]
  418     # vacc2x4567 += vb4567 * va2[7]
  419     VMLAL.S16 q13, d11, d5[3]
  420 
  421     # vacc3x0123 += vb0123 * va3[7]
  422     VMLAL.S16 q14, d10, d7[3]
  423     # vacc3x4567 += vb4567 * va3[7]
  424     VMLAL.S16 q15, d11, d7[3]
  425 
  426     BHS 0b
  427 
  428 1:
  429     CMP r2, -8
  430     BEQ 2f
  431 
  432     # Adjust a0, a1, a2, a3
  433     ADD r3, r2
  434     ADD r4, r2
  435     ADD r5, r2
  436     ADD r6, r2
  437 
  438     # a_shift = 8 * k - 64
  439     LSL r2, r2, 3
  440     VDUP.32 d13, r2
  441 
  442     # Load a0
  443     # - d1 = a0
  444     VLD1.8 {d1}, [r3]
  445 
  446     # Load a1
  447     # - d3 = a1
  448     VLD1.8 {d3}, [r4]
  449 
  450     # Load b0-b7 (channel 0)
  451     # - d9 = b0-b7
  452     VLD1.8 {d9}, [ip:64]!
  453 
  454     # Load a2
  455     # - d5 = a2
  456     VLD1.8 {d5}, [r5]
  457 
  458     # q0 = va0 = a0
  459     VSHL.U64 d1, d1, d13
  460     SUB_ZERO_POINT q0, d1, d14
  461 
  462     # Load a3
  463     # - d7 = a3
  464     VLD1.8 {d7}, [r6]
  465 
  466     # q1 = va1 = a1
  467     VSHL.U64 d3, d3, d13
  468     SUB_ZERO_POINT q1, d3, d14
  469 
  470     # q4 = b0:7 - b_zero_point
  471     # - d8 = vb0123 (channel 0)
  472     # - d9 = vb4567 (channel 0)
  473     VSUBL.U8 q4, d9, d15
  474 
  475     # q2 = va2 = a2
  476     VSHL.U64 d5, d5, d13
  477     SUB_ZERO_POINT q2, d5, d14
  478     # q3 = va3 = a3
  479     VSHL.U64 d7, d7, d13
  480     SUB_ZERO_POINT q3, d7, d14
  481 
  482     ### Channel 0 ###
  483 
  484     # vacc0x0123 += vb0123 * va0[0]
  485     VMLAL.S16 q8, d8, d0[0]
  486     # vacc0x4567 += vb4567 * va0[0]
  487     VMLAL.S16 q9, d9, d0[0]
  488 
  489     # vacc1x0123 += vb0123 * va1[0]
  490     VMLAL.S16 q10, d8, d2[0]
  491     # vacc1x4567 += vb4567 * va1[0]
  492     VMLAL.S16 q11, d9, d2[0]
  493 
  494     # vacc2x0123 += vb0123 * va2[0]
  495     VMLAL.S16 q12, d8, d4[0]
  496     # vacc2x4567 += vb4567 * va2[0]
  497     VMLAL.S16 q13, d9, d4[0]
  498 
  499     # vacc3x0123 += vb0123 * va3[0]
  500     VMLAL.S16 q14, d8, d6[0]
  501     # vacc3x4567 += vb4567 * va3[0]
  502     VMLAL.S16 q15, d9, d6[0]
  503 
  504     CMP r2, -48
  505     BLO 2f
  506 
  507     ### Channel 1 ###
  508 
  509     # Load b0-b7 (channel 1)
  510     # - d11 = b0-b7
  511     VLD1.8 {d11}, [ip:64]!
  512 
  513     # q5 = b0:7 - b_zero_point
  514     # - d10 = vb0123 (channel 1)
  515     # - d11 = vb4567 (channel 1)
  516     VSUBL.U8 q5, d11, d15
  517 
  518     # vacc0x0123 += vb0123 * va0[1]
  519     VMLAL.S16 q8, d10, d0[1]
  520     # vacc0x4567 += vb4567 * va0[1]
  521     VMLAL.S16 q9, d11, d0[1]
  522 
  523     # vacc1x0123 += vb0123 * va1[1]
  524     VMLAL.S16 q10, d10, d2[1]
  525     # vacc1x4567 += vb4567 * va1[1]
  526     VMLAL.S16 q11, d11, d2[1]
  527 
  528     # vacc2x0123 += vb0123 * va2[1]
  529     VMLAL.S16 q12, d10, d4[1]
  530     # vacc2x4567 += vb4567 * va2[1]
  531     VMLAL.S16 q13, d11, d4[1]
  532 
  533     # vacc3x0123 += vb0123 * va3[1]
  534     VMLAL.S16 q14, d10, d6[1]
  535     # vacc3x4567 += vb4567 * va3[1]
  536     VMLAL.S16 q15, d11, d6[1]
  537 
  538     ### Channel 2 ###
  539     BLS 2f
  540 
  541     # Load b0-b7 (channel 2)
  542     # - d9 = b0-b7
  543     VLD1.8 {d9}, [ip:64]!
  544 
  545     # q4 = b0:7 - b_zero_point
  546     # - d8 = vb0123 (channel 2)
  547     # - d9 = vb4567 (channel 2)
  548     VSUBL.U8 q4, d9, d15
  549 
  550     # vacc0x0123 += vb0123 * va0[2]
  551     VMLAL.S16 q8, d8, d0[2]
  552     # vacc0x4567 += vb4567 * va0[2]
  553     VMLAL.S16 q9, d9, d0[2]
  554 
  555     # vacc1x0123 += vb0123 * va1[2]
  556     VMLAL.S16 q10, d8, d2[2]
  557     # vacc1x4567 += vb4567 * va1[2]
  558     VMLAL.S16 q11, d9, d2[2]
  559 
  560     # vacc2x0123 += vb0123 * va2[2]
  561     VMLAL.S16 q12, d8, d4[2]
  562     # vacc2x4567 += vb4567 * va2[2]
  563     VMLAL.S16 q13, d9, d4[2]
  564 
  565     # vacc3x0123 += vb0123 * va3[2]
  566     VMLAL.S16 q14, d8, d6[2]
  567     # vacc3x4567 += vb4567 * va3[2]
  568     VMLAL.S16 q15, d9, d6[2]
  569 
  570     ### Channel 3 ###
  571     CMP r2, -32
  572     BLO 2f
  573 
  574     # Load b0-b7 (channel 3)
  575     # - d9 = b0-b7
  576     VLD1.8 {d11}, [ip:64]!
  577 
  578     # q4 = b0:7 - b_zero_point
  579     # - d8 = vb0123 (channel 3)
  580     # - d9 = vb4567 (channel 3)
  581     VSUBL.U8 q5, d11, d15
  582 
  583     # vacc0x0123 += vb0123 * va0[3]
  584     VMLAL.S16 q8, d10, d0[3]
  585     # vacc0x4567 += vb4567 * va0[3]
  586     VMLAL.S16 q9, d11, d0[3]
  587 
  588     # vacc1x0123 += vb0123 * va1[3]
  589     VMLAL.S16 q10, d10, d2[3]
  590     # vacc1x4567 += vb4567 * va1[3]
  591     VMLAL.S16 q11, d11, d2[3]
  592 
  593     # vacc2x0123 += vb0123 * va2[3]
  594     VMLAL.S16 q12, d10, d4[3]
  595     # vacc2x4567 += vb4567 * va2[3]
  596     VMLAL.S16 q13, d11, d4[3]
  597 
  598     # vacc3x0123 += vb0123 * va3[3]
  599     VMLAL.S16 q14, d10, d6[3]
  600     # vacc3x4567 += vb4567 * va3[3]
  601     VMLAL.S16 q15, d11, d6[3]
  602 
  603     ### Channel 4 ###
  604     BLS 2f
  605 
  606     # Load b0-b7 (channel 4)
  607     # - d11 = b0-b7
  608     VLD1.8 {d9}, [ip:64]!
  609 
  610     # q5 = b0:7 - b_zero_point
  611     # - d10 = vb0123 (channel 4)
  612     # - d11 = vb4567 (channel 4)
  613     VSUBL.U8 q4, d9, d15
  614 
  615     # vacc0x0123 += vb0123 * va0[4]
  616     VMLAL.S16 q8, d8, d1[0]
  617     # vacc0x4567 += vb4567 * va0[4]
  618     VMLAL.S16 q9, d9, d1[0]
  619 
  620     # vacc1x0123 += vb0123 * va1[4]
  621     VMLAL.S16 q10, d8, d3[0]
  622     # vacc1x4567 += vb4567 * va1[4]
  623     VMLAL.S16 q11, d9, d3[0]
  624 
  625     # vacc2x0123 += vb0123 * va2[4]
  626     VMLAL.S16 q12, d8, d5[0]
  627     # vacc2x4567 += vb4567 * va2[4]
  628     VMLAL.S16 q13, d9, d5[0]
  629 
  630     # vacc3x0123 += vb0123 * va3[4]
  631     VMLAL.S16 q14, d8, d7[0]
  632     # vacc3x4567 += vb4567 * va3[4]
  633     VMLAL.S16 q15, d9, d7[0]
  634 
  635     ### Channel 5 ###
  636     CMP r2, -16
  637     BLO 2f
  638 
  639     # Load b0-b7 (channel 5)
  640     # - d13 = b0-b7
  641     VLD1.8 {d11}, [ip:64]!
  642 
  643     # q5 = b0:7 - b_zero_point
  644     # - d10 = vb0123 (channel 5)
  645     # - d11 = vb4567 (channel 5)
  646     VSUBL.U8 q5, d11, d15
  647 
  648     # vacc0x0123 += vb0123 * va0[5]
  649     VMLAL.S16 q8, d10, d1[1]
  650     # vacc0x4567 += vb4567 * va0[5]
  651     VMLAL.S16 q9, d11, d1[1]
  652 
  653     # vacc1x0123 += vb0123 * va1[5]
  654     VMLAL.S16 q10, d10, d3[1]
  655     # vacc1x4567 += vb4567 * va1[5]
  656     VMLAL.S16 q11, d11, d3[1]
  657 
  658     # vacc2x0123 += vb0123 * va2[5]
  659     VMLAL.S16 q12, d10, d5[1]
  660     # vacc2x4567 += vb4567 * va2[5]
  661     VMLAL.S16 q13, d11, d5[1]
  662 
  663     # vacc3x0123 += vb0123 * va3[5]
  664     VMLAL.S16 q14, d10, d7[1]
  665     # vacc3x4567 += vb4567 * va3[5]
  666     VMLAL.S16 q15, d11, d7[1]
  667 
  668     ### Channel 6 ###
  669     BLS 2f
  670 
  671     # Load b0-b7 (channel 6)
  672     # - d9 = b0-b7
  673     VLD1.8 {d9}, [ip:64]
  674 
  675     # q4 = b0:7 - b_zero_point
  676     # - d8 = vb0123 (channel 6)
  677     # - d9 = vb4567 (channel 6)
  678     VSUBL.U8 q4, d9, d15
  679 
  680     # vacc0x0123 += vb0123 * va0[6]
  681     VMLAL.S16 q8, d8, d1[2]
  682     # vacc0x4567 += vb4567 * va0[6]
  683     VMLAL.S16 q9, d9, d1[2]
  684 
  685     # vacc1x0123 += vb0123 * va1[6]
  686     VMLAL.S16 q10, d8, d3[2]
  687     # vacc1x4567 += vb4567 * va1[6]
  688     VMLAL.S16 q11, d9, d3[2]
  689 
  690     # vacc2x0123 += vb0123 * va2[6]
  691     VMLAL.S16 q12, d8, d5[2]
  692 
  693     # vacc2x4567 += vb4567 * va2[6]
  694     VMLAL.S16 q13, d9, d5[2]
  695 
  696     # vacc3x0123 += vb0123 * va3[6]
  697     VMLAL.S16 q14, d8, d7[2]
  698     # vacc3x4567 += vb4567 * va3[6]
  699     VMLAL.S16 q15, d9, d7[2]
  700 
  701     .p2align 4
  702 2:
  703     # Load requantization_scale:
  704     # - d12 = requantization_scale
  705     VLD1.32 {d12, d13}, [r8]!
  706     # Load vfmax:
  707     VLD1.32 {d10[], d11[]}, [r7]!
  708     VLD1.32 {d4, d5}, [r8]
  709     # Load vfmin:
  710     VLD1.32 {d8[], d9[]}, [r7]!
  711     # Load vfmagic:
  712     VLD1.32 {d0[], d1[]}, [r7]!
  713     # Load vimagic:
  714     VLD1.32 {d2[], d3[]}, [r7]!
  715 
  716     # Moved here to hide load latency on d14
  717     VCVT.F32.S32 q8, q8
  718     VCVT.F32.S32 q9, q9
  719     VCVT.F32.S32 q10, q10
  720     VCVT.F32.S32 q11, q11
  721     VCVT.F32.S32 q12, q12
  722     VCVT.F32.S32 q13, q13
  723     VCVT.F32.S32 q14, q14
  724     VCVT.F32.S32 q15, q15
  725 
  726     VMUL.F32 q8, q8, q6
  727     VMUL.F32 q9, q9, q2
  728     VMUL.F32 q10, q10, q6
  729     VMUL.F32 q11, q11, q2
  730     VMUL.F32 q12, q12, q6
  731     VMUL.F32 q13, q13, q2
  732     VMUL.F32 q14, q14, q6
  733     VMUL.F32 q15, q15, q2
  734 
  735     VMIN.F32 q8, q8, q5
  736     VMIN.F32 q9, q9, q5
  737     VMIN.F32 q10, q10, q5
  738     VMIN.F32 q11, q11, q5
  739     VMIN.F32 q12, q12, q5
  740     VMIN.F32 q13, q13, q5
  741     VMIN.F32 q14, q14, q5
  742     VMIN.F32 q15, q15, q5
  743 
  744     VMAX.F32 q8, q8, q4
  745     VMAX.F32 q9, q9, q4
  746     VMAX.F32 q10, q10, q4
  747     VMAX.F32 q11, q11, q4
  748     VMAX.F32 q12, q12, q4
  749     VMAX.F32 q13, q13, q4
  750     VMAX.F32 q14, q14, q4
  751     VMAX.F32 q15, q15, q4
  752 
  753     VADD.F32 q8, q8, q0
  754     VADD.F32 q9, q9, q0
  755     VADD.F32 q10, q10, q0
  756     VADD.F32 q11, q11, q0
  757     VADD.F32 q12, q12, q0
  758     VADD.F32 q13, q13, q0
  759     VADD.F32 q14, q14, q0
  760     VADD.F32 q15, q15, q0
  761 
  762     # Load c, c_stride:
  763     # - r2 = c
  764     # - r2 = c_stride
  765     LDRD r2, r3, [sp, 96]
  766 
  767     VSUB.S32 q8, q8, q1
  768     VSUB.S32 q9, q9, q1
  769     VSUB.S32 q10, q10, q1
  770     VSUB.S32 q11, q11, q1
  771     VSUB.S32 q12, q12, q1
  772     VSUB.S32 q13, q13, q1
  773     VSUB.S32 q14, q14, q1
  774     VSUB.S32 q15, q15, q1
  775 
  776     ADD r4, r2, r3
  777     VQMOVN.S32 d16,  q8
  778     VQMOVN.S32 d17,  q9
  779     CMP r0, 2
  780     VQMOVN.S32 d18, q10
  781     VQMOVN.S32 d19, q11
  782     MOVLO r4, r2
  783     VQMOVN.S32 d20, q12
  784     VQMOVN.S32 d21, q13
  785     VQMOVN.S32 d22, q14
  786     VQMOVN.S32 d23, q15
  787 
  788 
  789     ADD r5, r4, r3
  790     VQMOVUN.S16 d16,  q8
  791     MOVLS r5, r4
  792     VQMOVUN.S16 d17,  q9
  793     VQMOVUN.S16 d18, q10
  794     CMP r0, 4
  795     ADD r3, r5, r3
  796 
  797     MOVNE r3, r5
  798     CMP r1, 8
  799     VQMOVUN.S16 d19, q11
  800 
  801 
  802     BNE 4f
  803 
  804     VST1.8 {d16}, [r2]
  805     VST1.8 {d17}, [r4]
  806     VST1.8 {d18}, [r5]
  807     VST1.8 {d19}, [r3]
  808 
  809     VPOP {d8-d15}
  810     POP {r4, r5, r6, r7, r8, r9}
  811     BX lr
  812 
  813     .p2align 3
  814 4:
  815     CMP r1, 4
  816     BLO 5f
  817 
  818     VST1.32 {d16[0]}, [r2]!
  819     VST1.32 {d17[0]}, [r4]!
  820     VST1.32 {d18[0]}, [r5]!
  821     VST1.32 {d19[0]}, [r3]!
  822 
  823     SUB r1, 4
  824     VEXT.8 q8, q8, q8, 4
  825     VEXT.8 q9, q9, q9, 4
  826 
  827 5:
  828     CMP r1, 2
  829     BLO 6f
  830 
  831     VST1.16 {d16[0]}, [r2]!
  832     VST1.16 {d17[0]}, [r4]!
  833     VST1.16 {d18[0]}, [r5]!
  834     VST1.16 {d19[0]}, [r3]!
  835 
  836     SUB r1, 2
  837     VEXT.8 q8, q8, q8, 2
  838     VEXT.8 q9, q9, q9, 2
  839 
  840 6:
  841     TEQ r1, 0
  842     BEQ 7f
  843 
  844     VST1.8 {d16[0]}, [r2]
  845     VST1.8 {d17[0]}, [r4]
  846     VST1.8 {d18[0]}, [r5]
  847     VST1.8 {d19[0]}, [r3]
  848 
  849 7:
  850     VPOP {d8-d15}
  851     POP {r4, r5, r6, r7, r8, r9}
  852     BX lr
  853 END_FUNCTION pytorch_q8gemm_ukernel_4x8__aarch32_neon
  854 
  855 #ifdef __ELF__
  856 .section ".note.GNU-stack","",%progbits
  857 #endif