Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/dav1d/src/arm/32/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 128 kB image not shown  

Quelle  mc16.S   Sprache: Sparc

 
/*
 * Copyright © 2018, VideoLAN and dav1d authors
 * Copyright © 2018, Janne Grunau
 * Copyright © 2020, Martin Storsjo
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


#include "src/arm/asm.S"
#include "util.S"

#define PREP_BIAS 8192

.macro avg d0, d00, d01, d1, d10, d11
        vld1.16         {q0, q1}, [r2, :128]!
        vld1.16         {q2, q3}, [r3, :128]!
        vqadd.s16       q0,  q0,  q2
        vqadd.s16       q1,  q1,  q3
        vmax.s16        q0,  q0,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
        vmax.s16        q1,  q1,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
        vqsub.s16       q0,  q0,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
        vqsub.s16       q1,  q1,  q12 // -2*PREP_BIAS - 1 << intermediate_bits
        vshl.s16        \d0, q0,  q13 // -(intermediate_bits+1)
        vshl.s16        \d1, q1,  q13 // -(intermediate_bits+1)
.endm

.macro w_avg d0, d00, d01, d1, d10, d11
        vld1.16         {q0, q1}, [r2, :128]!
        vld1.16         {q2, q3}, [r3, :128]!
        // This difference requires a 17 bit range, and all bits are
        // significant for the following multiplication.
        vsubl.s16       \d0, d4,  d0
        vsubl.s16       q0,  d5,  d1
        vsubl.s16       \d1, d6,  d2
        vsubl.s16       q1,  d7,  d3
        vmul.s32        \d0, \d0, q4
        vmul.s32        q0,  q0,  q4
        vmul.s32        \d1, \d1, q4
        vmul.s32        q1,  q1,  q4
        vshr.s32        \d0, \d0, #4
        vshr.s32        q0,  q0,  #4
        vshr.s32        \d1, \d1, #4
        vshr.s32        q1,  q1,  #4
        vaddw.s16       \d0, \d0, d4
        vaddw.s16       q0,  q0,  d5
        vaddw.s16       \d1, \d1, d6
        vaddw.s16       q1,  q1,  d7
        vmovn.i32       \d00, \d0
        vmovn.i32       \d01, q0
        vmovn.i32       \d10, \d1
        vmovn.i32       \d11, q1
        vrshl.s16       \d0, \d0, q13 // -intermediate_bits
        vrshl.s16       \d1, \d1, q13 // -intermediate_bits
        vadd.s16        \d0, \d0, q12 // PREP_BIAS >> intermediate_bits
        vadd.s16        \d1, \d1, q12 // PREP_BIAS >> intermediate_bits
        vmin.s16        \d0, \d0, q15 // bitdepth_max
        vmin.s16        \d1, \d1, q15 // bitdepth_max
        vmax.s16        \d0, \d0, q14 // 0
        vmax.s16        \d1, \d1, q14 // 0
.endm

.macro mask d0, d00, d01, d1, d10, d11
        vld1.8          {q7},     [r6, :128]!
        vld1.16         {q0, q1}, [r2, :128]!
        vneg.s8         q7,  q7
        vld1.16         {q2, q3}, [r3, :128]!
        vmovl.s8        q6,  d14
        vmovl.s8        q7,  d15
        vmovl.s16       q4,  d12
        vmovl.s16       q5,  d13
        vmovl.s16       q6,  d14
        vmovl.s16       q7,  d15
        vsubl.s16       \d0, d4,  d0
        vsubl.s16       q0,  d5,  d1
        vsubl.s16       \d1, d6,  d2
        vsubl.s16       q1,  d7,  d3
        vmul.s32        \d0, \d0, q4
        vmul.s32        q0,  q0,  q5
        vmul.s32        \d1, \d1, q6
        vmul.s32        q1,  q1,  q7
        vshr.s32        \d0, \d0, #6
        vshr.s32        q0,  q0,  #6
        vshr.s32        \d1, \d1, #6
        vshr.s32        q1,  q1,  #6
        vaddw.s16       \d0, \d0, d4
        vaddw.s16       q0,  q0,  d5
        vaddw.s16       \d1, \d1, d6
        vaddw.s16       q1,  q1,  d7
        vmovn.i32       \d00, \d0
        vmovn.i32       \d01, q0
        vmovn.i32       \d10, \d1
        vmovn.i32       \d11, q1
        vrshl.s16       \d0, \d0, q13 // -intermediate_bits
        vrshl.s16       \d1, \d1, q13 // -intermediate_bits
        vadd.s16        \d0, \d0, q12 // PREP_BIAS >> intermediate_bits
        vadd.s16        \d1, \d1, q12 // PREP_BIAS >> intermediate_bits
        vmin.s16        \d0, \d0, q15 // bitdepth_max
        vmin.s16        \d1, \d1, q15 // bitdepth_max
        vmax.s16        \d0, \d0, q14 // 0
        vmax.s16        \d1, \d1, q14 // 0
.endm

.macro bidir_fn type, bdmax
function \type\()_16bpc_neon, export=1
        push            {r4-r7,lr}
        ldrd            r4,  r5,  [sp, #20]
        ldr             r6,  [sp, #28]
        clz             r4,  r4
.ifnc \type, avg
        ldr             r7,  [sp, #32]
        vmov.i16        q14, #0
        vdup.16         q15, r7         // bitdepth_max
.endif
.ifc \type, w_avg
        vpush           {q4}
.endif
.ifc \type, mask
        vpush           {q4-q7}
.endif
        clz             r7,  \bdmax
        sub             r7,  r7,  #18   // intermediate_bits = clz(bitdepth_max) - 18
.ifc \type, avg
        mov             lr,  #1
        movw            r12, #2*PREP_BIAS
        lsl             lr,  lr,  r7    // 1 << intermediate_bits
        neg             r12, r12         // -2*PREP_BIAS
        add             r7,  r7,  #1
        sub             r12, r12, lr    // -2*PREP_BIAS - 1 << intermediate_bits
        neg             r7,  r7         // -(intermediate_bits+1)
        vdup.16         q12, r12         // -2*PREP_BIAS - 1 << intermediate_bits
        vdup.16         q13, r7         // -(intermediate_bits+1)
.else
        mov             r12, #PREP_BIAS
        lsr             r12, r12, r7    // PREP_BIAS >> intermediate_bits
        neg             r7,  r7         // -intermediate_bits
        vdup.16         q12, r12         // PREP_BIAS >> intermediate_bits
        vdup.16         q13, r7         // -intermediate_bits
.endif
.ifc \type, w_avg
        vdup.32         q4,  r6
        vneg.s32        q4,  q4
.endif
        adr             r7,  L(\type\()_tbl)
        sub             r4,  r4,  #24
        \type           q8,  d16, d17, q9,  d18, d19
        ldr             r4,  [r7, r4, lsl #2]
        add             r7,  r7,  r4
        bx              r7

        .align 2
L(\type\()_tbl):
        .word 1280f - L(\type\()_tbl) + CONFIG_THUMB
        .word 640f  - L(\type\()_tbl) + CONFIG_THUMB
        .word 320f  - L(\type\()_tbl) + CONFIG_THUMB
        .word 160f  - L(\type\()_tbl) + CONFIG_THUMB
        .word 80f   - L(\type\()_tbl) + CONFIG_THUMB
        .word 40f   - L(\type\()_tbl) + CONFIG_THUMB

40:
        add             r7,  r0,  r1
        lsl             r1,  r1,  #1
4:
        subs            r5,  r5,  #4
        vst1.16         {d16},  [r0, :64], r1
        vst1.16         {d17},  [r7, :64], r1
        vst1.16         {d18},  [r0, :64], r1
        vst1.16         {d19},  [r7, :64], r1
        ble             0f
        \type           q8,  d16, d17, q9,  d18, d19
        b               4b
80:
        add             r7,  r0,  r1
        lsl             r1,  r1,  #1
8:
        vst1.16         {q8},  [r0, :128], r1
        subs            r5,  r5,  #2
        vst1.16         {q9},  [r7, :128], r1
        ble             0f
        \type           q8,  d16, d17, q9,  d18, d19
        b               8b
160:
16:
        \type           q10, d20, d21, q11, d22, d23
        vst1.16         {q8,  q9},  [r0, :128], r1
        subs            r5,  r5,  #2
        vst1.16         {q10, q11}, [r0, :128], r1
        ble             0f
        \type           q8,  d16, d17, q9,  d18, d19
        b               16b
320:
        add             r7,  r0,  #32
32:
        \type           q10, d20, d21, q11, d22, d23
        vst1.16         {q8,  q9},  [r0, :128], r1
        subs            r5,  r5,  #1
        vst1.16         {q10, q11}, [r7, :128], r1
        ble             0f
        \type           q8,  d16, d17, q9,  d18, d19
        b               32b
640:
        add             r7,  r0,  #32
        mov             r12, #64
        sub             r1,  r1,  #64
64:
        \type           q10, d20, d21, q11, d22, d23
        vst1.16         {q8,  q9},  [r0, :128], r12
        \type           q8,  d16, d17, q9,  d18, d19
        vst1.16         {q10, q11}, [r7, :128], r12
        \type           q10, d20, d21, q11, d22, d23
        vst1.16         {q8,  q9},  [r0, :128], r1
        subs            r5,  r5,  #1
        vst1.16         {q10, q11}, [r7, :128], r1
        ble             0f
        \type           q8,  d16, d17, q9,  d18, d19
        b               64b
1280:
        add             r7,  r0,  #32
        mov             r12, #64
        sub             r1,  r1,  #192
128:
        \type           q10, d20, d21, q11, d22, d23
        vst1.16         {q8,  q9},  [r0, :128], r12
        \type           q8,  d16, d17, q9,  d18, d19
        vst1.16         {q10, q11}, [r7, :128], r12
        \type           q10, d20, d21, q11, d22, d23
        vst1.16         {q8,  q9},  [r0, :128], r12
        \type           q8,  d16, d17, q9,  d18, d19
        vst1.16         {q10, q11}, [r7, :128], r12
        \type           q10, d20, d21, q11, d22, d23
        vst1.16         {q8,  q9},  [r0, :128], r12
        \type           q8,  d16, d17, q9,  d18, d19
        vst1.16         {q10, q11}, [r7, :128], r12
        \type           q10, d20, d21, q11, d22, d23
        vst1.16         {q8,  q9},  [r0, :128], r1
        subs            r5,  r5,  #1
        vst1.16         {q10, q11}, [r7, :128], r1
        ble             0f
        \type           q8,  d16, d17, q9,  d18, d19
        b               128b
0:
.ifc \type, mask
        vpop            {q4-q7}
.endif
.ifc \type, w_avg
        vpop            {q4}
.endif
        pop             {r4-r7,pc}
endfunc
.endm

bidir_fn avg, r6
bidir_fn w_avg, r7
bidir_fn mask, r7


.macro w_mask_fn type
function w_mask_\type\()_16bpc_neon, export=1
        push            {r4-r10,lr}
        vpush           {q4-q7}
        ldrd            r4,  r5,  [sp, #96]
        ldrd            r6,  r7,  [sp, #104]
        ldr             r8,  [sp, #112]
        clz             r9,  r4
        adr             lr,  L(w_mask_\type\()_tbl)
        vdup.16         q15, r8       // bitdepth_max
        sub             r9,  r9,  #24
        clz             r8,  r8       // clz(bitdepth_max)
        ldr             r9,  [lr,  r9,  lsl #2]
        add             r9,  lr,  r9
        sub             r8,  r8,  #12 // sh = intermediate_bits + 6 = clz(bitdepth_max) - 12
        mov             r10, #PREP_BIAS*64
        neg             r8,  r8       // -sh
        movw            r12, #27615   // (64 + 1 - 38)<<mask_sh - 1 - mask_rnd
        vdup.32         q14, r8       // -sh
        vdup.16         q0,  r12
.if \type == 444
        vmov.i8         q1,  #64
.elseif \type == 422
        vdup.8          d4,  r7
        vmov.i8         d2,  #129
        vsub.i16        d2,  d2,  d4
.elseif \type == 420
        vdup.16         q2,  r7
        vmov.i16        q1,  #0x100
        vsub.i16        q1,  q1,  q2
.endif
        add             r12, r0,  r1
        lsl             r1,  r1,  #1
        bx              r9

        .align 2
L(w_mask_\type\()_tbl):
        .word 1280f - L(w_mask_\type\()_tbl) + CONFIG_THUMB
        .word 640f  - L(w_mask_\type\()_tbl) + CONFIG_THUMB
        .word 320f  - L(w_mask_\type\()_tbl) + CONFIG_THUMB
        .word 160f  - L(w_mask_\type\()_tbl) + CONFIG_THUMB
        .word 8f    - L(w_mask_\type\()_tbl) + CONFIG_THUMB
        .word 4f    - L(w_mask_\type\()_tbl) + CONFIG_THUMB

4:
        vld1.16         {q2, q3}, [r2, :128]! // tmp1 (four rows at once)
        vld1.16         {q4, q5}, [r3, :128]! // tmp2 (four rows at once)
        subs            r5,  r5,  #4
        vdup.32         q13, r10       // PREP_BIAS*64
        vabd.s16        q6,  q2,  q4   // abs(tmp1 - tmp2)
        vabd.s16        q7,  q3,  q5
        vsubl.s16       q8,  d8,  d4   // tmp2 - tmp1 (requires 17 bit)
        vsubl.s16       q9,  d9,  d5
        vsubl.s16       q10, d10, d6
        vsubl.s16       q11, d11, d7
        vqsub.u16       q6,  q0,  q6   // 27615 - abs()
        vqsub.u16       q7,  q0,  q7
        vshll.s16       q5,  d7,  #6   // tmp1 << 6
        vshll.s16       q4,  d6,  #6
        vshll.s16       q3,  d5,  #6
        vshll.s16       q2,  d4,  #6
        vshr.u16        q6,  q6,  #10  // 64-m = (27615 - abs()) >> mask_sh
        vshr.u16        q7,  q7,  #10
        vadd.i32        q2,  q2,  q13  // += PREP_BIAS*64
        vadd.i32        q3,  q3,  q13
        vadd.i32        q4,  q4,  q13
        vadd.i32        q5,  q5,  q13
        vmovl.u16       q12, d12
        vmovl.u16       q13, d13
        vmla.i32        q2,  q8,  q12  // (tmp2-tmp1)*(64-m)
        vmovl.u16       q12, d14
        vmla.i32        q3,  q9,  q13
        vmovl.u16       q13, d15
        vmla.i32        q4,  q10, q12
        vmla.i32        q5,  q11, q13
        vrshl.s32       q2,  q2,  q14  // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh
        vrshl.s32       q3,  q3,  q14
        vrshl.s32       q4,  q4,  q14
        vrshl.s32       q5,  q5,  q14
        vqmovun.s32     d4,  q2        // iclip_pixel
        vqmovun.s32     d5,  q3
        vqmovun.s32     d6,  q4
        vqmovun.s32     d7,  q5
        vmin.u16        q2,  q2,  q15  // iclip_pixel
        vmin.u16        q3,  q3,  q15  // iclip_pixel
.if \type == 444
        vmovn.i16       d12, q6        // 64 - m
        vmovn.i16       d13, q7
        vsub.i16        q6,  q1,  q6   // m
        vst1.8          {q6}, [r6, :128]!
.elseif \type == 422
        vpadd.i16       d12, d12, d13  // (64 - m) + (64 - n) (column wise addition)
        vpadd.i16       d13, d14, d15
        vmovn.i16       d12, q6
        vhsub.u8        d12, d2,  d12  // ((129 - sign) - ((64 - m) + (64 - n)) >> 1
        vst1.8          {d12}, [r6, :64]!
.elseif \type == 420
        vadd.i16        d12, d12, d13  // (64 - my1) + (64 - my2) (row wise addition)
        vadd.i16        d13, d14, d15
        vpadd.i16       d12, d12, d13  // (128 - m) + (128 - n) (column wise addition)
        vsub.i16        d12, d2,  d12  // (256 - sign) - ((128 - m) + (128 - n))
        vrshrn.i16      d12, q6,  #2   // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
        vst1.32         {d12[0]}, [r6, :32]!
.endif
        vst1.16         {d4}, [r0,  :64], r1
        vst1.16         {d5}, [r12, :64], r1
        vst1.16         {d6}, [r0,  :64], r1
        vst1.16         {d7}, [r12, :64], r1
        bgt             4b
        vpop            {q4-q7}
        pop             {r4-r10,pc}
8:
        vld1.16         {q2, q3}, [r2, :128]! // tmp1
        vld1.16         {q4, q5}, [r3, :128]! // tmp2
        subs            r5,  r5,  #2
        vdup.32         q13, r10       // PREP_BIAS*64
        vabd.s16        q6,  q2,  q4   // abs(tmp1 - tmp2)
        vabd.s16        q7,  q3,  q5
        vsubl.s16       q8,  d8,  d4   // tmp2 - tmp1 (requires 17 bit)
        vsubl.s16       q9,  d9,  d5
        vsubl.s16       q10, d10, d6
        vsubl.s16       q11, d11, d7
        vqsub.u16       q6,  q0,  q6   // 27615 - abs()
        vqsub.u16       q7,  q0,  q7
        vshll.s16       q5,  d7,  #6   // tmp1 << 6
        vshll.s16       q4,  d6,  #6
        vshll.s16       q3,  d5,  #6
        vshll.s16       q2,  d4,  #6
        vshr.u16        q6,  q6,  #10  // 64-m = (27615 - abs()) >> mask_sh
        vshr.u16        q7,  q7,  #10
        vadd.i32        q2,  q2,  q13  // += PREP_BIAS*64
        vadd.i32        q3,  q3,  q13
        vadd.i32        q4,  q4,  q13
        vadd.i32        q5,  q5,  q13
        vmovl.u16       q12, d12
        vmovl.u16       q13, d13
        vmla.i32        q2,  q8,  q12  // (tmp2-tmp1)*(64-m)
        vmovl.u16       q12, d14
        vmla.i32        q3,  q9,  q13
        vmovl.u16       q13, d15
        vmla.i32        q4,  q10, q12
        vmla.i32        q5,  q11, q13
        vrshl.s32       q2,  q2,  q14  // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh
        vrshl.s32       q3,  q3,  q14
        vrshl.s32       q4,  q4,  q14
        vrshl.s32       q5,  q5,  q14
        vqmovun.s32     d4,  q2        // iclip_pixel
        vqmovun.s32     d5,  q3
        vqmovun.s32     d6,  q4
        vqmovun.s32     d7,  q5
        vmin.u16        q2,  q2,  q15  // iclip_pixel
        vmin.u16        q3,  q3,  q15  // iclip_pixel
.if \type == 444
        vmovn.i16       d12, q6        // 64 - m
        vmovn.i16       d13, q7
        vsub.i16        q6,  q1,  q6   // m
        vst1.8          {q6}, [r6, :128]!
.elseif \type == 422
        vpadd.i16       d12, d12, d13  // (64 - m) + (64 - n) (column wise addition)
        vpadd.i16       d13, d14, d15
        vmovn.i16       d12, q6
        vhsub.u8        d12, d2,  d12  // ((129 - sign) - ((64 - m) + (64 - n)) >> 1
        vst1.8          {d12}, [r6, :64]!
.elseif \type == 420
        vadd.i16        q6,  q6,  q7   // (64 - my1) + (64 - my2) (row wise addition)
        vpadd.i16       d12, d12, d13  // (128 - m) + (128 - n) (column wise addition)
        vsub.i16        d12, d2,  d12  // (256 - sign) - ((128 - m) + (128 - n))
        vrshrn.i16      d12, q6,  #2   // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
        vst1.32         {d12[0]}, [r6, :32]!
.endif
        vst1.16         {q2}, [r0,  :128], r1
        vst1.16         {q3}, [r12, :128], r1
        bgt             8b
        vpop            {q4-q7}
        pop             {r4-r10,pc}
1280:
640:
320:
160:
        sub             r1,  r1,  r4,  lsl #1
.if \type == 444
        add             lr,  r6,  r4
.elseif \type == 422
        add             lr,  r6,  r4,  lsr #1
.endif
        add             r7,  r2,  r4,  lsl #1
        add             r9,  r3,  r4,  lsl #1
161:
        mov             r8,  r4
16:
        vld1.16         {q2}, [r2, :128]! // tmp1
        vld1.16         {q4}, [r3, :128]! // tmp2
        vld1.16         {q3}, [r7, :128]!
        vld1.16         {q5}, [r9, :128]!
        subs            r8,  r8,  #8
        vdup.32         q13, r10       // PREP_BIAS*64
        vabd.s16        q6,  q2,  q4   // abs(tmp1 - tmp2)
        vabd.s16        q7,  q3,  q5
        vsubl.s16       q8,  d8,  d4   // tmp2 - tmp1 (requires 17 bit)
        vsubl.s16       q9,  d9,  d5
        vsubl.s16       q10, d10, d6
        vsubl.s16       q11, d11, d7
        vqsub.u16       q6,  q0,  q6   // 27615 - abs()
        vqsub.u16       q7,  q0,  q7
        vshll.s16       q5,  d7,  #6   // tmp1 << 6
        vshll.s16       q4,  d6,  #6
        vshll.s16       q3,  d5,  #6
        vshll.s16       q2,  d4,  #6
        vshr.u16        q6,  q6,  #10  // 64-m = (27615 - abs()) >> mask_sh
        vshr.u16        q7,  q7,  #10
        vadd.i32        q2,  q2,  q13  // += PREP_BIAS*64
        vadd.i32        q3,  q3,  q13
        vadd.i32        q4,  q4,  q13
        vadd.i32        q5,  q5,  q13
        vmovl.u16       q12, d12
        vmovl.u16       q13, d13
        vmla.i32        q2,  q8,  q12  // (tmp2-tmp1)*(64-m)
        vmovl.u16       q12, d14
        vmla.i32        q3,  q9,  q13
        vmovl.u16       q13, d15
        vmla.i32        q4,  q10, q12
        vmla.i32        q5,  q11, q13
        vrshl.s32       q2,  q2,  q14  // (tmp1<<6 + (tmp2-tmp1)*(64-m) + (1 << (sh-1)) + PREP_BIAS*64) >> sh
        vrshl.s32       q3,  q3,  q14
        vrshl.s32       q4,  q4,  q14
        vrshl.s32       q5,  q5,  q14
        vqmovun.s32     d4,  q2        // iclip_pixel
        vqmovun.s32     d5,  q3
        vqmovun.s32     d6,  q4
        vqmovun.s32     d7,  q5
        vmin.u16        q2,  q2,  q15  // iclip_pixel
        vmin.u16        q3,  q3,  q15  // iclip_pixel
.if \type == 444
        vmovn.i16       d12, q6        // 64 - m
        vmovn.i16       d13, q7
        vsub.i16        q6,  q1,  q6   // m
        vst1.8          {d12}, [r6, :64]!
        vst1.8          {d13}, [lr, :64]!
.elseif \type == 422
        vpadd.i16       d12, d12, d13  // (64 - m) + (64 - n) (column wise addition)
        vpadd.i16       d13, d14, d15
        vmovn.i16       d12, q6
        vhsub.u8        d12, d2,  d12  // ((129 - sign) - ((64 - m) + (64 - n)) >> 1
        vst1.32         {d12[0]}, [r6, :32]!
        vst1.32         {d12[1]}, [lr, :32]!
.elseif \type == 420
        vadd.i16        q6,  q6,  q7   // (64 - my1) + (64 - my2) (row wise addition)
        vpadd.i16       d12, d12, d13  // (128 - m) + (128 - n) (column wise addition)
        vsub.i16        d12, d2,  d12  // (256 - sign) - ((128 - m) + (128 - n))
        vrshrn.i16      d12, q6,  #2   // ((256 - sign) - ((128 - m) + (128 - n)) + 2) >> 2
        vst1.32         {d12[0]}, [r6, :32]!
.endif
        vst1.16         {q2}, [r0,  :128]!
        vst1.16         {q3}, [r12, :128]!
        bgt             16b
        subs            r5,  r5,  #2
        add             r2,  r2,  r4,  lsl #1
        add             r3,  r3,  r4,  lsl #1
        add             r7,  r7,  r4,  lsl #1
        add             r9,  r9,  r4,  lsl #1
.if \type == 444
        add             r6,  r6,  r4
        add             lr,  lr,  r4
.elseif \type == 422
        add             r6,  r6,  r4,  lsr #1
        add             lr,  lr,  r4,  lsr #1
.endif
        add             r0,  r0,  r1
        add             r12, r12, r1
        bgt             161b
        vpop            {q4-q7}
        pop             {r4-r10,pc}
endfunc
.endm

w_mask_fn 444
w_mask_fn 422
w_mask_fn 420

function blend_16bpc_neon, export=1
        push            {r4-r5,lr}
        ldrd            r4,  r5,  [sp, #12]
        clz             lr,  r3
        adr             r3,  L(blend_tbl)
        sub             lr,  lr,  #26
        ldr             lr,  [r3,  lr,  lsl #2]
        add             r3,  r3,  lr
        bx              r3

        .align 2
L(blend_tbl):
        .word 320f - L(blend_tbl) + CONFIG_THUMB
        .word 160f - L(blend_tbl) + CONFIG_THUMB
        .word 80f  - L(blend_tbl) + CONFIG_THUMB
        .word 40f  - L(blend_tbl) + CONFIG_THUMB

40:
        add             r12, r0,  r1
        lsl             r1,  r1,  #1
4:
        vld1.8          {d4}, [r5, :64]!
        vld1.16         {q1}, [r2, :128]!
        vld1.16         {d0}, [r0, :64]
        vneg.s8         d4,  d4       // -m
        subs            r4,  r4,  #2
        vld1.16         {d1}, [r12, :64]
        vmovl.s8        q2,  d4
        vshl.i16        q2,  q2,  #9  // -m << 9
        vsub.i16        q1,  q0,  q1  // a - b
        vqrdmulh.s16    q1,  q1,  q2  // ((a-b)*-m + 32) >> 6
        vadd.i16        q0,  q0,  q1
        vst1.16         {d0}, [r0,  :64], r1
        vst1.16         {d1}, [r12, :64], r1
        bgt             4b
        pop             {r4-r5,pc}
80:
        add             r12, r0,  r1
        lsl             r1,  r1,  #1
8:
        vld1.8          {q8},     [r5, :128]!
        vld1.16         {q2, q3}, [r2, :128]!
        vneg.s8         q9,  q8       // -m
        vld1.16         {q0},     [r0,  :128]
        vld1.16         {q1},     [r12, :128]
        vmovl.s8        q8,  d18
        vmovl.s8        q9,  d19
        vshl.i16        q8,  q8,  #9  // -m << 9
        vshl.i16        q9,  q9,  #9
        vsub.i16        q2,  q0,  q2  // a - b
        vsub.i16        q3,  q1,  q3
        subs            r4,  r4,  #2
        vqrdmulh.s16    q2,  q2,  q8  // ((a-b)*-m + 32) >> 6
        vqrdmulh.s16    q3,  q3,  q9
        vadd.i16        q0,  q0,  q2
        vadd.i16        q1,  q1,  q3
        vst1.16         {q0}, [r0,  :128], r1
        vst1.16         {q1}, [r12, :128], r1
        bgt             8b
        pop             {r4-r5,pc}
160:
        add             r12, r0,  r1
        lsl             r1,  r1,  #1
16:
        vld1.8          {q12, q13}, [r5, :128]!
        vld1.16         {q8,  q9},  [r2, :128]!
        subs            r4,  r4,  #2
        vneg.s8         q14, q12      // -m
        vld1.16         {q0,  q1},  [r0, :128]
        vneg.s8         q15, q13
        vld1.16         {q10, q11}, [r2, :128]!
        vmovl.s8        q12, d28
        vmovl.s8        q13, d29
        vmovl.s8        q14, d30
        vmovl.s8        q15, d31
        vld1.16         {q2,  q3},  [r12, :128]
        vshl.i16        q12, q12, #9  // -m << 9
        vshl.i16        q13, q13, #9
        vshl.i16        q14, q14, #9
        vshl.i16        q15, q15, #9
        vsub.i16        q8,  q0,  q8  // a - b
        vsub.i16        q9,  q1,  q9
        vsub.i16        q10, q2,  q10
        vsub.i16        q11, q3,  q11
        vqrdmulh.s16    q8,  q8,  q12 // ((a-b)*-m + 32) >> 6
        vqrdmulh.s16    q9,  q9,  q13
        vqrdmulh.s16    q10, q10, q14
        vqrdmulh.s16    q11, q11, q15
        vadd.i16        q0,  q0,  q8
        vadd.i16        q1,  q1,  q9
        vadd.i16        q2,  q2,  q10
        vst1.16         {q0, q1}, [r0,  :128], r1
        vadd.i16        q3,  q3,  q11
        vst1.16         {q2, q3}, [r12, :128], r1
        bgt             16b
        pop             {r4-r5,pc}
320:
        add             r12, r0,  #32
32:
        vld1.8          {q12, q13}, [r5, :128]!
        vld1.16         {q8,  q9},  [r2, :128]!
        subs            r4,  r4,  #1
        vneg.s8         q14, q12      // -m
        vld1.16         {q0,  q1},  [r0, :128]
        vneg.s8         q15, q13
        vld1.16         {q10, q11}, [r2, :128]!
        vmovl.s8        q12, d28
        vmovl.s8        q13, d29
        vmovl.s8        q14, d30
        vmovl.s8        q15, d31
        vld1.16         {q2,  q3},  [r12, :128]
        vshl.i16        q12, q12, #9  // -m << 9
        vshl.i16        q13, q13, #9
        vshl.i16        q14, q14, #9
        vshl.i16        q15, q15, #9
        vsub.i16        q8,  q0,  q8  // a - b
        vsub.i16        q9,  q1,  q9
        vsub.i16        q10, q2,  q10
        vsub.i16        q11, q3,  q11
        vqrdmulh.s16    q8,  q8,  q12 // ((a-b)*-m + 32) >> 6
        vqrdmulh.s16    q9,  q9,  q13
        vqrdmulh.s16    q10, q10, q14
        vqrdmulh.s16    q11, q11, q15
        vadd.i16        q0,  q0,  q8
        vadd.i16        q1,  q1,  q9
        vadd.i16        q2,  q2,  q10
        vst1.16         {q0, q1}, [r0,  :128], r1
        vadd.i16        q3,  q3,  q11
        vst1.16         {q2, q3}, [r12, :128], r1
        bgt             32b
        pop             {r4-r5,pc}
endfunc

function blend_h_16bpc_neon, export=1
        push            {r4-r5,lr}
        ldr             r4,  [sp, #12]
        movrel          r5,  X(obmc_masks)
        add             r5,  r5,  r4
        sub             r4,  r4,  r4,  lsr #2
        clz             lr,  r3
        adr             r12, L(blend_h_tbl)
        sub             lr,  lr,  #24
        ldr             lr,  [r12, lr,  lsl #2]
        add             r12, r12, lr
        bx              r12

        .align 2
L(blend_h_tbl):
        .word 1280f - L(blend_h_tbl) + CONFIG_THUMB
        .word 640f  - L(blend_h_tbl) + CONFIG_THUMB
        .word 320f  - L(blend_h_tbl) + CONFIG_THUMB
        .word 160f  - L(blend_h_tbl) + CONFIG_THUMB
        .word 80f   - L(blend_h_tbl) + CONFIG_THUMB
        .word 40f   - L(blend_h_tbl) + CONFIG_THUMB
        .word 20f   - L(blend_h_tbl) + CONFIG_THUMB

20:
        add             r12, r0,  r1
        lsl             r1,  r1,  #1
2:
        vld2.8          {d4[], d5[]}, [r5, :16]!
        vld1.16         {d2},         [r2, :64]!
        vext.8          d4,  d4,  d5,  #6
        subs            r4,  r4,  #2
        vneg.s8         d4,  d4       // -m
        vld1.32         {d0[]},  [r0, :32]
        vld1.32         {d0[1]}, [r12, :32]
        vmovl.s8        q2,  d4
        vshl.i16        d4,  d4,  #9  // -m << 9
        vsub.i16        d2,  d0,  d2  // a - b
        vqrdmulh.s16    d2,  d2,  d4  // ((a-b)*-m + 32) >> 6
        vadd.i16        d0,  d0,  d2
        vst1.32         {d0[0]}, [r0,  :32], r1
        vst1.32         {d0[1]}, [r12, :32], r1
        bgt             2b
        pop             {r4-r5,pc}
40:
        add             r12, r0,  r1
        lsl             r1,  r1,  #1
4:
        vld2.8          {d4[], d5[]}, [r5, :16]!
        vld1.16         {q1},         [r2, :128]!
        vext.8          d4,  d4,  d5,  #4
        subs            r4,  r4,  #2
        vneg.s8         d4,  d4       // -m
        vld1.16         {d0}, [r0,  :64]
        vld1.16         {d1}, [r12, :64]
        vmovl.s8        q2,  d4
        vshl.i16        q2,  q2,  #9  // -m << 9
        vsub.i16        q1,  q0,  q1  // a - b
        vqrdmulh.s16    q1,  q1,  q2  // ((a-b)*-m + 32) >> 6
        vadd.i16        q0,  q0,  q1
        vst1.16         {d0}, [r0,  :64], r1
        vst1.16         {d1}, [r12, :64], r1
        bgt             4b
        pop             {r4-r5,pc}
80:
        add             r12, r0,  r1
        lsl             r1,  r1,  #1
8:
        vld2.8          {d16[], d17[]}, [r5, :16]!
        vld1.16         {q2, q3},       [r2, :128]!
        vneg.s8         q9,  q8      // -m
        vld1.16         {q0}, [r0, :128]
        subs            r4,  r4,  #2
        vmovl.s8        q8,  d18
        vmovl.s8        q9,  d19
        vld1.16         {q1}, [r12, :128]
        vshl.i16        q8,  q8,  #9  // -m << 9
        vshl.i16        q9,  q9,  #9
        vsub.i16        q2,  q0,  q2  // a - b
        vsub.i16        q3,  q1,  q3
        vqrdmulh.s16    q2,  q2,  q8  // ((a-b)*-m + 32) >> 6
        vqrdmulh.s16    q3,  q3,  q9
        vadd.i16        q0,  q0,  q2
        vadd.i16        q1,  q1,  q3
        vst1.16         {q0}, [r0,  :128], r1
        vst1.16         {q1}, [r12, :128], r1
        bgt             8b
        pop             {r4-r5,pc}
160:
        add             r12, r0,  r1
        lsl             r1,  r1,  #1
16:
        vld2.8          {d24[], d25[]}, [r5, :16]!
        vld1.16         {q8,  q9},  [r2, :128]!
        subs            r4,  r4,  #2
        vneg.s8         q13, q12      // -m
        vld1.16         {q0,  q1},  [r0, :128]
        vmovl.s8        q12, d26
        vld1.16         {q10, q11}, [r2, :128]!
        vmovl.s8        q13, d27
        vld1.16         {q2,  q3},  [r12, :128]
        vshl.i16        q12, q12, #9  // -m << 9
        vshl.i16        q13, q13, #9
        vsub.i16        q8,  q0,  q8  // a - b
        vsub.i16        q9,  q1,  q9
        vsub.i16        q10, q2,  q10
        vsub.i16        q11, q3,  q11
        vqrdmulh.s16    q8,  q8,  q12 // ((a-b)*-m + 32) >> 6
        vqrdmulh.s16    q9,  q9,  q12
        vqrdmulh.s16    q10, q10, q13
        vqrdmulh.s16    q11, q11, q13
        vadd.i16        q0,  q0,  q8
        vadd.i16        q1,  q1,  q9
        vadd.i16        q2,  q2,  q10
        vadd.i16        q3,  q3,  q11
        vst1.16         {q0, q1}, [r0,  :128], r1
        vst1.16         {q2, q3}, [r12, :128], r1
        bgt             16b
        pop             {r4-r5,pc}
1280:
640:
320:
        sub             r1,  r1,  r3,  lsl #1
321:
        vld1.8          {d24[]}, [r5]!
        mov             r12, r3
        vneg.s8         d24, d24      // -m
        vmovl.s8        q12, d24
        vshl.i16        q12, q12, #9  // -m << 9
32:
        vld1.16         {q8,  q9},  [r2, :128]!
        vld1.16         {q0,  q1},  [r0, :128]!
        subs            r12, r12, #32
        vld1.16         {q10, q11}, [r2, :128]!
        vld1.16         {q2,  q3},  [r0, :128]
        vsub.i16        q8,  q0,  q8  // a - b
        vsub.i16        q9,  q1,  q9
        vsub.i16        q10, q2,  q10
        vsub.i16        q11, q3,  q11
        sub             r0,  r0,  #32
        vqrdmulh.s16    q8,  q8,  q12 // ((a-b)*-m + 32) >> 6
        vqrdmulh.s16    q9,  q9,  q12
        vqrdmulh.s16    q10, q10, q12
        vqrdmulh.s16    q11, q11, q12
        vadd.i16        q0,  q0,  q8
        vadd.i16        q1,  q1,  q9
        vadd.i16        q2,  q2,  q10
        vst1.16         {q0, q1}, [r0, :128]!
        vadd.i16        q3,  q3,  q11
        vst1.16         {q2, q3}, [r0, :128]!
        bgt             32b
        subs            r4,  r4,  #1
        add             r0,  r0,  r1
        bgt             321b
        pop             {r4-r5,pc}
endfunc

function blend_v_16bpc_neon, export=1
        push            {r4,lr}
        ldr             r4,  [sp, #8]
        movrel          lr,  X(obmc_masks)
        add             lr,  lr,  r3
        clz             r12, r3
        adr             r3,  L(blend_v_tbl)
        sub             r12, r12, #26
        ldr             r12, [r3,  r12, lsl #2]
        add             r3,  r3,  r12
        bx              r3

        .align 2
L(blend_v_tbl):
        .word 320f - L(blend_v_tbl) + CONFIG_THUMB
        .word 160f - L(blend_v_tbl) + CONFIG_THUMB
        .word 80f  - L(blend_v_tbl) + CONFIG_THUMB
        .word 40f  - L(blend_v_tbl) + CONFIG_THUMB
        .word 20f  - L(blend_v_tbl) + CONFIG_THUMB

20:
        add             r12, r0,  r1
        lsl             r1,  r1,  #1
        vld1.8          {d4[]}, [lr]
        vneg.s8         d4,  d4       // -m
        vmovl.s8        q2,  d4
        vshl.i16        d4,  d4,  #9  // -m << 9
2:
        vld1.32         {d2[]},  [r2, :32]!
        vld1.16         {d0[]},  [r0, :16]
        subs            r4,  r4,  #2
        vld1.16         {d2[1]}, [r2,  :16]
        vld1.16         {d0[1]}, [r12, :16]
        add             r2,  r2,  #4
        vsub.i16        d2,  d0,  d2  // a - b
        vqrdmulh.s16    d2,  d2,  d4  // ((a-b)*-m + 32) >> 6
        vadd.i16        d0,  d0,  d2
        vst1.16         {d0[0]}, [r0,  :16], r1
        vst1.16         {d0[1]}, [r12, :16], r1
        bgt             2b
        pop             {r4,pc}
40:
        vld1.32         {d4[]}, [lr, :32]
        add             r12, r0,  r1
        vneg.s8         d4,  d4       // -m
        lsl             r1,  r1,  #1
        vmovl.s8        q2,  d4
        sub             r1,  r1,  #4
        vshl.i16        q2,  q2,  #9  // -m << 9
4:
        vld1.16         {q1}, [r2, :128]!
        vld1.16         {d0}, [r0,  :64]
        vld1.16         {d1}, [r12, :64]
        subs            r4,  r4,  #2
        vsub.i16        q1,  q0,  q1  // a - b
        vqrdmulh.s16    q1,  q1,  q2  // ((a-b)*-m + 32) >> 6
        vadd.i16        q0,  q0,  q1
        vst1.32         {d0[0]}, [r0,  :32]!
        vst1.32         {d1[0]}, [r12, :32]!
        vst1.16         {d0[2]}, [r0,  :16], r1
        vst1.16         {d1[2]}, [r12, :16], r1
        bgt             4b
        pop             {r4,pc}
80:
        vld1.8          {d16}, [lr, :64]
        add             r12, r0,  r1
        vneg.s8         d16, d16      // -m
        lsl             r1,  r1,  #1
        vmovl.s8        q8,  d16
        sub             r1,  r1,  #8
        vshl.i16        q8,  q8,  #9  // -m << 9
8:
        vld1.16         {q2, q3}, [r2,  :128]!
        vld1.16         {q0},     [r0,  :128]
        vld1.16         {q1},     [r12, :128]
        subs            r4,  r4,  #2
        vsub.i16        q2,  q0,  q2  // a - b
        vsub.i16        q3,  q1,  q3
        vqrdmulh.s16    q2,  q2,  q8  // ((a-b)*-m + 32) >> 6
        vqrdmulh.s16    q3,  q3,  q8
        vadd.i16        q0,  q0,  q2
        vadd.i16        q1,  q1,  q3
        vst1.16         {d0},    [r0,  :64]!
        vst1.16         {d2},    [r12, :64]!
        vst1.32         {d1[0]}, [r0,  :32], r1
        vst1.32         {d3[0]}, [r12, :32], r1
        bgt             8b
        pop             {r4,pc}
160:
        vld1.8          {q12}, [lr, :128]
        add             r12, r0,  r1
        vneg.s8         q13, q12      // -m
        lsl             r1,  r1,  #1
        vmovl.s8        q12, d26
        vmovl.s8        q13, d27
        vshl.i16        q12, q12, #9  // -m << 9
        vshl.i16        d26, d26, #9
16:
        vld1.16         {q8,  q9},      [r2,  :128]!
        vld1.16         {d0,  d1,  d2}, [r0,  :64]
        subs            r4,  r4,  #2
        vld1.16         {q10, q11},     [r2,  :128]!
        vsub.i16        q8,  q0,  q8  // a - b
        vld1.16         {d4,  d5,  d6}, [r12, :64]
        vsub.i16        d18, d2,  d18
        vsub.i16        q10, q2,  q10
        vsub.i16        d22, d6,  d22
        vqrdmulh.s16    q8,  q8,  q12  // ((a-b)*-m + 32) >> 6
        vqrdmulh.s16    d18, d18, d26
        vqrdmulh.s16    q10, q10, q12
        vqrdmulh.s16    d22, d22, d26
        vadd.i16        q0,  q0,  q8
        vadd.i16        d2,  d2,  d18
        vadd.i16        q2,  q2,  q10
        vst1.16         {d0,  d1,  d2}, [r0,  :64], r1
        vadd.i16        d6,  d6,  d22
        vst1.16         {d4,  d5,  d6}, [r12, :64], r1
        bgt             16b
        pop             {r4,pc}
320:
        vld1.8          {d24, d25, d26}, [lr, :64]
        vneg.s8         q14, q12      // -m
        vneg.s8         d30, d26
        vmovl.s8        q12, d28
        vmovl.s8        q13, d29
        vmovl.s8        q14, d30
        sub             r1,  r1,  #32
        vshl.i16        q12, q12, #9  // -m << 9
        vshl.i16        q13, q13, #9
        vshl.i16        q14, q14, #9
32:
        vld1.16         {q8,  q9},  [r2, :128]!
        vld1.16         {q0,  q1},  [r0, :128]!
        subs            r4,  r4,  #1
        vld1.16         {q10},      [r2, :128]
        vsub.i16        q8,  q0,  q8  // a - b
        vld1.16         {q2},       [r0, :128]
        sub             r0,  r0,  #32
        vsub.i16        q9,  q1,  q9
        vsub.i16        q10, q2,  q10
        vqrdmulh.s16    q8,  q8,  q12  // ((a-b)*-m + 32) >> 6
        vqrdmulh.s16    q9,  q9,  q13
        vqrdmulh.s16    q10, q10, q14
        vadd.i16        q0,  q0,  q8
        vadd.i16        q1,  q1,  q9
        vadd.i16        q2,  q2,  q10
        vst1.16         {q0, q1}, [r0, :128]!
        add             r2,  r2,  #32
        vst1.16         {q2},     [r0, :128], r1
        bgt             32b
        pop             {r4,pc}
endfunc

// This has got the same signature as the put_8tap functions,
// and assumes that r9 is set to (clz(w)-24).
function put_neon
        adr             r10, L(put_tbl)
        ldr             r9,  [r10, r9, lsl #2]
        add             r10, r10, r9
        bx              r10

        .align 2
L(put_tbl):
        .word 1280f - L(put_tbl) + CONFIG_THUMB
        .word 640f  - L(put_tbl) + CONFIG_THUMB
        .word 320f  - L(put_tbl) + CONFIG_THUMB
        .word 16f   - L(put_tbl) + CONFIG_THUMB
        .word 80f   - L(put_tbl) + CONFIG_THUMB
        .word 4f    - L(put_tbl) + CONFIG_THUMB
        .word 2f    - L(put_tbl) + CONFIG_THUMB

2:
        vld1.32         {d0[]}, [r2], r3
        vld1.32         {d1[]}, [r2], r3
        subs            r5,  r5,  #2
        vst1.32         {d0[0]}, [r0, :32], r1
        vst1.32         {d1[1]}, [r0, :32], r1
        bgt             2b
        pop             {r4-r11,pc}
4:
        vld1.16         {d0}, [r2], r3
        vld1.16         {d1}, [r2], r3
        subs            r5,  r5,  #2
        vst1.16         {d0}, [r0, :64], r1
        vst1.16         {d1}, [r0, :64], r1
        bgt             4b
        pop             {r4-r11,pc}
80:
        add             r8,  r0,  r1
        lsl             r1,  r1,  #1
        add             r9,  r2,  r3
        lsl             r3,  r3,  #1
8:
        vld1.16         {q0}, [r2], r3
        vld1.16         {q1}, [r9], r3
        subs            r5,  r5,  #2
        vst1.16         {q0}, [r0, :128], r1
        vst1.16         {q1}, [r8, :128], r1
        bgt             8b
        pop             {r4-r11,pc}
16:
        vld1.16         {q0,  q1},  [r2], r3
        subs            r5,  r5,  #1
        vst1.16         {q0,  q1},  [r0, :128], r1
        bgt             16b
        pop             {r4-r11,pc}
320:
        sub             r1,  r1,  #32
        sub             r3,  r3,  #32
32:
        vld1.16         {q0,  q1},  [r2]!
        vst1.16         {q0,  q1},  [r0, :128]!
        vld1.16         {q2,  q3},  [r2], r3
        subs            r5,  r5,  #1
        vst1.16         {q2,  q3},  [r0, :128], r1
        bgt             32b
        pop             {r4-r11,pc}
640:
        sub             r1,  r1,  #96
        sub             r3,  r3,  #96
64:
        vld1.16         {q8,  q9},  [r2]!
        vst1.16         {q8,  q9},  [r0, :128]!
        vld1.16         {q10, q11}, [r2]!
        vst1.16         {q10, q11}, [r0, :128]!
        vld1.16         {q12, q13}, [r2]!
        vst1.16         {q12, q13}, [r0, :128]!
        vld1.16         {q14, q15}, [r2], r3
        subs            r5,  r5,  #1
        vst1.16         {q14, q15}, [r0, :128], r1
        bgt             64b
        pop             {r4-r11,pc}
1280:
        sub             r1,  r1,  #224
        sub             r3,  r3,  #224
128:
        vld1.16         {q8,  q9},  [r2]!
        vst1.16         {q8,  q9},  [r0, :128]!
        vld1.16         {q10, q11}, [r2]!
        vst1.16         {q10, q11}, [r0, :128]!
        vld1.16         {q12, q13}, [r2]!
        vst1.16         {q12, q13}, [r0, :128]!
        vld1.16         {q14, q15}, [r2]!
        vst1.16         {q14, q15}, [r0, :128]!
        vld1.16         {q8,  q9},  [r2]!
        vst1.16         {q8,  q9},  [r0, :128]!
        vld1.16         {q10, q11}, [r2]!
        vst1.16         {q10, q11}, [r0, :128]!
        vld1.16         {q12, q13}, [r2]!
        vst1.16         {q12, q13}, [r0, :128]!
        vld1.16         {q14, q15}, [r2], r3
        subs            r5,  r5,  #1
        vst1.16         {q14, q15}, [r0, :128], r1
        bgt             128b
        pop             {r4-r11,pc}
endfunc

// This has got the same signature as the prep_8tap functions,
// and assumes that r9 is set to (clz(w)-24), r7 to intermediate_bits and
// r8 to w*2.
function prep_neon
        adr             r10, L(prep_tbl)
        ldr             r9,  [r10, r9, lsl #2]
        vdup.16         q15, r7   // intermediate_bits
        vmov.i16        q14, #PREP_BIAS
        add             r10, r10, r9
        bx              r10

        .align 2
L(prep_tbl):
        .word 1280f - L(prep_tbl) + CONFIG_THUMB
        .word 640f  - L(prep_tbl) + CONFIG_THUMB
        .word 320f  - L(prep_tbl) + CONFIG_THUMB
        .word 16f   - L(prep_tbl) + CONFIG_THUMB
        .word 80f   - L(prep_tbl) + CONFIG_THUMB
        .word 40f   - L(prep_tbl) + CONFIG_THUMB

40:
        add             r9,  r1,  r2
        lsl             r2,  r2,  #1
4:
        vld1.16         {d0}, [r1], r2
        vld1.16         {d1}, [r9], r2
        subs            r4,  r4,  #2
        vshl.s16        q0,  q0,  q15
        vsub.i16        q0,  q0,  q14
        vst1.16         {q0}, [r0, :128]!
        bgt             4b
        pop             {r4-r11,pc}
80:
        add             r9,  r1,  r2
        lsl             r2,  r2,  #1
8:
        vld1.16         {q0}, [r1], r2
        vld1.16         {q1}, [r9], r2
        subs            r4,  r4,  #2
        vshl.s16        q0,  q0,  q15
        vshl.s16        q1,  q1,  q15
        vsub.i16        q0,  q0,  q14
        vsub.i16        q1,  q1,  q14
        vst1.16         {q0, q1}, [r0, :128]!
        bgt             8b
        pop             {r4-r11,pc}
16:
        vld1.16         {q0, q1}, [r1], r2
        vshl.s16        q0,  q0,  q15
        vld1.16         {q2, q3}, [r1], r2
        subs            r4,  r4,  #2
        vshl.s16        q1,  q1,  q15
        vshl.s16        q2,  q2,  q15
        vshl.s16        q3,  q3,  q15
        vsub.i16        q0,  q0,  q14
        vsub.i16        q1,  q1,  q14
        vsub.i16        q2,  q2,  q14
        vst1.16         {q0, q1}, [r0, :128]!
        vsub.i16        q3,  q3,  q14
        vst1.16         {q2, q3}, [r0, :128]!
        bgt             16b
        pop             {r4-r11,pc}
320:
        sub             r2,  r2,  #32
32:
        vld1.16         {q0, q1}, [r1]!
        subs            r4,  r4,  #1
        vshl.s16        q0,  q0,  q15
        vld1.16         {q2, q3}, [r1], r2
        vshl.s16        q1,  q1,  q15
        vshl.s16        q2,  q2,  q15
        vshl.s16        q3,  q3,  q15
        vsub.i16        q0,  q0,  q14
        vsub.i16        q1,  q1,  q14
        vsub.i16        q2,  q2,  q14
        vst1.16         {q0, q1}, [r0, :128]!
        vsub.i16        q3,  q3,  q14
        vst1.16         {q2, q3}, [r0, :128]!
        bgt             32b
        pop             {r4-r11,pc}
640:
        sub             r2,  r2,  #96
64:
        vld1.16         {q0,  q1},  [r1]!
        subs            r4,  r4,  #1
        vshl.s16        q0,  q0,  q15
        vld1.16         {q2,  q3},  [r1]!
        vshl.s16        q1,  q1,  q15
        vld1.16         {q8,  q9},  [r1]!
        vshl.s16        q2,  q2,  q15
        vld1.16         {q10, q11}, [r1], r2
        vshl.s16        q3,  q3,  q15
        vshl.s16        q8,  q8,  q15
        vshl.s16        q9,  q9,  q15
        vshl.s16        q10, q10, q15
        vshl.s16        q11, q11, q15
        vsub.i16        q0,  q0,  q14
        vsub.i16        q1,  q1,  q14
        vsub.i16        q2,  q2,  q14
        vsub.i16        q3,  q3,  q14
        vsub.i16        q8,  q8,  q14
        vst1.16         {q0,  q1},  [r0, :128]!
        vsub.i16        q9,  q9,  q14
        vst1.16         {q2,  q3},  [r0, :128]!
        vsub.i16        q10, q10, q14
        vst1.16         {q8,  q9},  [r0, :128]!
        vsub.i16        q11, q11, q14
        vst1.16         {q10, q11}, [r0, :128]!
        bgt             64b
        pop             {r4-r11,pc}
1280:
        sub             r2,  r2,  #224
128:
        vld1.16         {q0,  q1},  [r1]!
        subs            r4,  r4,  #1
        vshl.s16        q0,  q0,  q15
        vld1.16         {q2,  q3},  [r1]!
        vshl.s16        q1,  q1,  q15
        vld1.16         {q8,  q9},  [r1]!
        vshl.s16        q2,  q2,  q15
        vld1.16         {q10, q11}, [r1]!
        vshl.s16        q3,  q3,  q15
        vshl.s16        q8,  q8,  q15
        vshl.s16        q9,  q9,  q15
        vshl.s16        q10, q10, q15
        vshl.s16        q11, q11, q15
        vsub.i16        q0,  q0,  q14
        vsub.i16        q1,  q1,  q14
        vsub.i16        q2,  q2,  q14
        vsub.i16        q3,  q3,  q14
        vsub.i16        q8,  q8,  q14
        vst1.16         {q0,  q1},  [r0, :128]!
        vld1.16         {q0,  q1},  [r1]!
        vsub.i16        q9,  q9,  q14
        vsub.i16        q10, q10, q14
        vst1.16         {q2,  q3},  [r0, :128]!
        vld1.16         {q2,  q3},  [r1]!
        vsub.i16        q11, q11, q14
        vshl.s16        q0,  q0,  q15
        vst1.16         {q8,  q9},  [r0, :128]!
        vld1.16         {q8,  q9},  [r1]!
        vshl.s16        q1,  q1,  q15
        vshl.s16        q2,  q2,  q15
        vst1.16         {q10, q11}, [r0, :128]!
        vld1.16         {q10, q11}, [r1], r2
        vshl.s16        q3,  q3,  q15
        vshl.s16        q8,  q8,  q15
        vshl.s16        q9,  q9,  q15
        vshl.s16        q10, q10, q15
        vshl.s16        q11, q11, q15
        vsub.i16        q0,  q0,  q14
        vsub.i16        q1,  q1,  q14
        vsub.i16        q2,  q2,  q14
        vsub.i16        q3,  q3,  q14
        vsub.i16        q8,  q8,  q14
        vst1.16         {q0,  q1},  [r0, :128]!
        vsub.i16        q9,  q9,  q14
        vst1.16         {q2,  q3},  [r0, :128]!
        vsub.i16        q10, q10, q14
        vst1.16         {q8,  q9},  [r0, :128]!
        vsub.i16        q11, q11, q14
        vst1.16         {q10, q11}, [r0, :128]!
        bgt             128b
        pop             {r4-r11,pc}
endfunc

.macro load_slice s0, s1, strd, wd, d0, d1, d2, d3, d4, d5, d6
        vld1.\wd        {\d0[]}, [\s0], \strd
        vld1.\wd        {\d1[]}, [\s1], \strd
.ifnb \d2
        vld1.\wd        {\d2[]}, [\s0], \strd
        vld1.\wd        {\d3[]}, [\s1], \strd
.endif
.ifnb \d4
        vld1.\wd        {\d4[]}, [\s0], \strd
.endif
.ifnb \d5
        vld1.\wd        {\d5[]}, [\s1], \strd
.endif
.ifnb \d6
        vld1.\wd        {\d6[]}, [\s0], \strd
.endif
.endm
.macro load_reg s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
        vld1.16         {\d0}, [\s0], \strd
        vld1.16         {\d1}, [\s1], \strd
.ifnb \d2
        vld1.16         {\d2}, [\s0], \strd
        vld1.16         {\d3}, [\s1], \strd
.endif
.ifnb \d4
        vld1.16         {\d4}, [\s0], \strd
.endif
.ifnb \d5
        vld1.16         {\d5}, [\s1], \strd
.endif
.ifnb \d6
        vld1.16         {\d6}, [\s0], \strd
.endif
.endm
.macro load_regpair s0, s1, strd, d0, d1, d2, d3, d4, d5
        vld1.16         {\d0, \d1}, [\s0], \strd
.ifnb \d2
        vld1.16         {\d2, \d3}, [\s1], \strd
.endif
.ifnb \d4
        vld1.16         {\d4, \d5}, [\s0], \strd
.endif
.endm
.macro load_32 s0, s1, strd, d0, d1, d2, d3, d4, d5, d6
        load_slice      \s0, \s1, \strd, 32, \d0, \d1, \d2, \d3, \d4, \d5, \d6
.endm
.macro load_16s16 s0, s1, strd, d0, d1, d2, d3, d4, d5
        load_regpair    \s0, \s1, \strd, \d0, \d1, \d2, \d3, \d4, \d5
.endm
.macro interleave_1_32 r0, r1, r2, r3, r4
        vext.8          \r0, \r0, \r1, #4
        vext.8          \r1, \r1, \r2, #4
.ifnb \r3
        vext.8          \r2, \r2, \r3, #4
        vext.8          \r3, \r3, \r4, #4
.endif
.endm
.macro vmin_u16 c, r0, r1, r2, r3
        vmin.u16        \r0, \r0, \c
.ifnb \r1
        vmin.u16        \r1, \r1, \c
.endif
.ifnb \r2
        vmin.u16        \r2, \r2, \c
        vmin.u16        \r3, \r3, \c
.endif
.endm
.macro vsub_i16 c, r0, r1, r2, r3
        vsub.i16        \r0, \r0, \c
.ifnb \r1
        vsub.i16        \r1, \r1, \c
.endif
.ifnb \r2
        vsub.i16        \r2, \r2, \c
        vsub.i16        \r3, \r3, \c
.endif
.endm
.macro vmull_vmlal_4 d, s0, s1, s2, s3
        vmull.s16       \d,  \s0, d0[0]
        vmlal.s16       \d,  \s1, d0[1]
        vmlal.s16       \d,  \s2, d0[2]
        vmlal.s16       \d,  \s3, d0[3]
.endm
.macro vmull_vmlal_8 d, s0, s1, s2, s3, s4, s5, s6, s7
        vmull.s16       \d,  \s0, d0[0]
        vmlal.s16       \d,  \s1, d0[1]
        vmlal.s16       \d,  \s2, d0[2]
        vmlal.s16       \d,  \s3, d0[3]
        vmlal.s16       \d,  \s4, d1[0]
        vmlal.s16       \d,  \s5, d1[1]
        vmlal.s16       \d,  \s6, d1[2]
        vmlal.s16       \d,  \s7, d1[3]
.endm
.macro vqrshrun_s32 shift, q0, d0, q1, d1, q2, d2, q3, d3
        vqrshrun.s32    \d0, \q0, #\shift
.ifnb \q1
        vqrshrun.s32    \d1, \q1, #\shift
.endif
.ifnb \q2
        vqrshrun.s32    \d2, \q2, #\shift
        vqrshrun.s32    \d3, \q3, #\shift
.endif
.endm
.macro vmovn_i32 q0, d0, q1, d1, q2, d2, q3, d3
        vmovn.i32       \d0, \q0
.ifnb \q1
        vmovn.i32       \d1, \q1
.endif
.ifnb \q2
        vmovn.i32       \d2, \q2
        vmovn.i32       \d3, \q3
.endif
.endm
.macro vrshl_s32 shift, r0, r1, r2, r3
        vrshl.s32       \r0, \r0, \shift
        vrshl.s32       \r1, \r1, \shift
.ifnb \r2
        vrshl.s32       \r2, \r2, \shift
        vrshl.s32       \r3, \r3, \shift
.endif
.endm
.macro vst1_32 strd, r0, r1
        vst1.32         {\r0[0]}, [r0, :32], \strd
        vst1.32         {\r0[1]}, [r9, :32], \strd
.ifnb \r1
        vst1.32         {\r1[0]}, [r0, :32], \strd
        vst1.32         {\r1[1]}, [r9, :32], \strd
.endif
.endm
.macro vst1_reg strd, align, r0, r1, r2, r3, r4, r5, r6, r7
        vst1.16         {\r0}, [r0, \align], \strd
        vst1.16         {\r1}, [r9, \align], \strd
.ifnb \r2
        vst1.16         {\r2}, [r0, \align], \strd
        vst1.16         {\r3}, [r9, \align], \strd
.endif
.ifnb \r4
        vst1.16         {\r4}, [r0, \align], \strd
        vst1.16         {\r5}, [r9, \align], \strd
        vst1.16         {\r6}, [r0, \align], \strd
        vst1.16         {\r7}, [r9, \align], \strd
.endif
.endm
.macro finalize type, q0, q1, d0, d1, q2, q3, d2, d3
.ifc \type, put
        vqrshrun_s32    6,   \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3
        vmin_u16        q15, \q0, \q1
.else
        vrshl_s32       q14, \q0, \q1, \q2, \q3 // -(6-intermediate_bits)
        vmovn_i32       \q0, \d0, \q1, \d1, \q2, \d2, \q3, \d3
        vsub_i16        q15, \q0, \q1           // PREP_BIAS
.endif
.endm
.macro shift_store_4 type, strd, q0, q1, d0, d1, q2, q3, d2, d3
        finalize        \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3
        vst1_reg        \strd, :64, \d0, \d1, \d2, \d3
.endm
.macro shift_store_8 type, strd, q0, q1, d0, d1, q2, q3, d2, d3
        finalize        \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3
        vst1_reg        \strd, :128, \q0, \q1
.endm
.macro shift_store_16 type, strd, q0, q1, d0, d1, q2, q3, d2, d3
        finalize        \type, \q0, \q1, \d0, \d1, \q2, \q3, \d2, \d3
        vst1.16         {\q0, \q1}, [r0, :128], \strd
.endm

.macro make_8tap_fn op, type, type_h, type_v
function \op\()_8tap_\type\()_16bpc_neon, export=1
        push            {r4-r11,lr}
        movw            r9,  \type_h
        movw            r10, \type_v
        b               \op\()_8tap_neon
endfunc
.endm

// No spaces in these expressions, due to gas-preprocessor.
#define REGULAR ((0*15<<7)|3*15)
#define SMOOTH  ((1*15<<7)|4*15)
#define SHARP   ((2*15<<7)|3*15)

.macro filter_fn type, dst, d_strd, src, s_strd, w, h, mx, my, bdmax, ds2, sr2
make_8tap_fn \type, regular,        REGULAR, REGULAR
make_8tap_fn \type, regular_smooth, REGULAR, SMOOTH
make_8tap_fn \type, regular_sharp,  REGULAR, SHARP
make_8tap_fn \type, smooth,         SMOOTH,  SMOOTH
make_8tap_fn \type, smooth_regular, SMOOTH,  REGULAR
make_8tap_fn \type, smooth_sharp,   SMOOTH,  SHARP
make_8tap_fn \type, sharp,          SHARP,   SHARP
make_8tap_fn \type, sharp_regular,  SHARP,   REGULAR
make_8tap_fn \type, sharp_smooth,   SHARP,   SMOOTH

function \type\()_8tap_neon
        ldrd            r4,  r5,  [sp, #36]
        ldrd            r6,  r7,  [sp, #44]
.ifc \bdmax, r8
        ldr             r8,  [sp, #52]
.endif
        movw            r11, #0x4081  // (1 << 14) | (1 << 7) | (1 << 0)
        mul             \mx, \mx, r11
        mul             \my, \my, r11
        add             \mx, \mx, r9  // mx, 8tap_h, 4tap_h
        add             \my, \my, r10 // my, 8tap_v, 4tap_v

.ifc \type, prep
        lsl             \d_strd, \w, #1
.endif

        vdup.16         q15, \bdmax            // bitdepth_max
        clz             \bdmax,  \bdmax
        clz             r9,  \w
        sub             \bdmax,  \bdmax,  #18  // intermediate_bits = clz(bitdepth_max) - 18
        tst             \mx, #(0x7f << 14)
        sub             r9,  r9,  #24
        add             lr,  \bdmax, #6        // 6 + intermediate_bits
        rsb             r12, \bdmax, #6        // 6 - intermediate_bits
        movrel          r11, X(mc_subpel_filters), -8
        bne             L(\type\()_8tap_h)
        tst             \my, #(0x7f << 14)
        bne             L(\type\()_8tap_v)
        b               \type\()_neon

L(\type\()_8tap_h):
        cmp             \w,  #4
        ubfx            r10, \mx, #7,  #7
        and             \mx, \mx, #0x7f
        it              gt
        movgt           \mx, r10
        tst             \my, #(0x7f << 14)
        add             \mx, r11, \mx, lsl #3
        bne             L(\type\()_8tap_hv)

        adr             r10, L(\type\()_8tap_h_tbl)
        vdup.32         q14, r12           // 6 - intermediate_bits
        ldr             r9,  [r10, r9, lsl #2]
        vneg.s32        q14, q14           // -(6-intermediate_bits)
.ifc \type, put
        vdup.16         q13, \bdmax        // intermediate_bits
.else
        vmov.i16        q13, #PREP_BIAS
.endif
        add             r10, r10, r9
.ifc \type, put
        vneg.s16        q13, q13           // -intermediate_bits
.endif
        bx              r10

        .align 2
L(\type\()_8tap_h_tbl):
        .word 1280f - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
        .word 640f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
        .word 320f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
        .word 160f  - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
        .word 80f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
        .word 40f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB
        .word 20f   - L(\type\()_8tap_h_tbl) + CONFIG_THUMB

20:     // 2xN h
.ifc \type, put
        add             \mx, \mx, #2
        vld1.32         {d0[]}, [\mx]
        sub             \src,  \src,  #2
        add             \ds2,  \dst,  \d_strd
        add             \sr2,  \src,  \s_strd
        lsl             \d_strd,  \d_strd,  #1
        lsl             \s_strd,  \s_strd,  #1
        vmovl.s8        q0,  d0
2:
        vld1.16         {q2}, [\src], \s_strd
        vld1.16         {q3}, [\sr2], \s_strd
        vext.8          d5,  d4,  d5,  #2
        vext.8          d7,  d6,  d7,  #2
        subs            \h,  \h,  #2
        vtrn.32         d4,  d6
        vtrn.32         d5,  d7
        vmull.s16       q1,  d4,  d0[0]
        vmlal.s16       q1,  d5,  d0[1]
        vmlal.s16       q1,  d6,  d0[2]
        vmlal.s16       q1,  d7,  d0[3]
        vrshl.s32       q1,  q1,  q14 // -(6-intermediate_bits)
        vqmovun.s32     d2,  q1
        vrshl.s16       d2,  d2,  d26 // -intermediate_bits
        vmin.u16        d2,  d2,  d30
        vst1.32         {d2[0]}, [\dst, :32], \d_strd
        vst1.32         {d2[1]}, [\ds2, :32], \d_strd
        bgt             2b
        pop             {r4-r11,pc}
.endif

40:     // 4xN h
        add             \mx, \mx, #2
        vld1.32         {d0[]}, [\mx]
        sub             \src,  \src,  #2
        add             \ds2,  \dst,  \d_strd
        add             \sr2,  \src,  \s_strd
        lsl             \d_strd,  \d_strd,  #1
        lsl             \s_strd,  \s_strd,  #1
        vmovl.s8        q0,  d0
4:
        vld1.16         {q8},  [\src], \s_strd
        vld1.16         {q11}, [\sr2], \s_strd
        vext.8          d18, d16, d17, #2
        vext.8          d19, d16, d17, #4
        vext.8          d20, d16, d17, #6
        vext.8          d24, d22, d23, #2
        vext.8          d25, d22, d23, #4
        vext.8          d21, d22, d23, #6
        subs            \h,  \h,  #2
        vmull.s16       q2,  d16, d0[0]
        vmlal.s16       q2,  d18, d0[1]
        vmlal.s16       q2,  d19, d0[2]
        vmlal.s16       q2,  d20, d0[3]
        vmull.s16       q3,  d22, d0[0]
        vmlal.s16       q3,  d24, d0[1]
        vmlal.s16       q3,  d25, d0[2]
        vmlal.s16       q3,  d21, d0[3]
        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
.ifc \type, put
        vqmovun.s32     d4,  q2
        vqmovun.s32     d5,  q3
        vrshl.s16       q2,  q2,  q13 // -intermediate_bits
        vmin.u16        q2,  q2,  q15
.else
        vmovn.s32       d4,  q2
        vmovn.s32       d5,  q3
        vsub.i16        q2,  q2,  q13 // PREP_BIAS
.endif
        vst1.16         {d4}, [\dst, :64], \d_strd
        vst1.16         {d5}, [\ds2, :64], \d_strd
        bgt             4b
        pop             {r4-r11,pc}

80:
160:
320:
640:
1280:   // 8xN, 16xN, 32xN, ... h
        vpush           {q4-q5}
        vld1.8          {d0}, [\mx, :64]
        sub             \src,  \src,  #6
        add             \ds2,  \dst,  \d_strd
        add             \sr2,  \src,  \s_strd
        lsl             \s_strd,  \s_strd,  #1
        vmovl.s8        q0,  d0

        sub             \s_strd,  \s_strd,  \w, lsl #1
        sub             \s_strd,  \s_strd,  #16
.ifc \type, put
        lsl             \d_strd,  \d_strd,  #1
        sub             \d_strd,  \d_strd,  \w, lsl #1
.endif
81:
        vld1.16         {q8,  q9},  [\src]!
        vld1.16         {q10, q11}, [\sr2]!
        mov             \mx, \w

8:
        vmull.s16       q1,  d16, d0[0]
        vmull.s16       q2,  d17, d0[0]
        vmull.s16       q3,  d20, d0[0]
        vmull.s16       q4,  d21, d0[0]
.irpc i, 1234567
        vext.8          q12, q8,  q9,  #(2*\i)
        vext.8          q5,  q10, q11, #(2*\i)
.if \i < 4
        vmlal.s16       q1,  d24, d0[\i]
        vmlal.s16       q2,  d25, d0[\i]
        vmlal.s16       q3,  d10, d0[\i]
        vmlal.s16       q4,  d11, d0[\i]
.else
        vmlal.s16       q1,  d24, d1[\i-4]
        vmlal.s16       q2,  d25, d1[\i-4]
        vmlal.s16       q3,  d10, d1[\i-4]
        vmlal.s16       q4,  d11, d1[\i-4]
.endif
.endr
        subs            \mx, \mx, #8
        vrshl.s32       q1,  q1,  q14 // -(6-intermediate_bits)
        vrshl.s32       q2,  q2,  q14 // -(6-intermediate_bits)
        vrshl.s32       q3,  q3,  q14 // -(6-intermediate_bits)
        vrshl.s32       q4,  q4,  q14 // -(6-intermediate_bits)
.ifc \type, put
        vqmovun.s32     d2,  q1
        vqmovun.s32     d3,  q2
        vqmovun.s32     d4,  q3
        vqmovun.s32     d5,  q4
        vrshl.s16       q1,  q1,  q13 // -intermediate_bits
        vrshl.s16       q2,  q2,  q13 // -intermediate_bits
        vmin.u16        q1,  q1,  q15
        vmin.u16        q2,  q2,  q15
.else
        vmovn.s32       d2,  q1
        vmovn.s32       d3,  q2
        vmovn.s32       d4,  q3
        vmovn.s32       d5,  q4
        vsub.i16        q1,  q1,  q13 // PREP_BIAS
        vsub.i16        q2,  q2,  q13 // PREP_BIAS
.endif
        vst1.16         {q1}, [\dst, :128]!
        vst1.16         {q2}, [\ds2, :128]!
        ble             9f

        vmov            q8,  q9
        vmov            q10, q11
        vld1.16         {q9},  [\src]!
        vld1.16         {q11}, [\sr2]!
        b               8b

9:
        add             \dst,  \dst,  \d_strd
        add             \ds2,  \ds2,  \d_strd
        add             \src,  \src,  \s_strd
        add             \sr2,  \sr2,  \s_strd

        subs            \h,  \h,  #2
        bgt             81b
        vpop            {q4-q5}
        pop             {r4-r11,pc}


L(\type\()_8tap_v):
        cmp             \h,  #4
        ubfx            r10, \my, #7,  #7
        and             \my, \my, #0x7f
        it              gt
        movgt           \my, r10
        add             \my, r11, \my, lsl #3

.ifc \type, prep
        vdup.32         q14, r12        // 6 - intermediate_bits
        vmov.i16        q15, #PREP_BIAS
.endif
        adr             r10, L(\type\()_8tap_v_tbl)
        ldr             r9,  [r10, r9, lsl #2]
.ifc \type, prep
        vneg.s32        q14, q14        // -(6-intermediate_bits)
.endif
        add             r10, r10, r9
        bx              r10

        .align 2
L(\type\()_8tap_v_tbl):
        .word 1280f - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
        .word 640f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
        .word 320f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
        .word 160f  - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
        .word 80f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
        .word 40f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB
        .word 20f   - L(\type\()_8tap_v_tbl) + CONFIG_THUMB

20:     // 2xN v
.ifc \type, put
        bgt             28f

        cmp             \h,  #2
        add             \my, \my, #2
        vld1.32         {d0[]}, [\my]
        sub             \src,  \src,  \s_strd
        add             \ds2,  \dst,  \d_strd
        add             \sr2,  \src,  \s_strd
        lsl             \s_strd,  \s_strd,  #1
        lsl             \d_strd,  \d_strd,  #1
        vmovl.s8        q0,  d0

        // 2x2 v
        load_32         \src, \sr2, \s_strd, d1, d2, d3, d4, d5
        interleave_1_32 d1,  d2,  d3,  d4,  d5
        bgt             24f
        vmull_vmlal_4   q8,  d1,  d2,  d3,  d4
        vqrshrun_s32    6,   q8,  d16
        vmin_u16        d30, d16
        vst1_32         \d_strd,  d16
        pop             {r4-r11,pc}

24:     // 2x4 v
        load_32         \sr2, \src, \s_strd, d6, d7
        interleave_1_32 d5,  d6,  d7
        vmull_vmlal_4   q8,  d1,  d2,  d3,  d4
        vmull_vmlal_4   q9,  d3,  d4,  d5,  d6
        vqrshrun_s32    6,   q8,  d16, q9,  d17
        vmin_u16        q15, q8
        vst1_32         \d_strd,  d16, d17
        pop             {r4-r11,pc}

28:     // 2x6, 2x8, 2x12, 2x16 v
        vld1.8          {d0}, [\my, :64]
        sub             \sr2,  \src,  \s_strd, lsl #1
        add             \ds2,  \dst,  \d_strd
        sub             \src,  \sr2,  \s_strd
        lsl             \d_strd,  \d_strd,  #1
        lsl             \s_strd,  \s_strd,  #1
        vmovl.s8        q0,  d0

        load_32         \src, \sr2, \s_strd, d2, d3, d4, d5, d6, d7, d16
        interleave_1_32 d2,  d3,  d4,  d5,  d6
        interleave_1_32 d6,  d7,  d16
216:
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=97 H=96 G=96

¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.