tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

vp9itxfm_neon.S (62533B)


      1 /*
      2 * Copyright (c) 2016 Google Inc.
      3 *
      4 * This file is part of FFmpeg.
      5 *
      6 * FFmpeg is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * FFmpeg is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with FFmpeg; if not, write to the Free Software
     18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19 */
     20 
     21 #include "libavutil/arm/asm.S"
     22 #include "neon.S"
     23 
     24 const itxfm4_coeffs, align=4
     25        .short  11585, 0, 6270, 15137
     26 iadst4_coeffs:
     27        .short  5283, 15212, 9929, 13377
     28 endconst
     29 
     30 const iadst8_coeffs, align=4
     31        .short  16305, 1606, 14449, 7723, 10394, 12665, 4756, 15679
     32 idct_coeffs:
     33        .short  11585, 0, 6270, 15137, 3196, 16069, 13623, 9102
     34        .short  1606, 16305, 12665, 10394, 7723, 14449, 15679, 4756
     35        .short  804, 16364, 12140, 11003, 7005, 14811, 15426, 5520
     36        .short  3981, 15893, 14053, 8423, 9760, 13160, 16207, 2404
     37 endconst
     38 
     39 const iadst16_coeffs, align=4
     40        .short  16364, 804, 15893, 3981, 11003, 12140, 8423, 14053
     41        .short  14811, 7005, 13160, 9760, 5520, 15426, 2404, 16207
     42 endconst
     43 
     44 @ Do four 4x4 transposes, using q registers for the subtransposes that don't
     45 @ need to address the individual d registers.
     46 @ r0,r1 == rq1, r2,r3 == rq1, etc
     47 .macro transpose16_q_4x_4x4 rq0, rq1, rq2, rq3, rq4, rq5, rq6, rq7, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
     48        vtrn.32          \rq0, \rq1
     49        vtrn.32          \rq2, \rq3
     50        vtrn.32          \rq4, \rq5
     51        vtrn.32          \rq6, \rq7
     52        vtrn.16          \r0,  \r1
     53        vtrn.16          \r2,  \r3
     54        vtrn.16          \r4,  \r5
     55        vtrn.16          \r6,  \r7
     56        vtrn.16          \r8,  \r9
     57        vtrn.16          \r10, \r11
     58        vtrn.16          \r12, \r13
     59        vtrn.16          \r14, \r15
     60 .endm
     61 
     62 @ out1 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
     63 @ out2 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
     64 @ in/out are d registers
     65 .macro mbutterfly0 out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4, neg=0
     66        vadd.s16        \tmpd1, \in1,  \in2
     67        vsub.s16        \tmpd2, \in1,  \in2
     68        vmull.s16       \tmpq3, \tmpd1, d0[0]
     69        vmull.s16       \tmpq4, \tmpd2, d0[0]
     70 .if \neg > 0
     71        vneg.s32        \tmpq3, \tmpq3
     72 .endif
     73        vrshrn.s32      \out1, \tmpq3, #14
     74        vrshrn.s32      \out2, \tmpq4, #14
     75 .endm
     76 
     77 @ Same as mbutterfly0 above, but treating the input in in2 as zero,
     78 @ writing the same output into both out1 and out2.
     79 .macro mbutterfly0_h out1, out2, in1, in2, tmpd1, tmpd2, tmpq3, tmpq4
     80        vmull.s16       \tmpq3, \in1, d0[0]
     81        vrshrn.s32      \out1,  \tmpq3, #14
     82        vrshrn.s32      \out2,  \tmpq3, #14
     83 .endm
     84 
     85 @ out1,out2 = ((in1 + in2) * d0[0] + (1 << 13)) >> 14
     86 @ out3,out4 = ((in1 - in2) * d0[0] + (1 << 13)) >> 14
     87 @ Same as mbutterfly0, but with input being 2 q registers, output
     88 @ being 4 d registers.
     89 @ This can do with either 4 or 6 temporary q registers.
     90 .macro dmbutterfly0 out1, out2, out3, out4, in1, in2, tmpq1, tmpq2, tmpd11, tmpd12, tmpd21, tmpd22, tmpq3, tmpq4, tmpq5, tmpq6
     91        vadd.s16        \tmpq1, \in1,  \in2
     92        vsub.s16        \tmpq2, \in1,  \in2
     93        vmull.s16       \tmpq3, \tmpd11, d0[0]
     94        vmull.s16       \tmpq4, \tmpd12, d0[0]
     95 .ifb \tmpq5
     96        vrshrn.s32      \out1, \tmpq3, #14
     97        vrshrn.s32      \out2, \tmpq4, #14
     98        vmull.s16       \tmpq3, \tmpd21, d0[0]
     99        vmull.s16       \tmpq4, \tmpd22, d0[0]
    100        vrshrn.s32      \out3, \tmpq3, #14
    101        vrshrn.s32      \out4, \tmpq4, #14
    102 .else
    103        vmull.s16       \tmpq5, \tmpd21, d0[0]
    104        vmull.s16       \tmpq6, \tmpd22, d0[0]
    105        vrshrn.s32      \out1, \tmpq3, #14
    106        vrshrn.s32      \out2, \tmpq4, #14
    107        vrshrn.s32      \out3, \tmpq5, #14
    108        vrshrn.s32      \out4, \tmpq6, #14
    109 .endif
    110 .endm
    111 
    112 @ out1 = in1 * coef1 - in2 * coef2
    113 @ out2 = in1 * coef2 + in2 * coef1
    114 @ out are 2 q registers, in are 2 d registers
    115 .macro mbutterfly_l out1, out2, in1, in2, coef1, coef2
    116        vmull.s16       \out1, \in1, \coef1
    117        vmlsl.s16       \out1, \in2, \coef2
    118        vmull.s16       \out2, \in1, \coef2
    119        vmlal.s16       \out2, \in2, \coef1
    120 .endm
    121 
    122 @ out1,out2 = in1,in2 * coef1 - in3,in4 * coef2
    123 @ out3,out4 = in1,in2 * coef2 + in3,in4 * coef1
    124 @ out are 4 q registers, in are 4 d registers
    125 .macro dmbutterfly_l out1, out2, out3, out4, in1, in2, in3, in4, coef1, coef2
    126        vmull.s16       \out1, \in1, \coef1
    127        vmull.s16       \out2, \in2, \coef1
    128        vmull.s16       \out3, \in1, \coef2
    129        vmull.s16       \out4, \in2, \coef2
    130        vmlsl.s16       \out1, \in3, \coef2
    131        vmlsl.s16       \out2, \in4, \coef2
    132        vmlal.s16       \out3, \in3, \coef1
    133        vmlal.s16       \out4, \in4, \coef1
    134 .endm
    135 
    136 @ inout1 = (inout1 * coef1 - inout2 * coef2 + (1 << 13)) >> 14
    137 @ inout2 = (inout1 * coef2 + inout2 * coef1 + (1 << 13)) >> 14
    138 @ inout are 2 d registers, tmp are 2 q registers
    139 .macro mbutterfly inout1, inout2, coef1, coef2, tmp1, tmp2, neg=0
    140        mbutterfly_l    \tmp1, \tmp2, \inout1, \inout2, \coef1, \coef2
    141 .if \neg > 0
    142        vneg.s32        \tmp2, \tmp2
    143 .endif
    144        vrshrn.s32      \inout1, \tmp1,  #14
    145        vrshrn.s32      \inout2, \tmp2,  #14
    146 .endm
    147 
    148 @ Same as mbutterfly above, but treating the input in inout2 as zero
    149 .macro mbutterfly_h1 inout1, inout2, coef1, coef2, tmp1, tmp2
    150        vmull.s16       \tmp1,   \inout1, \coef1
    151        vmull.s16       \tmp2,   \inout1, \coef2
    152        vrshrn.s32      \inout1, \tmp1,   #14
    153        vrshrn.s32      \inout2, \tmp2,   #14
    154 .endm
    155 
    156 @ Same as mbutterfly above, but treating the input in inout1 as zero
    157 .macro mbutterfly_h2 inout1, inout2, coef1, coef2, tmp1, tmp2
    158        vmull.s16       \tmp1,   \inout2, \coef2
    159        vmull.s16       \tmp2,   \inout2, \coef1
    160        vneg.s32        \tmp1,   \tmp1
    161        vrshrn.s32      \inout2, \tmp2,   #14
    162        vrshrn.s32      \inout1, \tmp1,   #14
    163 .endm
    164 
    165 @ inout1,inout2 = (inout1,inout2 * coef1 - inout3,inout4 * coef2 + (1 << 13)) >> 14
    166 @ inout3,inout4 = (inout1,inout2 * coef2 + inout3,inout4 * coef1 + (1 << 13)) >> 14
    167 @ inout are 4 d registers, tmp are 4 q registers
    168 .macro dmbutterfly inout1, inout2, inout3, inout4, coef1, coef2, tmp1, tmp2, tmp3, tmp4
    169        dmbutterfly_l   \tmp1, \tmp2, \tmp3, \tmp4, \inout1, \inout2, \inout3, \inout4, \coef1, \coef2
    170        vrshrn.s32      \inout1, \tmp1,  #14
    171        vrshrn.s32      \inout2, \tmp2,  #14
    172        vrshrn.s32      \inout3, \tmp3,  #14
    173        vrshrn.s32      \inout4, \tmp4,  #14
    174 .endm
    175 
    176 @ out1 = in1 + in2
    177 @ out2 = in1 - in2
    178 .macro butterfly out1, out2, in1, in2
    179        vadd.s16        \out1, \in1, \in2
    180        vsub.s16        \out2, \in1, \in2
    181 .endm
    182 
    183 @ out1 = in1 - in2
    184 @ out2 = in1 + in2
    185 .macro butterfly_r out1, out2, in1, in2
    186        vsub.s16        \out1, \in1, \in2
    187        vadd.s16        \out2, \in1, \in2
    188 .endm
    189 
    190 @ out1 = (in1 + in2 + (1 << 13)) >> 14
    191 @ out2 = (in1 - in2 + (1 << 13)) >> 14
    192 @ out are 2 d registers, in are 2 q registers, tmp are 2 q registers
    193 .macro butterfly_n out1, out2, in1, in2, tmp1, tmp2
    194        vadd.s32        \tmp1, \in1, \in2
    195        vsub.s32        \tmp2, \in1, \in2
    196        vrshrn.s32      \out1, \tmp1,  #14
    197        vrshrn.s32      \out2, \tmp2,  #14
    198 .endm
    199 
    200 @ out1,out2 = (in1,in2 + in3,in4 + (1 << 13)) >> 14
    201 @ out3,out4 = (in1,in2 - in3,in4 + (1 << 13)) >> 14
    202 @ out are 4 d registers, in are 4 q registers, tmp are 4 q registers
    203 .macro dbutterfly_n out1, out2, out3, out4, in1, in2, in3, in4, tmp1, tmp2, tmp3, tmp4
    204        vadd.s32        \tmp1, \in1, \in3
    205        vadd.s32        \tmp2, \in2, \in4
    206        vsub.s32        \tmp3, \in1, \in3
    207        vsub.s32        \tmp4, \in2, \in4
    208        vrshrn.s32      \out1, \tmp1,  #14
    209        vrshrn.s32      \out2, \tmp2,  #14
    210        vrshrn.s32      \out3, \tmp3,  #14
    211        vrshrn.s32      \out4, \tmp4,  #14
    212 .endm
    213 
    214 
    215 .macro iwht4 c0, c1, c2, c3
    216        vadd.i16        \c0,  \c0,  \c1
    217        vsub.i16        d17,  \c2,  \c3
    218        vsub.i16        d16,  \c0,  d17
    219        vshr.s16        d16,  d16,  #1
    220        vsub.i16        \c2,  d16,  \c1
    221        vsub.i16        \c1,  d16,  \c3
    222        vadd.i16        \c3,  d17,  \c2
    223        vsub.i16        \c0,  \c0,  \c1
    224 .endm
    225 
    226 .macro idct4 c0, c1, c2, c3
    227        vmull.s16       q13,  \c1,  d0[3]
    228        vmull.s16       q11,  \c1,  d0[2]
    229        vadd.i16        d16,  \c0,  \c2
    230        vsub.i16        d17,  \c0,  \c2
    231        vmlal.s16       q13,  \c3,  d0[2]
    232        vmull.s16       q9,   d16,  d0[0]
    233        vmull.s16       q10,  d17,  d0[0]
    234        vmlsl.s16       q11,  \c3,  d0[3]
    235        vrshrn.s32      d26,  q13,  #14
    236        vrshrn.s32      d18,  q9,   #14
    237        vrshrn.s32      d20,  q10,  #14
    238        vrshrn.s32      d22,  q11,  #14
    239        vadd.i16        \c0,  d18,  d26
    240        vsub.i16        \c3,  d18,  d26
    241        vadd.i16        \c1,  d20,  d22
    242        vsub.i16        \c2,  d20,  d22
    243 .endm
    244 
    245 .macro iadst4 c0, c1, c2, c3
    246        vmull.s16       q10,  \c0,  d1[0]
    247        vmlal.s16       q10,  \c2,  d1[1]
    248        vmlal.s16       q10,  \c3,  d1[2]
    249        vmull.s16       q11,  \c0,  d1[2]
    250        vmlsl.s16       q11,  \c2,  d1[0]
    251        vsub.s16        \c0,  \c0,  \c2
    252        vmlsl.s16       q11,  \c3,  d1[1]
    253        vadd.s16        \c0,  \c0,  \c3
    254        vmull.s16       q13,  \c1,  d1[3]
    255        vmull.s16       q12,  \c0,  d1[3]
    256        vadd.s32        q14,  q10,  q13
    257        vadd.s32        q1,   q11,  q13
    258        vrshrn.s32      \c0,  q14,  #14
    259        vadd.s32        q10,  q10,  q11
    260        vrshrn.s32      \c1,  q1,   #14
    261        vsub.s32        q10,  q10,  q13
    262        vrshrn.s32      \c2,  q12,  #14
    263        vrshrn.s32      \c3,  q10,  #14
    264 .endm
    265 
    266 @ The public functions in this file have got the following signature:
    267 @ void itxfm_add(uint8_t *dst, ptrdiff_t stride, int16_t *block, int eob);
    268 
    269 .macro itxfm_func4x4 txfm1, txfm2
    270 function ff_vp9_\txfm1\()_\txfm2\()_4x4_add_neon, export=1
    271 .ifc \txfm1,\txfm2
    272 .ifc \txfm1,idct
    273        movrel          r12, itxfm4_coeffs
    274        vld1.16         {d0}, [r12,:64]
    275 .endif
    276 .ifc \txfm1,iadst
    277        movrel          r12, iadst4_coeffs
    278        vld1.16         {d1}, [r12,:64]
    279 .endif
    280 .else
    281        movrel          r12, itxfm4_coeffs
    282        vld1.16         {q0}, [r12,:128]
    283 .endif
    284 
    285        vmov.i16        q15, #0
    286 .ifc \txfm1\()_\txfm2,idct_idct
    287        cmp             r3,  #1
    288        bne             1f
    289        @ DC-only for idct/idct
    290        vld1.16         {d4[]},   [r2,:16]
    291        vmull.s16       q2,  d4,  d0[0]
    292        vrshrn.s32      d4,  q2,  #14
    293        vmull.s16       q2,  d4,  d0[0]
    294        vrshrn.s32      d4,  q2,  #14
    295        vst1.16         {d30[0]}, [r2,:16]
    296        vdup.16         q2,  d4[0]
    297        vmov            q3,  q2
    298        b               2f
    299 .endif
    300 
    301 1:
    302        vld1.16         {d4-d7},  [r2,:128]
    303        vst1.16         {q15}, [r2,:128]!
    304 
    305 .ifc \txfm1,iwht
    306        vshr.s16        q2,  q2,  #2
    307        vshr.s16        q3,  q3,  #2
    308 .endif
    309 
    310        \txfm1\()4      d4,  d5,  d6,  d7
    311 
    312        vst1.16         {q15}, [r2,:128]!
    313        @ Transpose 4x4 with 16 bit elements
    314        vtrn.16         d4,  d5
    315        vtrn.16         d6,  d7
    316        vtrn.32         q2,  q3
    317 
    318        \txfm2\()4      d4,  d5,  d6,  d7
    319 2:
    320        vld1.32         {d0[]},   [r0,:32], r1
    321        vld1.32         {d0[1]},  [r0,:32], r1
    322 .ifnc \txfm1,iwht
    323        vrshr.s16       q2,  q2,  #4
    324        vrshr.s16       q3,  q3,  #4
    325 .endif
    326        vaddw.u8        q2,  q2,  d0
    327        vld1.32         {d1[]},   [r0,:32], r1
    328        vld1.32         {d1[1]},  [r0,:32], r1
    329        vqmovun.s16     d0,  q2
    330        sub             r0,  r0,  r1, lsl #2
    331 
    332        vaddw.u8        q3,  q3,  d1
    333        vst1.32         {d0[0]},  [r0,:32], r1
    334        vqmovun.s16     d1,  q3
    335 
    336        vst1.32         {d0[1]},  [r0,:32], r1
    337        vst1.32         {d1[0]},  [r0,:32], r1
    338        vst1.32         {d1[1]},  [r0,:32], r1
    339 
    340        bx              lr
    341 endfunc
    342 .endm
    343 
    344 itxfm_func4x4 idct,  idct
    345 itxfm_func4x4 iadst, idct
    346 itxfm_func4x4 idct,  iadst
    347 itxfm_func4x4 iadst, iadst
    348 itxfm_func4x4 iwht,  iwht
    349 
    350 
    351 .macro idct8
    352        dmbutterfly0    d16, d17, d24, d25, q8,  q12, q2, q4, d4, d5, d8, d9, q3, q2, q5, q4 @ q8 = t0a, q12 = t1a
    353        dmbutterfly     d20, d21, d28, d29, d0[2], d0[3], q2,  q3,  q4,  q5 @ q10 = t2a, q14 = t3a
    354        dmbutterfly     d18, d19, d30, d31, d1[0], d1[1], q2,  q3,  q4,  q5 @ q9  = t4a, q15 = t7a
    355        dmbutterfly     d26, d27, d22, d23, d1[2], d1[3], q2,  q3,  q4,  q5 @ q13 = t5a, q11 = t6a
    356 
    357        butterfly       q2,  q14, q8,  q14 @ q2 = t0, q14 = t3
    358        butterfly       q3,  q10, q12, q10 @ q3 = t1, q10 = t2
    359        butterfly       q4,  q13, q9,  q13 @ q4 = t4, q13 = t5a
    360        butterfly       q5,  q11, q15, q11 @ q5 = t7, q11 = t6a
    361 
    362        butterfly       q8,  q15, q2,  q5  @ q8 = out[0], q15 = out[7]
    363 
    364        dmbutterfly0    d4,  d5,  d10, d11, q11, q13, q9,  q13, d18, d19, d26, d27, q2,  q5, q11, q12 @ q2 = t6, q5 = t5
    365 
    366        butterfly       q11, q12, q14, q4  @ q11 = out[3], q12 = out[4]
    367        butterfly       q9,  q14, q3,  q2  @ q9 = out[1],  q14 = out[6]
    368        butterfly_r     q13, q10, q10, q5  @ q13 = out[5], q10 = out[2]
    369 .endm
    370 
    371 .macro iadst8
    372        dmbutterfly_l   q4,  q5,  q2,  q3,  d30, d31, d16, d17, d2[1], d2[0] @ q4,q5  = t1a, q2,q3 = t0a
    373        dmbutterfly_l   q8,  q15, q6,  q7,  d22, d23, d24, d25, d3[1], d3[0] @ q8,q15 = t5a, q6,q7 = t4a
    374 
    375        dbutterfly_n    d22, d23, d4,  d5,  q2,  q3,  q6,  q7,  q11, q12, q2,  q3 @ q11 = t0, q2 = t4
    376 
    377        dbutterfly_n    d24, d25, d6,  d7,  q4,  q5,  q8,  q15, q12, q3,  q6,  q7 @ q12 = t1, q3 = t5
    378 
    379        dmbutterfly_l   q6,  q7,  q4,  q5,  d26, d27, d20, d21, d2[3], d2[2] @ q6,q7 = t3a, q4,q5 = t2a
    380        dmbutterfly_l   q10, q13, q8,  q15, d18, d19, d28, d29, d3[3], d3[2] @ q10,q13 = t7a, q8,q15 = t6a
    381 
    382        dbutterfly_n    d18, d19, d8,  d9,  q4,  q5,  q8,  q15, q9,  q14, q4, q5 @ q9 = t2, q4 = t6
    383        dbutterfly_n    d16, d17, d12, d13, q6,  q7,  q10, q13, q8,  q15, q6, q7 @ q8 = t3, q6 = t7
    384 
    385        butterfly       q15, q12, q12, q8 @ q15 = -out[7], q12 = t3
    386        vneg.s16        q15, q15          @ q15 = out[7]
    387        butterfly       q8,  q9,  q11, q9 @ q8 = out[0], q9 = t2
    388 
    389        dmbutterfly_l   q10, q11, q5,  q7,  d4,  d5,  d6,  d7,  d0[2], d0[3] @ q10,q11 = t5a, q5,q7 = t4a
    390        dmbutterfly_l   q2,  q3,  q13, q14, d12, d13, d8,  d9,  d0[3], d0[2] @ q2,q3 = t6a, q13,q14 = t7a
    391 
    392        dbutterfly_n    d28, d29, d8,  d9,  q10, q11, q13, q14, q4,  q6,  q10, q11 @ q14 = out[6], q4 = t7
    393 
    394        dmbutterfly0    d22, d23, d24, d25, q9,  q12, q6, q13, d12, d13, d26, d27, q9, q10 @ q11 = -out[3], q12 = out[4]
    395        vneg.s16        q11, q11      @ q11 = out[3]
    396 
    397        dbutterfly_n    d18, d19, d4,  d5,  q5,  q7,  q2,  q3,  q9, q10, q2,  q3 @ q9 = -out[1], q2 = t6
    398        vneg.s16        q9,  q9       @ q9 = out[1]
    399 
    400        dmbutterfly0    d20, d21, d26, d27, q2,  q4,  q3, q5,  d6,  d7,  d10, d11, q6,  q7 @ q10 = out[2], q13 = -out[5]
    401        vneg.s16        q13, q13      @ q13 = out[5]
    402 .endm
    403 
    404 
    405 .macro itxfm_func8x8 txfm1, txfm2
    406 function ff_vp9_\txfm1\()_\txfm2\()_8x8_add_neon, export=1
    407        @ Push q4-q7 if iadst is used, idct requires
    408        @ a few scratch registers less, so only push q4-q5
    409        @ if only idct is involved.
    410        @ The iadst also uses a few coefficients from
    411        @ idct, so those always need to be loaded.
    412 .ifc \txfm1\()_\txfm2,idct_idct
    413        movrel          r12, idct_coeffs
    414        vpush           {q4-q5}
    415 .else
    416        movrel          r12, iadst8_coeffs
    417        vld1.16         {q1}, [r12,:128]!
    418        vpush           {q4-q7}
    419 .endif
    420        vld1.16         {q0}, [r12,:128]
    421 
    422        vmov.i16        q2, #0
    423        vmov.i16        q3, #0
    424 
    425 .ifc \txfm1\()_\txfm2,idct_idct
    426        cmp             r3,  #1
    427        bne             1f
    428        @ DC-only for idct/idct
    429        vld1.16         {d16[]}, [r2,:16]
    430        vmull.s16       q8,  d16, d0[0]
    431        vrshrn.s32      d16, q8,  #14
    432        vmull.s16       q8,  d16, d0[0]
    433        vrshrn.s32      d16, q8,  #14
    434        vdup.16         q8,  d16[0]
    435        vmov            q9,  q8
    436        vmov            q10, q8
    437        vmov            q11, q8
    438        vmov            q12, q8
    439        vmov            q13, q8
    440        vmov            q14, q8
    441        vmov            q15, q8
    442        vst1.16         {d4[0]}, [r2,:16]
    443        b               2f
    444 .endif
    445 1:
    446        vld1.16         {q8-q9},    [r2,:128]!
    447        vld1.16         {q10-q11},  [r2,:128]!
    448        vld1.16         {q12-q13},  [r2,:128]!
    449        vld1.16         {q14-q15},  [r2,:128]!
    450        sub             r2,  r2,  #128
    451        vst1.16         {q2-q3}, [r2,:128]!
    452        vst1.16         {q2-q3}, [r2,:128]!
    453        vst1.16         {q2-q3}, [r2,:128]!
    454        vst1.16         {q2-q3}, [r2,:128]!
    455 
    456        \txfm1\()8
    457 
    458        @ Transpose 8x8 with 16 bit elements
    459        vswp            d17, d24
    460        vswp            d19, d26
    461        vswp            d21, d28
    462        vswp            d23, d30
    463        transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
    464 
    465        \txfm2\()8
    466 2:
    467        mov             r3,  r0
    468        @ Add into the destination
    469        vld1.8          {d4},  [r0,:64], r1
    470        vrshr.s16       q8,  q8,  #5
    471        vld1.8          {d5},  [r0,:64], r1
    472        vrshr.s16       q9,  q9,  #5
    473        vld1.8          {d6},  [r0,:64], r1
    474        vrshr.s16       q10, q10, #5
    475        vaddw.u8        q8,  q8,  d4
    476        vld1.8          {d7},  [r0,:64], r1
    477        vrshr.s16       q11, q11, #5
    478        vaddw.u8        q9,  q9,  d5
    479        vld1.8          {d8},  [r0,:64], r1
    480        vrshr.s16       q12, q12, #5
    481        vaddw.u8        q10, q10, d6
    482        vqmovun.s16     d4,  q8
    483        vld1.8          {d9},  [r0,:64], r1
    484        vrshr.s16       q13, q13, #5
    485        vaddw.u8        q11, q11, d7
    486        vqmovun.s16     d5,  q9
    487        vld1.8          {d10}, [r0,:64], r1
    488        vrshr.s16       q14, q14, #5
    489        vaddw.u8        q12, q12, d8
    490        vqmovun.s16     d6,  q10
    491        vld1.8          {d11}, [r0,:64], r1
    492        vrshr.s16       q15, q15, #5
    493        vaddw.u8        q13, q13, d9
    494        vqmovun.s16     d7,  q11
    495 
    496 
    497        vst1.8          {d4},  [r3,:64], r1
    498        vaddw.u8        q14, q14, d10
    499        vst1.8          {d5},  [r3,:64], r1
    500        vqmovun.s16     d8,  q12
    501        vst1.8          {d6},  [r3,:64], r1
    502        vaddw.u8        q15, q15, d11
    503        vst1.8          {d7},  [r3,:64], r1
    504        vqmovun.s16     d9,  q13
    505        vst1.8          {d8},  [r3,:64], r1
    506        vqmovun.s16     d10, q14
    507        vst1.8          {d9},  [r3,:64], r1
    508        vqmovun.s16     d11, q15
    509 
    510        vst1.8          {d10}, [r3,:64], r1
    511        vst1.8          {d11}, [r3,:64], r1
    512 
    513 .ifc \txfm1\()_\txfm2,idct_idct
    514        vpop            {q4-q5}
    515 .else
    516        vpop            {q4-q7}
    517 .endif
    518        bx              lr
    519 endfunc
    520 .endm
    521 
    522 itxfm_func8x8 idct,  idct
    523 itxfm_func8x8 iadst, idct
    524 .ltorg
    525 itxfm_func8x8 idct,  iadst
    526 itxfm_func8x8 iadst, iadst
    527 
    528 
    529 function idct16x16_dc_add_neon
    530        movrel          r12, idct_coeffs
    531        vld1.16         {d0}, [r12,:64]
    532 
    533        vmov.i16        q2,  #0
    534 
    535        vld1.16         {d16[]}, [r2,:16]
    536        vmull.s16       q8,  d16, d0[0]
    537        vrshrn.s32      d16, q8,  #14
    538        vmull.s16       q8,  d16, d0[0]
    539        vrshrn.s32      d16, q8,  #14
    540        vdup.16         q8,  d16[0]
    541        vst1.16         {d4[0]}, [r2,:16]
    542 
    543        vrshr.s16       q8,  q8,  #6
    544 
    545        mov             r3,  r0
    546        mov             r12, #16
    547 1:
    548        @ Loop to add the constant from q8 into all 16x16 outputs
    549        subs            r12, r12, #2
    550        vld1.8          {q2},  [r0,:128], r1
    551        vaddw.u8        q10, q8,  d4
    552        vld1.8          {q3},  [r0,:128], r1
    553        vaddw.u8        q11, q8,  d5
    554        vaddw.u8        q12, q8,  d6
    555        vaddw.u8        q13, q8,  d7
    556        vqmovun.s16     d4,  q10
    557        vqmovun.s16     d5,  q11
    558        vqmovun.s16     d6,  q12
    559        vst1.8          {q2},  [r3,:128], r1
    560        vqmovun.s16     d7,  q13
    561        vst1.8          {q3},  [r3,:128], r1
    562        bne             1b
    563 
    564        bx              lr
    565 endfunc
    566 .ltorg
    567 
    568 .macro idct16_end
    569        butterfly       d18, d7,  d4,  d7                @ d18 = t0a,  d7  = t7a
    570        butterfly       d19, d22, d5,  d22               @ d19 = t1a,  d22 = t6
    571        butterfly       d4,  d26, d20, d26               @ d4  = t2a,  d26 = t5
    572        butterfly       d5,  d6,  d28, d6                @ d5  = t3a,  d6  = t4
    573        butterfly       d20, d28, d16, d24               @ d20 = t8a,  d28 = t11a
    574        butterfly       d24, d21, d23, d21               @ d24 = t9,   d21 = t10
    575        butterfly       d23, d27, d25, d27               @ d23 = t14,  d27 = t13
    576        butterfly       d25, d29, d29, d17               @ d25 = t15a, d29 = t12a
    577 
    578        mbutterfly0     d27, d21, d27, d21, d16, d30, q8, q15 @ d27 = t13a, d21 = t10a
    579        mbutterfly0     d29, d28, d29, d28, d16, d30, q8, q15 @ d29 = t12,  d28 = t11
    580 
    581        vswp            d27, d29                         @ d27 = t12, d29 = t13a
    582        vswp            d28, d27                         @ d28 = t12, d27 = t11
    583        butterfly       d16, d31, d18, d25               @ d16 = out[0], d31 = out[15]
    584        butterfly       d17, d30, d19, d23               @ d17 = out[1], d30 = out[14]
    585        butterfly_r     d25, d22, d22, d24               @ d25 = out[9], d22 = out[6]
    586        butterfly       d23, d24, d7,  d20               @ d23 = out[7], d24 = out[8]
    587        butterfly       d18, d29, d4,  d29               @ d18 = out[2], d29 = out[13]
    588        butterfly       d19, d28, d5,  d28               @ d19 = out[3], d28 = out[12]
    589        vmov            d4,  d21                         @ d4  = t10a
    590        butterfly       d20, d27, d6,  d27               @ d20 = out[4], d27 = out[11]
    591        butterfly       d21, d26, d26, d4                @ d21 = out[5], d26 = out[10]
    592        bx              lr
    593 .endm
    594 
    595 function idct16
    596        mbutterfly0     d16, d24, d16, d24, d4, d6,  q2,  q3 @ d16 = t0a,  d24 = t1a
    597        mbutterfly      d20, d28, d0[2], d0[3], q2,  q3  @ d20 = t2a,  d28 = t3a
    598        mbutterfly      d18, d30, d1[0], d1[1], q2,  q3  @ d18 = t4a,  d30 = t7a
    599        mbutterfly      d26, d22, d1[2], d1[3], q2,  q3  @ d26 = t5a,  d22 = t6a
    600        mbutterfly      d17, d31, d2[0], d2[1], q2,  q3  @ d17 = t8a,  d31 = t15a
    601        mbutterfly      d25, d23, d2[2], d2[3], q2,  q3  @ d25 = t9a,  d23 = t14a
    602        mbutterfly      d21, d27, d3[0], d3[1], q2,  q3  @ d21 = t10a, d27 = t13a
    603        mbutterfly      d29, d19, d3[2], d3[3], q2,  q3  @ d29 = t11a, d19 = t12a
    604 
    605        butterfly       d4,  d28, d16, d28               @ d4  = t0,   d28 = t3
    606        butterfly       d5,  d20, d24, d20               @ d5  = t1,   d20 = t2
    607        butterfly       d6,  d26, d18, d26               @ d6  = t4,   d26 = t5
    608        butterfly       d7,  d22, d30, d22               @ d7  = t7,   d22 = t6
    609        butterfly       d16, d25, d17, d25               @ d16 = t8,   d25 = t9
    610        butterfly       d24, d21, d29, d21               @ d24 = t11,  d21 = t10
    611        butterfly       d17, d27, d19, d27               @ d17 = t12,  d27 = t13
    612        butterfly       d29, d23, d31, d23               @ d29 = t15,  d23 = t14
    613 
    614        mbutterfly0     d22, d26, d22, d26, d18, d30, q9,  q15  @ d22 = t6a, d26 = t5a
    615        mbutterfly      d23, d25, d0[2], d0[3], q9,  q15        @ d23 = t9a,  d25 = t14a
    616        mbutterfly      d27, d21, d0[2], d0[3], q9,  q15, neg=1 @ d27 = t13a, d21 = t10a
    617        idct16_end
    618 endfunc
    619 
    620 function idct16_half
    621        mbutterfly0_h   d16, d24, d16, d24, d4, d6,  q2,  q3 @ d16 = t0a,  d24 = t1a
    622        mbutterfly_h1   d20, d28, d0[2], d0[3], q2,  q3  @ d20 = t2a,  d28 = t3a
    623        mbutterfly_h1   d18, d30, d1[0], d1[1], q2,  q3  @ d18 = t4a,  d30 = t7a
    624        mbutterfly_h2   d26, d22, d1[2], d1[3], q2,  q3  @ d26 = t5a,  d22 = t6a
    625        mbutterfly_h1   d17, d31, d2[0], d2[1], q2,  q3  @ d17 = t8a,  d31 = t15a
    626        mbutterfly_h2   d25, d23, d2[2], d2[3], q2,  q3  @ d25 = t9a,  d23 = t14a
    627        mbutterfly_h1   d21, d27, d3[0], d3[1], q2,  q3  @ d21 = t10a, d27 = t13a
    628        mbutterfly_h2   d29, d19, d3[2], d3[3], q2,  q3  @ d29 = t11a, d19 = t12a
    629 
    630        butterfly       d4,  d28, d16, d28               @ d4  = t0,   d28 = t3
    631        butterfly       d5,  d20, d24, d20               @ d5  = t1,   d20 = t2
    632        butterfly       d6,  d26, d18, d26               @ d6  = t4,   d26 = t5
    633        butterfly       d7,  d22, d30, d22               @ d7  = t7,   d22 = t6
    634        butterfly       d16, d25, d17, d25               @ d16 = t8,   d25 = t9
    635        butterfly       d24, d21, d29, d21               @ d24 = t11,  d21 = t10
    636        butterfly       d17, d27, d19, d27               @ d17 = t12,  d27 = t13
    637        butterfly       d29, d23, d31, d23               @ d29 = t15,  d23 = t14
    638 
    639        mbutterfly0     d22, d26, d22, d26, d18, d30, q9,  q15  @ d22 = t6a, d26 = t5a
    640        mbutterfly      d23, d25, d0[2], d0[3], q9,  q15        @ d23 = t9a,  d25 = t14a
    641        mbutterfly      d27, d21, d0[2], d0[3], q9,  q15, neg=1 @ d27 = t13a, d21 = t10a
    642        idct16_end
    643 endfunc
    644 
    645 function idct16_quarter
    646        vmull.s16       q12, d19, d3[3]
    647        vmull.s16       q2,  d17, d2[0]
    648        vmull.s16       q3,  d18, d1[1]
    649        vmull.s16       q15, d18, d1[0]
    650        vneg.s32        q12, q12
    651        vmull.s16       q14, d17, d2[1]
    652        vmull.s16       q13, d19, d3[2]
    653        vmull.s16       q11, d16, d0[0]
    654        vrshrn.s32      d24, q12, #14
    655        vrshrn.s32      d16, q2,  #14
    656        vrshrn.s32      d7,  q3,  #14
    657        vrshrn.s32      d6,  q15, #14
    658        vrshrn.s32      d29, q14, #14
    659        vrshrn.s32      d17, q13, #14
    660        vrshrn.s32      d28, q11, #14
    661 
    662        mbutterfly_l    q10, q11, d17, d24, d0[2], d0[3]
    663        mbutterfly_l    q9,  q15, d29, d16, d0[2], d0[3]
    664        vneg.s32        q11, q11
    665        vrshrn.s32      d27, q10, #14
    666        vrshrn.s32      d21, q11, #14
    667        vrshrn.s32      d23, q9,  #14
    668        vrshrn.s32      d25, q15, #14
    669        vmov            d4,  d28
    670        vmov            d5,  d28
    671        mbutterfly0     d22, d26, d7,  d6,  d18, d30, q9,  q15
    672        vmov            d20, d28
    673        idct16_end
    674 endfunc
    675 
    676 function iadst16
    677        movrel          r12, iadst16_coeffs
    678        vld1.16         {q0-q1}, [r12,:128]
    679 
    680        mbutterfly_l    q3,  q2,  d31, d16, d0[1], d0[0] @ q3  = t1,   q2  = t0
    681        mbutterfly_l    q5,  q4,  d23, d24, d1[1], d1[0] @ q5  = t9,   q4  = t8
    682        butterfly_n     d31, d24, q3,  q5,  q6,  q5      @ d31 = t1a,  d24 = t9a
    683        mbutterfly_l    q7,  q6,  d29, d18, d0[3], d0[2] @ q7  = t3,   q6  = t2
    684        butterfly_n     d16, d23, q2,  q4,  q3,  q4      @ d16 = t0a,  d23 = t8a
    685 
    686        mbutterfly_l    q3,  q2,  d21, d26, d1[3], d1[2] @ q3  = t11,  q2  = t10
    687        butterfly_n     d29, d26, q7,  q3,  q4,  q3      @ d29 = t3a,  d26 = t11a
    688        mbutterfly_l    q5,  q4,  d27, d20, d2[1], d2[0] @ q5  = t5,   q4  = t4
    689        butterfly_n     d18, d21, q6,  q2,  q3,  q2      @ d18 = t2a,  d21 = t10a
    690 
    691        mbutterfly_l    q7,  q6,  d19, d28, d3[1], d3[0] @ q7  = t13,  q6  = t12
    692        butterfly_n     d20, d28, q5,  q7,  q2,  q7      @ d20 = t5a,  d28 = t13a
    693        mbutterfly_l    q3,  q2,  d25, d22, d2[3], d2[2] @ q3  = t7,   q2  = t6
    694        butterfly_n     d27, d19, q4,  q6,  q5,  q6      @ d27 = t4a,  d19 = t12a
    695 
    696        mbutterfly_l    q5,  q4,  d17, d30, d3[3], d3[2] @ q5  = t15,  q4  = t14
    697        movrel          r12, idct_coeffs
    698        vld1.16         {q0}, [r12,:128]
    699        butterfly_n     d22, d30, q3,  q5,  q6,  q5      @ d22 = t7a,  d30 = t15a
    700        mbutterfly_l    q7,  q6,  d23, d24, d1[0], d1[1] @ q7  = t9,   q6  = t8
    701        butterfly_n     d25, d17, q2,  q4,  q3,  q4      @ d25 = t6a,  d17 = t14a
    702 
    703        mbutterfly_l    q2,  q3,  d28, d19, d1[1], d1[0] @ q2  = t12,  q3  = t13
    704        butterfly_n     d23, d19, q6,  q2,  q4,  q2      @ d23 = t8a,  d19 = t12a
    705        mbutterfly_l    q5,  q4,  d21, d26, d1[2], d1[3] @ q5  = t11,  q4  = t10
    706        butterfly_r     d4,  d27, d16, d27               @ d4  = t4,   d27 = t0
    707        butterfly_n     d24, d28, q7,  q3,  q6,  q3      @ d24 = t9a,  d28 = t13a
    708 
    709        mbutterfly_l    q6,  q7,  d30, d17, d1[3], d1[2] @ q6  = t14,  q7  = t15
    710        butterfly_r     d5,  d20, d31, d20               @ d5  = t5,   d20 = t1
    711        butterfly_n     d21, d17, q4,  q6,  q3,  q6      @ d21 = t10a, d17 = t14a
    712        butterfly_n     d26, d30, q5,  q7,  q4,  q7      @ d26 = t11a, d30 = t15a
    713 
    714        butterfly_r     d6,  d25, d18, d25               @ d6  = t6,   d25 = t2
    715        butterfly_r     d7,  d22, d29, d22               @ d7  = t7,   d22 = t3
    716 
    717        mbutterfly_l    q5,  q4,  d19, d28, d0[2], d0[3] @ q5  = t13,  q4  = t12
    718        mbutterfly_l    q6,  q7,  d30, d17, d0[3], d0[2] @ q6  = t14,  q7  = t15
    719 
    720        butterfly_n     d18, d30, q4,  q6,  q8,  q6      @ d18 = out[2],   d30 = t14a
    721        butterfly_n     d29, d17, q5,  q7,  q6,  q7      @ d29 = -out[13], d17 = t15a
    722        vneg.s16        d29, d29                         @ d29 = out[13]
    723 
    724        mbutterfly_l    q5,  q4,  d4,  d5,  d0[2], d0[3] @ q5  = t5a,  q4  = t4a
    725        mbutterfly_l    q6,  q7,  d7,  d6,  d0[3], d0[2] @ q6  = t6a,  q7  = t7a
    726 
    727        butterfly       d2,  d6,  d27, d25               @ d2 = out[0], d6 = t2a
    728        butterfly       d3,  d7,  d23, d21               @ d3 =-out[1], d7 = t10
    729 
    730        butterfly_n     d19, d31, q4,  q6,  q2,  q4      @ d19 = -out[3],  d31 = t6
    731        vneg.s16        d19, d19                         @ d19 = out[3]
    732        butterfly_n     d28, d16, q5,  q7,  q2,  q5      @ d28 = out[12],  d16 = t7
    733 
    734        butterfly       d5,  d8,  d20, d22               @ d5 =-out[15],d8 = t3a
    735        butterfly       d4,  d9,  d24, d26               @ d4 = out[14],d9 = t11
    736 
    737        mbutterfly0     d23, d24, d6,  d8,  d10, d11, q6,  q7, 1 @ d23 = out[7], d24 = out[8]
    738        mbutterfly0     d20, d27, d16, d31, d10, d11, q6,  q7    @ d20 = out[4], d27 = out[11]
    739        mbutterfly0     d22, d25, d9,  d7,  d10, d11, q6,  q7    @ d22 = out[6], d25 = out[9]
    740        mbutterfly0     d21, d26, d30, d17, d10, d11, q6,  q7, 1 @ d21 = out[5], d26 = out[10]
    741 
    742        vneg.s16        d31, d5                          @ d31 = out[15]
    743        vneg.s16        d17, d3                          @ d17 = out[1]
    744 
    745        vmov            d16, d2
    746        vmov            d30, d4
    747        bx              lr
    748 endfunc
    749 
    750 .macro load_add_store coef0, coef1, coef2, coef3
    751        vrshr.s16       \coef0, \coef0, #6
    752        vrshr.s16       \coef1, \coef1, #6
    753 
    754        vld1.32         {d4[]},   [r0,:32], r1
    755        vld1.32         {d4[1]},  [r3,:32], r1
    756        vrshr.s16       \coef2, \coef2, #6
    757        vrshr.s16       \coef3, \coef3, #6
    758        vld1.32         {d5[]},   [r0,:32], r1
    759        vld1.32         {d5[1]},  [r3,:32], r1
    760        vaddw.u8        \coef0, \coef0, d4
    761        vld1.32         {d6[]},   [r0,:32], r1
    762        vld1.32         {d6[1]},  [r3,:32], r1
    763        vaddw.u8        \coef1, \coef1, d5
    764        vld1.32         {d7[]},   [r0,:32], r1
    765        vld1.32         {d7[1]},  [r3,:32], r1
    766 
    767        vqmovun.s16     d4,  \coef0
    768        vqmovun.s16     d5,  \coef1
    769        sub             r0,  r0,  r1, lsl #2
    770        sub             r3,  r3,  r1, lsl #2
    771        vaddw.u8        \coef2, \coef2, d6
    772        vaddw.u8        \coef3, \coef3, d7
    773        vst1.32         {d4[0]},  [r0,:32], r1
    774        vst1.32         {d4[1]},  [r3,:32], r1
    775        vqmovun.s16     d6,  \coef2
    776        vst1.32         {d5[0]},  [r0,:32], r1
    777        vst1.32         {d5[1]},  [r3,:32], r1
    778        vqmovun.s16     d7,  \coef3
    779 
    780        vst1.32         {d6[0]},  [r0,:32], r1
    781        vst1.32         {d6[1]},  [r3,:32], r1
    782        vst1.32         {d7[0]},  [r0,:32], r1
    783        vst1.32         {d7[1]},  [r3,:32], r1
    784 .endm
    785 
    786 .macro itxfm16_1d_funcs txfm
    787 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
    788 @ transpose into a horizontal 16x4 slice and store.
    789 @ r0 = dst (temp buffer)
    790 @ r1 = slice offset
    791 @ r2 = src
    792 function \txfm\()16_1d_4x16_pass1_neon
    793        push            {lr}
    794 
    795        mov             r12, #32
    796        vmov.s16        q2,  #0
    797 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
    798        vld1.16         {d\i}, [r2,:64]
    799        vst1.16         {d4},  [r2,:64], r12
    800 .endr
    801 
    802        bl              \txfm\()16
    803 
    804        @ Do four 4x4 transposes. Originally, d16-d31 contain the
    805        @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
    806        @ contain the transposed 4x4 blocks.
    807        transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
    808 
    809        @ Store the transposed 4x4 blocks horizontally.
    810        cmp             r1,  #12
    811        beq             1f
    812 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
    813        vst1.16         {d\i}, [r0,:64]!
    814 .endr
    815        pop             {pc}
    816 1:
    817        @ Special case: For the last input column (r1 == 12),
    818        @ which would be stored as the last row in the temp buffer,
    819        @ don't store the first 4x4 block, but keep it in registers
    820        @ for the first slice of the second pass (where it is the
    821        @ last 4x4 block).
    822        add             r0,  r0,  #8
    823        vst1.16         {d20}, [r0,:64]!
    824        vst1.16         {d24}, [r0,:64]!
    825        vst1.16         {d28}, [r0,:64]!
    826        add             r0,  r0,  #8
    827        vst1.16         {d21}, [r0,:64]!
    828        vst1.16         {d25}, [r0,:64]!
    829        vst1.16         {d29}, [r0,:64]!
    830        add             r0,  r0,  #8
    831        vst1.16         {d22}, [r0,:64]!
    832        vst1.16         {d26}, [r0,:64]!
    833        vst1.16         {d30}, [r0,:64]!
    834        add             r0,  r0,  #8
    835        vst1.16         {d23}, [r0,:64]!
    836        vst1.16         {d27}, [r0,:64]!
    837        vst1.16         {d31}, [r0,:64]!
    838        vmov            d28, d16
    839        vmov            d29, d17
    840        vmov            d30, d18
    841        vmov            d31, d19
    842        pop             {pc}
    843 endfunc
    844 
    845 @ Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it,
    846 @ load the destination pixels (from a similar 4x16 slice), add and store back.
    847 @ r0 = dst
    848 @ r1 = dst stride
    849 @ r2 = src (temp buffer)
    850 @ r3 = slice offset
    851 function \txfm\()16_1d_4x16_pass2_neon
    852        push            {lr}
    853        mov             r12, #32
    854 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
    855        vld1.16         {d\i}, [r2,:64], r12
    856 .endr
    857        cmp             r3,  #0
    858        beq             1f
    859 .irp i, 28, 29, 30, 31
    860        vld1.16         {d\i}, [r2,:64], r12
    861 .endr
    862 1:
    863 
    864        add             r3,  r0,  r1
    865        lsl             r1,  r1,  #1
    866        bl              \txfm\()16
    867 
    868        load_add_store  q8,  q9,  q10, q11
    869        load_add_store  q12, q13, q14, q15
    870 
    871        pop             {pc}
    872 endfunc
    873 .endm
    874 
    875 itxfm16_1d_funcs idct
    876 itxfm16_1d_funcs iadst
    877 
    878 @ This is the minimum eob value for each subpartition, in increments of 4
    879 const min_eob_idct_idct_16, align=4
    880        .short  0, 10, 38, 89
    881 endconst
    882 
    883 .macro itxfm_func16x16 txfm1, txfm2
    884 function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1
    885 .ifc \txfm1\()_\txfm2,idct_idct
    886        cmp             r3,  #1
    887        beq             idct16x16_dc_add_neon
    888 .endif
    889        push            {r4-r8,lr}
    890 .ifnc \txfm1\()_\txfm2,idct_idct
    891        vpush           {q4-q7}
    892 .endif
    893 
    894        @ Align the stack, allocate a temp buffer
    895 T       mov             r7,  sp
    896 T       and             r7,  r7,  #15
    897 A       and             r7,  sp,  #15
    898        add             r7,  r7,  #512
    899        sub             sp,  sp,  r7
    900 
    901        mov             r4,  r0
    902        mov             r5,  r1
    903        mov             r6,  r2
    904 
    905 .ifc \txfm1,idct
    906        movrel          r12, idct_coeffs
    907        vld1.16         {q0-q1}, [r12,:128]
    908 .endif
    909 
    910 .ifc \txfm1\()_\txfm2,idct_idct
    911        cmp             r3,  #10
    912        ble             idct16x16_quarter_add_neon
    913        cmp             r3,  #38
    914        ble             idct16x16_half_add_neon
    915 
    916        movrel          r8,  min_eob_idct_idct_16 + 2
    917 .endif
    918 
    919 .irp i, 0, 4, 8, 12
    920        add             r0,  sp,  #(\i*32)
    921 .ifc \txfm1\()_\txfm2,idct_idct
    922 .if \i > 0
    923        ldrh_post       r1,  r8,  #2
    924        cmp             r3,  r1
    925        it              le
    926        movle           r1,  #(16 - \i)/4
    927        ble             1f
    928 .endif
    929 .endif
    930        mov             r1,  #\i
    931        add             r2,  r6,  #(\i*2)
    932        bl              \txfm1\()16_1d_4x16_pass1_neon
    933 .endr
    934 
    935 .ifc \txfm1\()_\txfm2,idct_idct
    936        b               3f
    937 1:
    938        @ For all-zero slices in pass 1, set d28-d31 to zero, for the in-register
    939        @ passthrough of coefficients to pass 2 and clear the end of the temp buffer
    940        vmov.i16        q14, #0
    941        vmov.i16        q15, #0
    942 2:
    943        subs            r1,  r1,  #1
    944 .rept 4
    945        vst1.16         {q14-q15}, [r0,:128]!
    946 .endr
    947        bne             2b
    948 3:
    949 .endif
    950 
    951 .ifc \txfm1\()_\txfm2,iadst_idct
    952        movrel          r12, idct_coeffs
    953        vld1.16         {q0-q1}, [r12,:128]
    954 .endif
    955 .irp i, 0, 4, 8, 12
    956        add             r0,  r4,  #(\i)
    957        mov             r1,  r5
    958        add             r2,  sp,  #(\i*2)
    959        mov             r3,  #\i
    960        bl              \txfm2\()16_1d_4x16_pass2_neon
    961 .endr
    962 
    963        add             sp,  sp,  r7
    964 .ifnc \txfm1\()_\txfm2,idct_idct
    965        vpop            {q4-q7}
    966 .endif
    967        pop             {r4-r8,pc}
    968 endfunc
    969 .endm
    970 
    971 itxfm_func16x16 idct,  idct
    972 itxfm_func16x16 iadst, idct
    973 itxfm_func16x16 idct,  iadst
    974 itxfm_func16x16 iadst, iadst
    975 .ltorg
    976 
    977 function idct16_1d_4x16_pass1_quarter_neon
    978        push            {lr}
    979        mov             r12, #32
    980        vmov.s16        q2, #0
    981 .irp i, 16, 17, 18, 19
    982        vld1.16         {d\i}, [r2,:64]
    983        vst1.16         {d4},  [r2,:64], r12
    984 .endr
    985 
    986        bl              idct16_quarter
    987 
    988        @ Do four 4x4 transposes. Originally, d16-d31 contain the
    989        @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
    990        @ contain the transposed 4x4 blocks.
    991        transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
    992 
    993        @ Store the transposed 4x4 blocks horizontally.
    994        @ The first 4x4 block is kept in registers for the second pass,
    995        @ store the rest in the temp buffer.
    996        add             r0,  r0,  #8
    997        vst1.16         {d20}, [r0,:64]!
    998        vst1.16         {d24}, [r0,:64]!
    999        vst1.16         {d28}, [r0,:64]!
   1000        add             r0,  r0,  #8
   1001        vst1.16         {d21}, [r0,:64]!
   1002        vst1.16         {d25}, [r0,:64]!
   1003        vst1.16         {d29}, [r0,:64]!
   1004        add             r0,  r0,  #8
   1005        vst1.16         {d22}, [r0,:64]!
   1006        vst1.16         {d26}, [r0,:64]!
   1007        vst1.16         {d30}, [r0,:64]!
   1008        add             r0,  r0,  #8
   1009        vst1.16         {d23}, [r0,:64]!
   1010        vst1.16         {d27}, [r0,:64]!
   1011        vst1.16         {d31}, [r0,:64]!
   1012        pop             {pc}
   1013 endfunc
   1014 
   1015 function idct16_1d_4x16_pass2_quarter_neon
   1016        push            {lr}
   1017        @ Only load the top 4 lines, and only do it for the later slices.
   1018        @ For the first slice, d16-d19 is kept in registers from the first pass.
   1019        cmp             r3,  #0
   1020        beq             1f
   1021        mov             r12, #32
   1022 .irp i, 16, 17, 18, 19
   1023        vld1.16         {d\i}, [r2,:64], r12
   1024 .endr
   1025 1:
   1026 
   1027        add             r3,  r0,  r1
   1028        lsl             r1,  r1,  #1
   1029        bl              idct16_quarter
   1030 
   1031        load_add_store  q8,  q9,  q10, q11
   1032        load_add_store  q12, q13, q14, q15
   1033 
   1034        pop             {pc}
   1035 endfunc
   1036 
   1037 function idct16_1d_4x16_pass1_half_neon
   1038        push            {lr}
   1039        mov             r12, #32
   1040        vmov.s16        q2, #0
   1041 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
   1042        vld1.16         {d\i}, [r2,:64]
   1043        vst1.16         {d4},  [r2,:64], r12
   1044 .endr
   1045 
   1046        bl              idct16_half
   1047 
   1048        @ Do four 4x4 transposes. Originally, d16-d31 contain the
   1049        @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
   1050        @ contain the transposed 4x4 blocks.
   1051        transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
   1052 
   1053        @ Store the transposed 4x4 blocks horizontally.
   1054        cmp             r1,  #4
   1055        beq             1f
   1056 .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31
   1057        vst1.16         {d\i}, [r0,:64]!
   1058 .endr
   1059        pop             {pc}
   1060 1:
   1061        @ Special case: For the second input column (r1 == 4),
   1062        @ which would be stored as the second row in the temp buffer,
   1063        @ don't store the first 4x4 block, but keep it in registers
   1064        @ for the first slice of the second pass (where it is the
   1065        @ second 4x4 block).
   1066        add             r0,  r0,  #8
   1067        vst1.16         {d20}, [r0,:64]!
   1068        vst1.16         {d24}, [r0,:64]!
   1069        vst1.16         {d28}, [r0,:64]!
   1070        add             r0,  r0,  #8
   1071        vst1.16         {d21}, [r0,:64]!
   1072        vst1.16         {d25}, [r0,:64]!
   1073        vst1.16         {d29}, [r0,:64]!
   1074        add             r0,  r0,  #8
   1075        vst1.16         {d22}, [r0,:64]!
   1076        vst1.16         {d26}, [r0,:64]!
   1077        vst1.16         {d30}, [r0,:64]!
   1078        add             r0,  r0,  #8
   1079        vst1.16         {d23}, [r0,:64]!
   1080        vst1.16         {d27}, [r0,:64]!
   1081        vst1.16         {d31}, [r0,:64]!
   1082        vmov            d20, d16
   1083        vmov            d21, d17
   1084        vmov            d22, d18
   1085        vmov            d23, d19
   1086        pop             {pc}
   1087 endfunc
   1088 
   1089 function idct16_1d_4x16_pass2_half_neon
   1090        push            {lr}
   1091        mov             r12, #32
   1092        cmp             r3,  #0
   1093 .irp i, 16, 17, 18, 19
   1094        vld1.16         {d\i}, [r2,:64], r12
   1095 .endr
   1096        beq             1f
   1097 .irp i, 20, 21, 22, 23
   1098        vld1.16         {d\i}, [r2,:64], r12
   1099 .endr
   1100 1:
   1101 
   1102        add             r3,  r0,  r1
   1103        lsl             r1,  r1,  #1
   1104        bl              idct16_half
   1105 
   1106        load_add_store  q8,  q9,  q10, q11
   1107        load_add_store  q12, q13, q14, q15
   1108 
   1109        pop             {pc}
   1110 endfunc
   1111 .purgem load_add_store
   1112 
   1113 .macro idct16_partial size
   1114 function idct16x16_\size\()_add_neon
   1115        add             r0,  sp,  #(0*32)
   1116        mov             r1,  #0
   1117        add             r2,  r6,  #(0*2)
   1118        bl              idct16_1d_4x16_pass1_\size\()_neon
   1119 .ifc \size,half
   1120        add             r0,  sp,  #(4*32)
   1121        mov             r1,  #4
   1122        add             r2,  r6,  #(4*2)
   1123        bl              idct16_1d_4x16_pass1_\size\()_neon
   1124 .endif
   1125 .irp i, 0, 4, 8, 12
   1126        add             r0,  r4,  #(\i)
   1127        mov             r1,  r5
   1128        add             r2,  sp,  #(\i*2)
   1129        mov             r3,  #\i
   1130        bl              idct16_1d_4x16_pass2_\size\()_neon
   1131 .endr
   1132 
   1133        add             sp,  sp,  r7
   1134        pop             {r4-r8,pc}
   1135 endfunc
   1136 .endm
   1137 
   1138 idct16_partial quarter
   1139 idct16_partial half
   1140 
   1141 function idct32x32_dc_add_neon
   1142        movrel          r12, idct_coeffs
   1143        vld1.16         {d0}, [r12,:64]
   1144 
   1145        vmov.i16        q2,  #0
   1146 
   1147        vld1.16         {d16[]}, [r2,:16]
   1148        vmull.s16       q8,  d16, d0[0]
   1149        vrshrn.s32      d16, q8,  #14
   1150        vmull.s16       q8,  d16, d0[0]
   1151        vrshrn.s32      d16, q8,  #14
   1152        vdup.16         q8,  d16[0]
   1153        vst1.16         {d4[0]}, [r2,:16]
   1154 
   1155        vrshr.s16       q8,  q8,  #6
   1156 
   1157        mov             r3,  r0
   1158        mov             r12, #32
   1159 1:
   1160        @ Loop to add the constant from q8 into all 32x32 outputs
   1161        subs            r12, r12, #2
   1162        vld1.8          {q0-q1},  [r0,:128], r1
   1163        vaddw.u8        q9,  q8,  d0
   1164        vaddw.u8        q10, q8,  d1
   1165        vld1.8          {q2-q3},  [r0,:128], r1
   1166        vaddw.u8        q11, q8,  d2
   1167        vaddw.u8        q12, q8,  d3
   1168        vaddw.u8        q13, q8,  d4
   1169        vaddw.u8        q14, q8,  d5
   1170        vaddw.u8        q15, q8,  d6
   1171        vqmovun.s16     d0,  q9
   1172        vaddw.u8        q9,  q8,  d7
   1173        vqmovun.s16     d1,  q10
   1174        vqmovun.s16     d2,  q11
   1175        vqmovun.s16     d3,  q12
   1176        vqmovun.s16     d4,  q13
   1177        vqmovun.s16     d5,  q14
   1178        vst1.8          {q0-q1},  [r3,:128], r1
   1179        vqmovun.s16     d6,  q15
   1180        vqmovun.s16     d7,  q9
   1181        vst1.8          {q2-q3},  [r3,:128], r1
   1182        bne             1b
   1183 
   1184        bx              lr
   1185 endfunc
   1186 
   1187 .macro idct32_end
   1188        butterfly       d16, d9,  d8,  d9  @ d16 = t16a, d9  = t19a
   1189        butterfly       d17, d20, d23, d20 @ d17 = t17,  d20 = t18
   1190        butterfly       d18, d10, d11, d10 @ d18 = t23a, d10 = t20a
   1191        butterfly       d19, d21, d22, d21 @ d19 = t22,  d21 = t21
   1192        butterfly       d8,  d28, d28, d30 @ d8  = t24a, d28 = t27a
   1193        butterfly       d23, d26, d25, d26 @ d23 = t25,  d26 = t26
   1194        butterfly       d11, d29, d29, d31 @ d11 = t31a, d29 = t28a
   1195        butterfly       d22, d27, d24, d27 @ d22 = t30,  d27 = t29
   1196 
   1197        mbutterfly      d27, d20, d0[2], d0[3], q12, q15        @ d27 = t18a, d20 = t29a
   1198        mbutterfly      d29, d9,  d0[2], d0[3], q12, q15        @ d29 = t19,  d5  = t28
   1199        mbutterfly      d28, d10, d0[2], d0[3], q12, q15, neg=1 @ d28 = t27,  d6  = t20
   1200        mbutterfly      d26, d21, d0[2], d0[3], q12, q15, neg=1 @ d26 = t26a, d21 = t21a
   1201 
   1202        butterfly       d31, d24, d11, d8  @ d31 = t31,  d24 = t24
   1203        butterfly       d30, d25, d22, d23 @ d30 = t30a, d25 = t25a
   1204        butterfly_r     d23, d16, d16, d18 @ d23 = t23,  d16 = t16
   1205        butterfly_r     d22, d17, d17, d19 @ d22 = t22a, d17 = t17a
   1206        butterfly       d18, d21, d27, d21 @ d18 = t18,  d21 = t21
   1207        butterfly_r     d27, d28, d9,  d28 @ d27 = t27a, d28 = t28a
   1208        butterfly       d8,  d26, d20, d26 @ d8  = t29,  d26 = t26
   1209        butterfly       d19, d20, d29, d10 @ d19 = t19a, d20 = t20
   1210        vmov            d29, d8            @ d29 = t29
   1211 
   1212        mbutterfly0     d27, d20, d27, d20, d8, d10, q4, q5 @ d27 = t27,  d20 = t20
   1213        mbutterfly0     d26, d21, d26, d21, d8, d10, q4, q5 @ d26 = t26a, d21 = t21a
   1214        mbutterfly0     d25, d22, d25, d22, d8, d10, q4, q5 @ d25 = t25,  d22 = t22
   1215        mbutterfly0     d24, d23, d24, d23, d8, d10, q4, q5 @ d24 = t24a, d23 = t23a
   1216        bx              lr
   1217 .endm
   1218 
   1219 function idct32_odd
   1220        mbutterfly      d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a
   1221        mbutterfly      d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a
   1222        mbutterfly      d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a
   1223        mbutterfly      d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a
   1224        mbutterfly      d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a
   1225        mbutterfly      d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a
   1226        mbutterfly      d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a
   1227        mbutterfly      d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a
   1228 
   1229        butterfly       d8,  d24, d16, d24 @ d8  = t16, d24 = t17
   1230        butterfly       d9,  d20, d28, d20 @ d9  = t19, d20 = t18
   1231        butterfly       d10, d26, d18, d26 @ d10 = t20, d26 = t21
   1232        butterfly       d11, d22, d30, d22 @ d11 = t23, d22 = t22
   1233        butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
   1234        butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
   1235        butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
   1236        butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
   1237 
   1238        mbutterfly      d23, d24, d1[0], d1[1], q8, q9        @ d23 = t17a, d24 = t30a
   1239        mbutterfly      d27, d20, d1[0], d1[1], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
   1240        mbutterfly      d21, d26, d1[2], d1[3], q8, q9        @ d21 = t21a, d26 = t26a
   1241        mbutterfly      d25, d22, d1[2], d1[3], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
   1242        idct32_end
   1243 endfunc
   1244 
   1245 function idct32_odd_half
   1246        mbutterfly_h1   d16, d31, d4[0], d4[1], q4, q5 @ d16 = t16a, d31 = t31a
   1247        mbutterfly_h2   d24, d23, d4[2], d4[3], q4, q5 @ d24 = t17a, d23 = t30a
   1248        mbutterfly_h1   d20, d27, d5[0], d5[1], q4, q5 @ d20 = t18a, d27 = t29a
   1249        mbutterfly_h2   d28, d19, d5[2], d5[3], q4, q5 @ d28 = t19a, d19 = t28a
   1250        mbutterfly_h1   d18, d29, d6[0], d6[1], q4, q5 @ d18 = t20a, d29 = t27a
   1251        mbutterfly_h2   d26, d21, d6[2], d6[3], q4, q5 @ d26 = t21a, d21 = t26a
   1252        mbutterfly_h1   d22, d25, d7[0], d7[1], q4, q5 @ d22 = t22a, d25 = t25a
   1253        mbutterfly_h2   d30, d17, d7[2], d7[3], q4, q5 @ d30 = t23a, d17 = t24a
   1254 
   1255        butterfly       d8,  d24, d16, d24 @ d8  = t16, d24 = t17
   1256        butterfly       d9,  d20, d28, d20 @ d9  = t19, d20 = t18
   1257        butterfly       d10, d26, d18, d26 @ d10 = t20, d26 = t21
   1258        butterfly       d11, d22, d30, d22 @ d11 = t23, d22 = t22
   1259        butterfly       d28, d25, d17, d25 @ d28 = t24, d25 = t25
   1260        butterfly       d30, d21, d29, d21 @ d30 = t27, d21 = t26
   1261        butterfly       d29, d23, d31, d23 @ d29 = t31, d23 = t30
   1262        butterfly       d31, d27, d19, d27 @ d31 = t28, d27 = t29
   1263 
   1264        mbutterfly      d23, d24, d1[0], d1[1], q8, q9        @ d23 = t17a, d24 = t30a
   1265        mbutterfly      d27, d20, d1[0], d1[1], q8, q9, neg=1 @ d27 = t29a, d20 = t18a
   1266        mbutterfly      d21, d26, d1[2], d1[3], q8, q9        @ d21 = t21a, d26 = t26a
   1267        mbutterfly      d25, d22, d1[2], d1[3], q8, q9, neg=1 @ d25 = t25a, d22 = t22a
   1268 
   1269        idct32_end
   1270 endfunc
   1271 
   1272 function idct32_odd_quarter
   1273        vmull.s16       q4,  d16, d4[0]
   1274        vmull.s16       q14, d19, d5[3]
   1275        vmull.s16       q15, d16, d4[1]
   1276        vmull.s16       q11, d17, d7[2]
   1277        vmull.s16       q5,  d17, d7[3]
   1278        vmull.s16       q13, d19, d5[2]
   1279        vmull.s16       q10, d18, d6[0]
   1280        vmull.s16       q12, d18, d6[1]
   1281 
   1282        vneg.s32        q14, q14
   1283        vneg.s32        q5,  q5
   1284 
   1285        vrshrn.s32      d8,  q4,  #14
   1286        vrshrn.s32      d9,  q14, #14
   1287        vrshrn.s32      d29, q15, #14
   1288        vrshrn.s32      d28, q11, #14
   1289        vrshrn.s32      d11, q5,  #14
   1290        vrshrn.s32      d31, q13, #14
   1291        vrshrn.s32      d10, q10, #14
   1292        vrshrn.s32      d30, q12, #14
   1293 
   1294        mbutterfly_l    q8,  q9,  d29, d8,  d1[0], d1[1]
   1295        mbutterfly_l    q13, q10, d31, d9,  d1[0], d1[1]
   1296        vrshrn.s32      d23, q8,  #14
   1297        vrshrn.s32      d24, q9,  #14
   1298        vneg.s32        q10, q10
   1299        vrshrn.s32      d27, q13, #14
   1300        vrshrn.s32      d20, q10, #14
   1301        mbutterfly_l    q8,  q9,  d30, d10, d1[2], d1[3]
   1302        vrshrn.s32      d21, q8,  #14
   1303        vrshrn.s32      d26, q9,  #14
   1304        mbutterfly_l    q8,  q9,  d28, d11, d1[2], d1[3]
   1305        vrshrn.s32      d25, q8,  #14
   1306        vneg.s32        q9,  q9
   1307        vrshrn.s32      d22, q9,  #14
   1308 
   1309        idct32_end
   1310 endfunc
   1311 
   1312 .macro idct32_funcs suffix
   1313 @ Do an 32-point IDCT of a 4x32 slice out of a 32x32 matrix.
   1314 @ We don't have register space to do a single pass IDCT of 4x32 though,
   1315 @ but the 32-point IDCT can be decomposed into two 16-point IDCTs;
   1316 @ a normal IDCT16 with every other input component (the even ones, with
   1317 @ each output written twice), followed by a separate 16-point IDCT
   1318 @ of the odd inputs, added/subtracted onto the outputs of the first idct16.
   1319 @ r0 = dst (temp buffer)
   1320 @ r1 = unused
   1321 @ r2 = src
   1322 function idct32_1d_4x32_pass1\suffix\()_neon
   1323        push            {lr}
   1324 
   1325        @ idct16 clobbers q2-q3 (since it doesn't clobber q4-q7 at all
   1326        @ when doing the normal 16x16 idct), so move the idct32_odd coeffs
   1327        @ to q4-q5
   1328        vmov            q4,  q2
   1329        vmov            q5,  q3
   1330 
   1331        @ Double stride of the input, since we only read every other line
   1332        mov             r12, #128
   1333        vmov.s16        d4,  #0
   1334 
   1335        @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
   1336 .ifb \suffix
   1337 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
   1338        vld1.16         {d\i}, [r2,:64]
   1339        vst1.16         {d4},  [r2,:64], r12
   1340 .endr
   1341 .endif
   1342 .ifc \suffix,_quarter
   1343 .irp i, 16, 17, 18, 19
   1344        vld1.16         {d\i}, [r2,:64]
   1345        vst1.16         {d4},  [r2,:64], r12
   1346 .endr
   1347 .endif
   1348 .ifc \suffix,_half
   1349 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
   1350        vld1.16         {d\i}, [r2,:64]
   1351        vst1.16         {d4},  [r2,:64], r12
   1352 .endr
   1353 .endif
   1354 
   1355        bl              idct16\suffix
   1356 
   1357        @ Move the idct32_odd coeffs back into q2-q3 for idct32_odd;
   1358        @ the constants for a vmul with a lane must be in q0-q3.
   1359        vmov            q2,  q4
   1360        vmov            q3,  q5
   1361 
   1362        @ Do four 4x4 transposes. Originally, d16-d31 contain the
   1363        @ 16 rows. Afterwards, d16-d19, d20-d23, d24-d27, d28-d31
   1364        @ contain the transposed 4x4 blocks.
   1365        transpose16_q_4x_4x4 q8,  q9,  q10, q11, q12, q13, q14, q15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31
   1366        @ Store the registers a, b, c, d horizontally, followed
   1367        @ by the same registers d, c, b, a mirrored.
   1368 .macro store_rev a, b, c, d
   1369 .irp i, \a, \b, \c, \d
   1370        vst1.16         {d\i}, [r0,:64]!
   1371        vrev64.16       d\i, d\i
   1372 .endr
   1373 .irp i, \d, \c, \b, \a
   1374        vst1.16         {d\i}, [r0,:64]!
   1375 .endr
   1376 .endm
   1377        store_rev       16, 20, 24, 28
   1378        store_rev       17, 21, 25, 29
   1379        store_rev       18, 22, 26, 30
   1380        store_rev       19, 23, 27, 31
   1381        sub             r0,  r0,  #256
   1382 .purgem store_rev
   1383 
   1384        @ Move r2 back to the start of the input, and move
   1385        @ to the first odd row
   1386 .ifb \suffix
   1387        sub             r2,  r2,  r12, lsl #4
   1388 .endif
   1389 .ifc \suffix,_quarter
   1390        sub             r2,  r2,  r12, lsl #2
   1391 .endif
   1392 .ifc \suffix,_half
   1393        sub             r2,  r2,  r12, lsl #3
   1394 .endif
   1395        add             r2,  r2,  #64
   1396 
   1397        vmov.s16        d8,  #0
   1398        @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
   1399 .ifb \suffix
   1400 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
   1401        vld1.16         {d\i}, [r2,:64]
   1402        vst1.16         {d8},  [r2,:64], r12
   1403 .endr
   1404 .endif
   1405 .ifc \suffix,_quarter
   1406 .irp i, 16, 17, 18, 19
   1407        vld1.16         {d\i}, [r2,:64]
   1408        vst1.16         {d8},  [r2,:64], r12
   1409 .endr
   1410 .endif
   1411 .ifc \suffix,_half
   1412 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
   1413        vld1.16         {d\i}, [r2,:64]
   1414        vst1.16         {d8},  [r2,:64], r12
   1415 .endr
   1416 .endif
   1417 
   1418        bl              idct32_odd\suffix
   1419 
   1420        transpose16_q_4x_4x4 q15, q14, q13, q12, q11, q10, q9,  q8,  d31, d30, d29, d28, d27, d26, d25, d24, d23, d22, d21, d20, d19, d18, d17, d16
   1421 
   1422        @ Store the registers a, b, c, d horizontally,
   1423        @ adding into the output first, and then mirrored, subtracted
   1424        @ from the output.
   1425 .macro store_rev a, b, c, d
   1426 .irp i, \a, \b, \c, \d
   1427        vld1.16         {d8},  [r0,:64]
   1428        vadd.s16        d8,  d8,  d\i
   1429        vst1.16         {d8},  [r0,:64]!
   1430        vrev64.16       d\i, d\i
   1431 .endr
   1432 .irp i, \d, \c, \b, \a
   1433        vld1.16         {d8},  [r0,:64]
   1434        vsub.s16        d8,  d8,  d\i
   1435        vst1.16         {d8},  [r0,:64]!
   1436 .endr
   1437 .endm
   1438 
   1439        store_rev       31, 27, 23, 19
   1440        store_rev       30, 26, 22, 18
   1441        store_rev       29, 25, 21, 17
   1442        store_rev       28, 24, 20, 16
   1443 .purgem store_rev
   1444        pop             {pc}
   1445 endfunc
   1446 .ltorg
   1447 
   1448 @ This is mostly the same as 4x32_pass1, but without the transpose,
   1449 @ and use the source as temp buffer between the two idct passes, and
   1450 @ add into the destination.
   1451 @ r0 = dst
   1452 @ r1 = dst stride
   1453 @ r2 = src (temp buffer)
   1454 function idct32_1d_4x32_pass2\suffix\()_neon
   1455        push            {lr}
   1456        vmov            q4,  q2
   1457        vmov            q5,  q3
   1458 
   1459        mov             r12, #128
   1460        @ d16 = IN(0), d17 = IN(2) ... d31 = IN(30)
   1461 .ifb \suffix
   1462 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
   1463        vld1.16         {d\i}, [r2,:64], r12
   1464 .endr
   1465        sub             r2,  r2,  r12, lsl #4
   1466 .endif
   1467 .ifc \suffix,_quarter
   1468 .irp i, 16, 17, 18, 19
   1469        vld1.16         {d\i}, [r2,:64], r12
   1470 .endr
   1471        sub             r2,  r2,  r12, lsl #2
   1472 .endif
   1473 .ifc \suffix,_half
   1474 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
   1475        vld1.16         {d\i}, [r2,:64], r12
   1476 .endr
   1477        sub             r2,  r2,  r12, lsl #3
   1478 .endif
   1479 
   1480        bl              idct16\suffix
   1481 
   1482        vmov            q2,  q4
   1483        vmov            q3,  q5
   1484 
   1485 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
   1486        vst1.16         {d\i}, [r2,:64], r12
   1487 .endr
   1488 
   1489        sub             r2,  r2,  r12, lsl #4
   1490        add             r2,  r2,  #64
   1491 
   1492        @ d16 = IN(1), d17 = IN(3) ... d31 = IN(31)
   1493 .ifb \suffix
   1494 .irp i, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
   1495        vld1.16         {d\i}, [r2,:64], r12
   1496 .endr
   1497        sub             r2,  r2,  r12, lsl #4
   1498 .endif
   1499 .ifc \suffix,_quarter
   1500 .irp i, 16, 17, 18, 19
   1501        vld1.16         {d\i}, [r2,:64], r12
   1502 .endr
   1503        sub             r2,  r2,  r12, lsl #2
   1504 .endif
   1505 .ifc \suffix,_half
   1506 .irp i, 16, 17, 18, 19, 20, 21, 22, 23
   1507        vld1.16         {d\i}, [r2,:64], r12
   1508 .endr
   1509        sub             r2,  r2,  r12, lsl #3
   1510 .endif
   1511        sub             r2,  r2,  #64
   1512 
   1513        bl              idct32_odd\suffix
   1514 
   1515        mov             r12, #128
   1516 .macro load_acc_store a, b, c, d, neg=0
   1517        vld1.16         {d8},  [r2,:64], r12
   1518        vld1.16         {d9},  [r2,:64], r12
   1519 .if \neg == 0
   1520        vadd.s16        d8,  d8,  d\a
   1521        vld1.16         {d10}, [r2,:64], r12
   1522        vadd.s16        d9,  d9,  d\b
   1523        vld1.16         {d11}, [r2,:64], r12
   1524        vadd.s16        d10, d10, d\c
   1525        vadd.s16        d11, d11, d\d
   1526 .else
   1527        vsub.s16        d8,  d8,  d\a
   1528        vld1.16         {d10}, [r2,:64], r12
   1529        vsub.s16        d9,  d9,  d\b
   1530        vld1.16         {d11}, [r2,:64], r12
   1531        vsub.s16        d10, d10, d\c
   1532        vsub.s16        d11, d11, d\d
   1533 .endif
   1534        vld1.32         {d12[]},  [r0,:32], r1
   1535        vld1.32         {d12[1]}, [r0,:32], r1
   1536        vrshr.s16       q4,  q4,  #6
   1537        vld1.32         {d13[]},  [r0,:32], r1
   1538        vrshr.s16       q5,  q5,  #6
   1539        vld1.32         {d13[1]}, [r0,:32], r1
   1540        sub             r0,  r0,  r1, lsl #2
   1541        vaddw.u8        q4,  q4,  d12
   1542        vaddw.u8        q5,  q5,  d13
   1543        vqmovun.s16     d8,  q4
   1544        vqmovun.s16     d9,  q5
   1545        vst1.32         {d8[0]},  [r0,:32], r1
   1546        vst1.32         {d8[1]},  [r0,:32], r1
   1547        vst1.32         {d9[0]},  [r0,:32], r1
   1548        vst1.32         {d9[1]},  [r0,:32], r1
   1549 .endm
   1550        load_acc_store  31, 30, 29, 28
   1551        load_acc_store  27, 26, 25, 24
   1552        load_acc_store  23, 22, 21, 20
   1553        load_acc_store  19, 18, 17, 16
   1554        sub             r2,  r2,  r12
   1555        neg             r12, r12
   1556        load_acc_store  16, 17, 18, 19, 1
   1557        load_acc_store  20, 21, 22, 23, 1
   1558        load_acc_store  24, 25, 26, 27, 1
   1559        load_acc_store  28, 29, 30, 31, 1
   1560 .purgem load_acc_store
   1561        pop             {pc}
   1562 endfunc
   1563 .endm
   1564 
   1565 idct32_funcs
   1566 idct32_funcs _quarter
   1567 idct32_funcs _half
   1568 
   1569 const min_eob_idct_idct_32, align=4
   1570        .short  0, 9, 34, 70, 135, 240, 336, 448
   1571 endconst
   1572 
   1573 function ff_vp9_idct_idct_32x32_add_neon, export=1
   1574        cmp             r3,  #1
   1575        beq             idct32x32_dc_add_neon
   1576        push            {r4-r8,lr}
   1577        vpush           {q4-q6}
   1578 
   1579        @ Align the stack, allocate a temp buffer
   1580 T       mov             r7,  sp
   1581 T       and             r7,  r7,  #15
   1582 A       and             r7,  sp,  #15
   1583        add             r7,  r7,  #2048
   1584        sub             sp,  sp,  r7
   1585 
   1586        mov             r4,  r0
   1587        mov             r5,  r1
   1588        mov             r6,  r2
   1589 
   1590        movrel          r12, idct_coeffs
   1591        vld1.16         {q0-q1}, [r12,:128]!
   1592        vld1.16         {q2-q3}, [r12,:128]
   1593 
   1594        cmp             r3,  #34
   1595        ble             idct32x32_quarter_add_neon
   1596        cmp             r3,  #135
   1597        ble             idct32x32_half_add_neon
   1598 
   1599        movrel          r8,  min_eob_idct_idct_32 + 2
   1600 
   1601 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
   1602        add             r0,  sp,  #(\i*64)
   1603 .if \i > 0
   1604        ldrh_post       r1,  r8,  #2
   1605        cmp             r3,  r1
   1606        it              le
   1607        movle           r1,  #(32 - \i)/2
   1608        ble             1f
   1609 .endif
   1610        add             r2,  r6,  #(\i*2)
   1611        bl              idct32_1d_4x32_pass1_neon
   1612 .endr
   1613        b               3f
   1614 
   1615 1:
   1616        @ Write zeros to the temp buffer for pass 2
   1617        vmov.i16        q14, #0
   1618        vmov.i16        q15, #0
   1619 2:
   1620        subs            r1,  r1,  #1
   1621 .rept 4
   1622        vst1.16         {q14-q15}, [r0,:128]!
   1623 .endr
   1624        bne             2b
   1625 3:
   1626 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
   1627        add             r0,  r4,  #(\i)
   1628        mov             r1,  r5
   1629        add             r2,  sp,  #(\i*2)
   1630        bl              idct32_1d_4x32_pass2_neon
   1631 .endr
   1632 
   1633        add             sp,  sp,  r7
   1634        vpop            {q4-q6}
   1635        pop             {r4-r8,pc}
   1636 endfunc
   1637 
   1638 .macro idct32_partial size
   1639 function idct32x32_\size\()_add_neon
   1640 .irp i, 0, 4
   1641        add             r0,  sp,  #(\i*64)
   1642 .ifc \size,quarter
   1643 .if \i == 4
   1644        cmp             r3,  #9
   1645        ble             1f
   1646 .endif
   1647 .endif
   1648        add             r2,  r6,  #(\i*2)
   1649        bl              idct32_1d_4x32_pass1_\size\()_neon
   1650 .endr
   1651 
   1652 .ifc \size,half
   1653 .irp i, 8, 12
   1654        add             r0,  sp,  #(\i*64)
   1655 .if \i == 12
   1656        cmp             r3,  #70
   1657        ble             1f
   1658 .endif
   1659        add             r2,  r6,  #(\i*2)
   1660        bl              idct32_1d_4x32_pass1_\size\()_neon
   1661 .endr
   1662 .endif
   1663        b               3f
   1664 
   1665 1:
   1666        @ Write zeros to the temp buffer for pass 2
   1667        vmov.i16        q14, #0
   1668        vmov.i16        q15, #0
   1669 .rept 8
   1670        vst1.16         {q14-q15}, [r0,:128]!
   1671 .endr
   1672 
   1673 3:
   1674 .irp i, 0, 4, 8, 12, 16, 20, 24, 28
   1675        add             r0,  r4,  #(\i)
   1676        mov             r1,  r5
   1677        add             r2,  sp,  #(\i*2)
   1678        bl              idct32_1d_4x32_pass2_\size\()_neon
   1679 .endr
   1680 
   1681        add             sp,  sp,  r7
   1682        vpop            {q4-q6}
   1683        pop             {r4-r8,pc}
   1684 endfunc
   1685 .endm
   1686 
   1687 idct32_partial quarter
   1688 idct32_partial half