/* * Copyright © 2018, VideoLAN and dav1d authors * 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" .macro loop_filter wdfunction lpf_4_wd\wd\()_neon vabd.u16 d0, d22, d23 // abs(p1 - p0) vabd.u16 d1, d25, d24 // abs(q1 - q0) vabd.u16 d2, d23, d24 // abs(p0 - q0) vabd.u16 d3, d22, d25 // abs(p1 - q1).if \wd >= 6 vabd.u16 d4, d21, d22 // abs(p2 - p1) vabd.u16 d5, d26, d25 // abs(q2 - q1).endif.if \wd >= 8 vabd.u16 d6, d20, d21 // abs(p3 - p2) vabd.u16 d7, d27, d26 // abs(q3 - q3).endif.if \wd >= 6 vmax.u16 d4, d4, d5.endif vqadd.u16 d2, d2, d2 // abs(p0 - q0) * 2.if \wd >= 8 vmax.u16 d6, d6, d7.endif vshr.u16 d3, d3, #1.if \wd >= 8 vmax.u16 d4, d4, d6.endif vmax.u16 d0, d0, d1 // max(abs(p1 - p0), abs(q1 - q0)) vqadd.u16 d2, d2, d3 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1.if \wd >= 6 vmax.u16 d4, d0, d4 vcge.u16 d1, d11, d4 // max(abs(p1 - p0), abs(q1 - q0), abs(), abs(), ...) <= I.else vcge.u16 d1, d11, d0 // max(abs(p1 - p0), abs(q1 - q0)) <= I.endif vcge.u16 d2, d10, d2 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 <= E vand d1, d1, d2 // fm && wd >= 4 (implicit).if \wd >= 6 vmov d14, d1 // fm && wd > 4 (implicit).endif.if \wd >= 16 vmov d15, d1 // fm && wd == 16 (implicit).endif vmov r10, r11, d1 orrs r10, r10, r11 beq 9f // if (!fm || wd < 4) return; .if \wd >= 6 vmov.i16 d10, #1 vabd.u16 d2, d21, d23 // abs(p2 - p0) vabd.u16 d3, d22, d23 // abs(p1 - p0) vabd.u16 d4, d25, d24 // abs(q1 - q0) vabd.u16 d5, d26, d24 // abs(q2 - q0) vdup.16 d9, r9 // bitdepth_min_8.if \wd >= 8 vabd.u16 d6, d20, d23 // abs(p3 - p0) vabd.u16 d7, d27, d24 // abs(q3 - q0).endif vmax.u16 d2, d2, d3 vmax.u16 d4, d4, d5.if \wd >= 8 vmax.u16 d6, d6, d7.endif vmax.u16 d2, d2, d4 vshl.u16 d10, d10, d9 // F = 1 << bitdepth_min_8.if \wd >= 8 vmax.u16 d2, d2, d6.endif .if \wd == 16 vabd.u16 d3, d17, d23 // abs(p6 - p0) vabd.u16 d4, d18, d23 // abs(p5 - p0) vabd.u16 d5, d19, d23 // abs(p4 - p0).endif vcge.u16 d2, d10, d2 // flat8in.if \wd == 16 vabd.u16 d6, d28, d24 // abs(q4 - q0) vabd.u16 d7, d29, d24 // abs(q5 - q0) vabd.u16 d8, d30, d24 // abs(q6 - q0).endif vand d14, d2, d14 // flat8in && fm && wd > 4 vbic d1, d1, d14 // fm && wd >= 4 && !flat8in.if \wd == 16 vmax.u16 d3, d3, d4 vmax.u16 d5, d5, d6.endif vmov r10, r11, d1.if \wd == 16 vmax.u16 d7, d7, d8 vmax.u16 d3, d3, d5 vmax.u16 d3, d3, d7 vcge.u16 d3, d10, d3 // flat8out.endif orrs r10, r10, r11.if \wd == 16 vand d15, d15, d3 // flat8out && fm && wd == 16 vand d15, d15, d14 // flat8out && flat8in && fm && wd == 16 vbic d14, d14, d15 // flat8in && fm && wd >= 4 && !flat8out.endif beq 1f // skip wd == 4 case.endif vdup.16 d3, r8 // bitdepth_max vsub.u16 d2, d22, d25 // p1 - q1 vshr.u16 d3, d3, #1 // 128 << bitdepth_min_8 - 1 vcgt.u16 d0, d0, d12 // hev vmvn d9, d3 // - 128 * (1 << bitdepth_min_8) vmin.s16 d2, d2, d3 // iclip_diff(p1 - q1) vmax.s16 d2, d2, d9 // iclip_diff(p1 - q1) vand d4, d2, d0 // if (hev) iclip_diff(p1 - q1) vsub.u16 d2, d24, d23 vmov.i16 d6, #3 vbic d0, d1, d0 // (fm && wd >= 4 && !hev) vmul.i16 d2, d2, d6 vmov.i16 d6, #4 vadd.i16 d2, d2, d4 vmin.s16 d2, d2, d3 // f = iclip_diff() vmov.i16 d7, #3 vmax.s16 d2, d2, d9 // f = iclip_diff() vqadd.s16 d4, d6, d2 // f + 4 vqadd.s16 d5, d7, d2 // f + 3 vmin.s16 d4, d4, d3 // imin(f + 4, 128 << bitdepth_min_8 - 1) vmin.s16 d5, d5, d3 // imin(f + 3, 128 << bitdepth_min_8 - 1) vshr.s16 d4, d4, #3 // f1 vshr.s16 d5, d5, #3 // f2 vmov.i16 d9, #0 vdup.16 d3, r8 // bitdepth_max vqadd.s16 d2, d23, d5 // p0 + f2 vqsub.s16 d6, d24, d4 // q0 - f1 vrshr.s16 d4, d4, #1 // (f1 + 1) >> 1 vmin.s16 d2, d2, d3 // out p0 = iclip_pixel() vmin.s16 d6, d6, d3 // out q0 = iclip_pixel() vmax.s16 d2, d2, d9 // out p0 = iclip_pixel() vmax.s16 d6, d6, d9 // out q0 = iclip_pixel() vbit d23, d2, d1 // if (fm && wd >= 4) vbit d24, d6, d1 // if (fm && wd >= 4) vqadd.s16 d2, d22, d4 // p1 + f vqsub.s16 d6, d25, d4 // q1 - f vmin.s16 d2, d2, d3 // out p1 = iclip_pixel() vmin.s16 d6, d6, d3 // out q1 = iclip_pixel() vmax.s16 d2, d2, d9 // out p1 = iclip_pixel() vmax.s16 d6, d6, d9 // out q1 = iclip_pixel() vbit d22, d2, d0 // if (fm && wd >= 4 && !hev) vbit d25, d6, d0 // if (fm && wd >= 4 && !hev)1: .if \wd == 6 vmov r10, r11, d14 orrs r10, r10, r11 beq 2f // skip if there's no flat8in vadd.i16 d0, d21, d21 // p2 * 2 vadd.i16 d2, d21, d22 // p2 + p1 vadd.i16 d4, d22, d23 // p1 + p0 vadd.i16 d6, d23, d24 // p0 + q0 vadd.i16 d8, d0, d2 vadd.i16 d10, d4, d6 vadd.i16 d12, d24, d25 // q0 + q1 vadd.i16 d8, d8, d10 vsub.i16 d12, d12, d0 vadd.i16 d10, d25, d26 // q1 + q2 vrshr.u16 d0, d8, #3 // out p1 vadd.i16 d8, d8, d12 vsub.i16 d10, d10, d2 vadd.i16 d12, d26, d26 // q2 + q2 vrshr.u16 d1, d8, #3 // out p0 vadd.i16 d8, d8, d10 vsub.i16 d12, d12, d4 vrshr.u16 d2, d8, #3 // out q0 vbit d22, d0, d14 // p1 if (flat8in) vadd.i16 d8, d8, d12 vbit d23, d1, d14 // p0 if (flat8in) vrshr.u16 d3, d8, #3 // out q1 vbit d24, d2, d14 // q0 if (flat8in) vbit d25, d3, d14 // q1 if (flat8in).elseif \wd >= 8 vmov r10, r11, d14 orrs r10, r10, r11.if \wd == 8 beq 8f // skip if there's no flat8in.else beq 2f // skip if there's no flat8in.endif vadd.i16 d0, d20, d21 // p3 + p2 vadd.i16 d2, d22, d25 // p1 + q1 vadd.i16 d4, d20, d22 // p3 + p1 vadd.i16 d6, d23, d26 // p0 + q2 vadd.i16 d8, d0, d0 // 2 * (p3 + p2) vadd.i16 d9, d23, d24 // p0 + q0 vadd.i16 d8, d8, d4 // + p3 + p1 vsub.i16 d2, d2, d0 // p1 + q1 - p3 - p2 vadd.i16 d8, d8, d9 // + p0 + q0 vsub.i16 d6, d6, d4 // p0 + q2 - p3 - p1 vrshr.u16 d10, d8, #3 // out p2 vadd.i16 d8, d8, d2 vadd.i16 d0, d20, d23 // p3 + p0 vadd.i16 d2, d24, d27 // q0 + q3 vrshr.u16 d11, d8, #3 // out p1 vadd.i16 d8, d8, d6 vsub.i16 d2, d2, d0 // q0 + q3 - p3 - p0 vadd.i16 d4, d21, d24 // p2 + q0 vadd.i16 d6, d25, d27 // q1 + q3 vrshr.u16 d12, d8, #3 // out p0 vadd.i16 d8, d8, d2 vsub.i16 d6, d6, d4 // q1 + q3 - p2 - q0 vadd.i16 d0, d22, d25 // p1 + q1 vadd.i16 d2, d26, d27 // q2 + q3 vrshr.u16 d13, d8, #3 // out q0 vadd.i16 d8, d8, d6 vsub.i16 d2, d2, d0 // q2 + q3 - p1 - q1 vrshr.u16 d0, d8, #3 // out q1 vadd.i16 d8, d8, d2 vbit d21, d10, d14 vbit d22, d11, d14 vbit d23, d12, d14 vrshr.u16 d1, d8, #3 // out q2 vbit d24, d13, d14 vbit d25, d0, d14 vbit d26, d1, d14.endif2:.if \wd == 16 vmov r10, r11, d15 orrs r10, r10, r11 bne 1f // check if flat8out is needed vmov r10, r11, d14 orrs r10, r10, r11 beq 8f // if there was no flat8in, just write the inner 4 pixels b 7f // if flat8in was used, write the inner 6 pixels1: vadd.i16 d2, d17, d17 // p6 + p6 vadd.i16 d4, d17, d18 // p6 + p5 vadd.i16 d6, d17, d19 // p6 + p4 vadd.i16 d8, d17, d20 // p6 + p3 vadd.i16 d12, d2, d4 vadd.i16 d10, d6, d8 vadd.i16 d6, d17, d21 // p6 + p2 vadd.i16 d12, d12, d10 vadd.i16 d8, d17, d22 // p6 + p1 vadd.i16 d10, d18, d23 // p5 + p0 vadd.i16 d6, d6, d8 vadd.i16 d8, d19, d24 // p4 + q0 vadd.i16 d12, d12, d6 vadd.i16 d10, d10, d8 vadd.i16 d6, d20, d25 // p3 + q1 vadd.i16 d12, d12, d10 vsub.i16 d6, d6, d2 vadd.i16 d2, d21, d26 // p2 + q2 vrshr.u16 d0, d12, #4 // out p5 vadd.i16 d12, d12, d6 // - (p6 + p6) + (p3 + q1) vsub.i16 d2, d2, d4 vadd.i16 d4, d22, d27 // p1 + q3 vadd.i16 d6, d17, d19 // p6 + p4 vrshr.u16 d1, d12, #4 // out p4 vadd.i16 d12, d12, d2 // - (p6 + p5) + (p2 + q2) vsub.i16 d4, d4, d6 vadd.i16 d6, d23, d28 // p0 + q4 vadd.i16 d8, d17, d20 // p6 + p3 vrshr.u16 d2, d12, #4 // out p3 vadd.i16 d12, d12, d4 // - (p6 + p4) + (p1 + q3) vsub.i16 d6, d6, d8 vadd.i16 d8, d24, d29 // q0 + q5 vadd.i16 d4, d17, d21 // p6 + p2 vrshr.u16 d3, d12, #4 // out p2 vadd.i16 d12, d12, d6 // - (p6 + p3) + (p0 + q4) vsub.i16 d8, d8, d4 vadd.i16 d6, d25, d30 // q1 + q6 vadd.i16 d10, d17, d22 // p6 + p1 vrshr.u16 d4, d12, #4 // out p1 vadd.i16 d12, d12, d8 // - (p6 + p2) + (q0 + q5) vsub.i16 d6, d6, d10 vadd.i16 d8, d26, d30 // q2 + q6 vbif d0, d18, d15 // out p5 vadd.i16 d10, d18, d23 // p5 + p0 vrshr.u16 d5, d12, #4 // out p0 vadd.i16 d12, d12, d6 // - (p6 + p1) + (q1 + q6) vsub.i16 d8, d8, d10 vadd.i16 d10, d27, d30 // q3 + q6 vbif d1, d19, d15 // out p4 vadd.i16 d18, d19, d24 // p4 + q0 vrshr.u16 d6, d12, #4 // out q0 vadd.i16 d12, d12, d8 // - (p5 + p0) + (q2 + q6) vsub.i16 d10, d10, d18 vadd.i16 d8, d28, d30 // q4 + q6 vbif d2, d20, d15 // out p3 vadd.i16 d18, d20, d25 // p3 + q1 vrshr.u16 d7, d12, #4 // out q1 vadd.i16 d12, d12, d10 // - (p4 + q0) + (q3 + q6) vsub.i16 d18, d8, d18 vadd.i16 d10, d29, d30 // q5 + q6 vbif d3, d21, d15 // out p2 vadd.i16 d20, d21, d26 // p2 + q2 vrshr.u16 d8, d12, #4 // out q2 vadd.i16 d12, d12, d18 // - (p3 + q1) + (q4 + q6) vsub.i16 d10, d10, d20 vadd.i16 d18, d30, d30 // q6 + q6 vbif d4, d22, d15 // out p1 vadd.i16 d20, d22, d27 // p1 + q3 vrshr.u16 d9, d12, #4 // out q3 vadd.i16 d12, d12, d10 // - (p2 + q2) + (q5 + q6) vsub.i16 d18, d18, d20 vbif d5, d23, d15 // out p0 vrshr.u16 d10, d12, #4 // out q4 vadd.i16 d12, d12, d18 // - (p1 + q3) + (q6 + q6) vrshr.u16 d11, d12, #4 // out q5 vbif d6, d24, d15 // out q0 vbif d7, d25, d15 // out q1 vbif d8, d26, d15 // out q2 vbif d9, d27, d15 // out q3 vbif d10, d28, d15 // out q4 vbif d11, d29, d15 // out q5.endif bx lr.if \wd == 167: // Return to a shorter epilogue, writing only the inner 6 pixels bx r6.endif.if \wd >= 88: // Return to a shorter epilogue, writing only the inner 4 pixels bx r7.endif9: // Return directly without writing back any pixels bx r12endfunc.endm loop_filter 16loop_filter 8loop_filter 6loop_filter 4 .macro lpf_4_wd16 adr r6, 7f + CONFIG_THUMB adr r7, 8f + CONFIG_THUMB bl lpf_4_wd16_neon.endm .macro lpf_4_wd8 adr r7, 8f + CONFIG_THUMB bl lpf_4_wd8_neon.endm .macro lpf_4_wd6 bl lpf_4_wd6_neon.endm .macro lpf_4_wd4 bl lpf_4_wd4_neon.endm function lpf_v_4_4_neon mov r12, lr sub r10, r0, r1, lsl #1 vld1.16 {d22}, [r10, :64], r1 // p1 vld1.16 {d24}, [r0, :64], r1 // q0 vld1.16 {d23}, [r10, :64], r1 // p0 vld1.16 {d25}, [r0, :64], r1 // q1 sub r0, r0, r1, lsl #1 lpf_4_wd4 sub r10, r0, r1, lsl #1 vst1.16 {d22}, [r10, :64], r1 // p1 vst1.16 {d24}, [r0, :64], r1 // q0 vst1.16 {d23}, [r10, :64], r1 // p0 vst1.16 {d25}, [r0, :64], r1 // q1 sub r0, r0, r1, lsl #1 bx r12endfunc function lpf_h_4_4_neon mov r12, lr sub r10, r0, #4 add r0, r10, r1, lsl #1 vld1.16 {d22}, [r10], r1 vld1.16 {d24}, [r0], r1 vld1.16 {d23}, [r10], r1 vld1.16 {d25}, [r0], r1 add r0, r0, #4 transpose_4x4h q11, q12, d22, d23, d24, d25 lpf_4_wd4 sub r10, r0, r1, lsl #2 sub r10, r10, #4 transpose_4x4h q11, q12, d22, d23, d24, d25 add r0, r10, r1, lsl #1 vst1.16 {d22}, [r10], r1 vst1.16 {d24}, [r0], r1 vst1.16 {d23}, [r10], r1 vst1.16 {d25}, [r0], r1 add r0, r0, #4 bx r12endfunc function lpf_v_6_4_neon mov r12, lr sub r10, r0, r1, lsl #1 sub r10, r10, r1 vld1.16 {d21}, [r10, :64], r1 // p2 vld1.16 {d24}, [r0, :64], r1 // q0 vld1.16 {d22}, [r10, :64], r1 // p1 vld1.16 {d25}, [r0, :64], r1 // q1 vld1.16 {d23}, [r10, :64], r1 // p0 vld1.16 {d26}, [r0, :64], r1 // q2 sub r0, r0, r1, lsl #1 sub r0, r0, r1 lpf_4_wd6 sub r10, r0, r1, lsl #1 vst1.16 {d22}, [r10, :64], r1 // p1 vst1.16 {d24}, [r0, :64], r1 // q0 vst1.16 {d23}, [r10, :64], r1 // p0 vst1.16 {d25}, [r0, :64], r1 // q1 sub r0, r0, r1, lsl #1 bx r12endfunc function lpf_h_6_4_neon mov r12, lr sub r10, r0, #8 vld1.16 {d20}, [r10, :64], r1 vld1.16 {d24}, [r0, :64], r1 vld1.16 {d21}, [r10, :64], r1 vld1.16 {d25}, [r0, :64], r1 vld1.16 {d22}, [r10, :64], r1 vld1.16 {d26}, [r0, :64], r1 vld1.16 {d23}, [r10, :64], r1 vld1.16 {d27}, [r0, :64], r1 transpose_4x4h q10, q11, d20, d21, d22, d23 transpose_4x4h q12, q13, d24, d25, d26, d27 lpf_4_wd6 sub r0, r0, #4 transpose_4x4h q11, q12, d22, d23, d24, d25 sub r10, r0, r1, lsl #2 sub r0, r0, r1, lsl #1 vst1.16 {d22}, [r10], r1 vst1.16 {d24}, [r0], r1 vst1.16 {d23}, [r10], r1 vst1.16 {d25}, [r0], r1 add r0, r0, #4 bx r12endfunc function lpf_v_8_4_neon mov r12, lr sub r10, r0, r1, lsl #2 vld1.16 {d20}, [r10, :64], r1 // p3 vld1.16 {d24}, [r0, :64], r1 // q0Lines 1–500 of 860. Load more
/* * Copyright © 2018, VideoLAN and dav1d authors * 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" .macro loop_filter wd function lpf_4_wd\wd\()_neon vabd.u16 d0, d22, d23 // abs(p1 - p0) vabd.u16 d1, d25, d24 // abs(q1 - q0) vabd.u16 d2, d23, d24 // abs(p0 - q0) vabd.u16 d3, d22, d25 // abs(p1 - q1) .if \wd >= 6 vabd.u16 d4, d21, d22 // abs(p2 - p1) vabd.u16 d5, d26, d25 // abs(q2 - q1) .endif .if \wd >= 8 vabd.u16 d6, d20, d21 // abs(p3 - p2) vabd.u16 d7, d27, d26 // abs(q3 - q3) .endif .if \wd >= 6 vmax.u16 d4, d4, d5 .endif vqadd.u16 d2, d2, d2 // abs(p0 - q0) * 2 .if \wd >= 8 vmax.u16 d6, d6, d7 .endif vshr.u16 d3, d3, #1 .if \wd >= 8 vmax.u16 d4, d4, d6 .endif vmax.u16 d0, d0, d1 // max(abs(p1 - p0), abs(q1 - q0)) vqadd.u16 d2, d2, d3 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 .if \wd >= 6 vmax.u16 d4, d0, d4 vcge.u16 d1, d11, d4 // max(abs(p1 - p0), abs(q1 - q0), abs(), abs(), ...) <= I .else vcge.u16 d1, d11, d0 // max(abs(p1 - p0), abs(q1 - q0)) <= I .endif vcge.u16 d2, d10, d2 // abs(p0 - q0) * 2 + abs(p1 - q1) >> 1 <= E vand d1, d1, d2 // fm && wd >= 4 (implicit) .if \wd >= 6 vmov d14, d1 // fm && wd > 4 (implicit) .endif .if \wd >= 16 vmov d15, d1 // fm && wd == 16 (implicit) .endif vmov r10, r11, d1 orrs r10, r10, r11 beq 9f // if (!fm || wd < 4) return; .if \wd >= 6 vmov.i16 d10, #1 vabd.u16 d2, d21, d23 // abs(p2 - p0) vabd.u16 d3, d22, d23 // abs(p1 - p0) vabd.u16 d4, d25, d24 // abs(q1 - q0) vabd.u16 d5, d26, d24 // abs(q2 - q0) vdup.16 d9, r9 // bitdepth_min_8 .if \wd >= 8 vabd.u16 d6, d20, d23 // abs(p3 - p0) vabd.u16 d7, d27, d24 // abs(q3 - q0) .endif vmax.u16 d2, d2, d3 vmax.u16 d4, d4, d5 .if \wd >= 8 vmax.u16 d6, d6, d7 .endif vmax.u16 d2, d2, d4 vshl.u16 d10, d10, d9 // F = 1 << bitdepth_min_8 .if \wd >= 8 vmax.u16 d2, d2, d6 .endif .if \wd == 16 vabd.u16 d3, d17, d23 // abs(p6 - p0) vabd.u16 d4, d18, d23 // abs(p5 - p0) vabd.u16 d5, d19, d23 // abs(p4 - p0) .endif vcge.u16 d2, d10, d2 // flat8in .if \wd == 16 vabd.u16 d6, d28, d24 // abs(q4 - q0) vabd.u16 d7, d29, d24 // abs(q5 - q0) vabd.u16 d8, d30, d24 // abs(q6 - q0) .endif vand d14, d2, d14 // flat8in && fm && wd > 4 vbic d1, d1, d14 // fm && wd >= 4 && !flat8in .if \wd == 16 vmax.u16 d3, d3, d4 vmax.u16 d5, d5, d6 .endif vmov r10, r11, d1 .if \wd == 16 vmax.u16 d7, d7, d8 vmax.u16 d3, d3, d5 vmax.u16 d3, d3, d7 vcge.u16 d3, d10, d3 // flat8out .endif orrs r10, r10, r11 .if \wd == 16 vand d15, d15, d3 // flat8out && fm && wd == 16 vand d15, d15, d14 // flat8out && flat8in && fm && wd == 16 vbic d14, d14, d15 // flat8in && fm && wd >= 4 && !flat8out .endif beq 1f // skip wd == 4 case .endif vdup.16 d3, r8 // bitdepth_max vsub.u16 d2, d22, d25 // p1 - q1 vshr.u16 d3, d3, #1 // 128 << bitdepth_min_8 - 1 vcgt.u16 d0, d0, d12 // hev vmvn d9, d3 // - 128 * (1 << bitdepth_min_8) vmin.s16 d2, d2, d3 // iclip_diff(p1 - q1) vmax.s16 d2, d2, d9 // iclip_diff(p1 - q1) vand d4, d2, d0 // if (hev) iclip_diff(p1 - q1) vsub.u16 d2, d24, d23 vmov.i16 d6, #3 vbic d0, d1, d0 // (fm && wd >= 4 && !hev) vmul.i16 d2, d2, d6 vmov.i16 d6, #4 vadd.i16 d2, d2, d4 vmin.s16 d2, d2, d3 // f = iclip_diff() vmov.i16 d7, #3 vmax.s16 d2, d2, d9 // f = iclip_diff() vqadd.s16 d4, d6, d2 // f + 4 vqadd.s16 d5, d7, d2 // f + 3 vmin.s16 d4, d4, d3 // imin(f + 4, 128 << bitdepth_min_8 - 1) vmin.s16 d5, d5, d3 // imin(f + 3, 128 << bitdepth_min_8 - 1) vshr.s16 d4, d4, #3 // f1 vshr.s16 d5, d5, #3 // f2 vmov.i16 d9, #0 vdup.16 d3, r8 // bitdepth_max vqadd.s16 d2, d23, d5 // p0 + f2 vqsub.s16 d6, d24, d4 // q0 - f1 vrshr.s16 d4, d4, #1 // (f1 + 1) >> 1 vmin.s16 d2, d2, d3 // out p0 = iclip_pixel() vmin.s16 d6, d6, d3 // out q0 = iclip_pixel() vmax.s16 d2, d2, d9 // out p0 = iclip_pixel() vmax.s16 d6, d6, d9 // out q0 = iclip_pixel() vbit d23, d2, d1 // if (fm && wd >= 4) vbit d24, d6, d1 // if (fm && wd >= 4) vqadd.s16 d2, d22, d4 // p1 + f vqsub.s16 d6, d25, d4 // q1 - f vmin.s16 d2, d2, d3 // out p1 = iclip_pixel() vmin.s16 d6, d6, d3 // out q1 = iclip_pixel() vmax.s16 d2, d2, d9 // out p1 = iclip_pixel() vmax.s16 d6, d6, d9 // out q1 = iclip_pixel() vbit d22, d2, d0 // if (fm && wd >= 4 && !hev) vbit d25, d6, d0 // if (fm && wd >= 4 && !hev) 1: .if \wd == 6 vmov r10, r11, d14 orrs r10, r10, r11 beq 2f // skip if there's no flat8in vadd.i16 d0, d21, d21 // p2 * 2 vadd.i16 d2, d21, d22 // p2 + p1 vadd.i16 d4, d22, d23 // p1 + p0 vadd.i16 d6, d23, d24 // p0 + q0 vadd.i16 d8, d0, d2 vadd.i16 d10, d4, d6 vadd.i16 d12, d24, d25 // q0 + q1 vadd.i16 d8, d8, d10 vsub.i16 d12, d12, d0 vadd.i16 d10, d25, d26 // q1 + q2 vrshr.u16 d0, d8, #3 // out p1 vadd.i16 d8, d8, d12 vsub.i16 d10, d10, d2 vadd.i16 d12, d26, d26 // q2 + q2 vrshr.u16 d1, d8, #3 // out p0 vadd.i16 d8, d8, d10 vsub.i16 d12, d12, d4 vrshr.u16 d2, d8, #3 // out q0 vbit d22, d0, d14 // p1 if (flat8in) vadd.i16 d8, d8, d12 vbit d23, d1, d14 // p0 if (flat8in) vrshr.u16 d3, d8, #3 // out q1 vbit d24, d2, d14 // q0 if (flat8in) vbit d25, d3, d14 // q1 if (flat8in) .elseif \wd >= 8 vmov r10, r11, d14 orrs r10, r10, r11 .if \wd == 8 beq 8f // skip if there's no flat8in .else beq 2f // skip if there's no flat8in .endif vadd.i16 d0, d20, d21 // p3 + p2 vadd.i16 d2, d22, d25 // p1 + q1 vadd.i16 d4, d20, d22 // p3 + p1 vadd.i16 d6, d23, d26 // p0 + q2 vadd.i16 d8, d0, d0 // 2 * (p3 + p2) vadd.i16 d9, d23, d24 // p0 + q0 vadd.i16 d8, d8, d4 // + p3 + p1 vsub.i16 d2, d2, d0 // p1 + q1 - p3 - p2 vadd.i16 d8, d8, d9 // + p0 + q0 vsub.i16 d6, d6, d4 // p0 + q2 - p3 - p1 vrshr.u16 d10, d8, #3 // out p2 vadd.i16 d8, d8, d2 vadd.i16 d0, d20, d23 // p3 + p0 vadd.i16 d2, d24, d27 // q0 + q3 vrshr.u16 d11, d8, #3 // out p1 vadd.i16 d8, d8, d6 vsub.i16 d2, d2, d0 // q0 + q3 - p3 - p0 vadd.i16 d4, d21, d24 // p2 + q0 vadd.i16 d6, d25, d27 // q1 + q3 vrshr.u16 d12, d8, #3 // out p0 vadd.i16 d8, d8, d2 vsub.i16 d6, d6, d4 // q1 + q3 - p2 - q0 vadd.i16 d0, d22, d25 // p1 + q1 vadd.i16 d2, d26, d27 // q2 + q3 vrshr.u16 d13, d8, #3 // out q0 vadd.i16 d8, d8, d6 vsub.i16 d2, d2, d0 // q2 + q3 - p1 - q1 vrshr.u16 d0, d8, #3 // out q1 vadd.i16 d8, d8, d2 vbit d21, d10, d14 vbit d22, d11, d14 vbit d23, d12, d14 vrshr.u16 d1, d8, #3 // out q2 vbit d24, d13, d14 vbit d25, d0, d14 vbit d26, d1, d14 .endif 2: .if \wd == 16 vmov r10, r11, d15 orrs r10, r10, r11 bne 1f // check if flat8out is needed vmov r10, r11, d14 orrs r10, r10, r11 beq 8f // if there was no flat8in, just write the inner 4 pixels b 7f // if flat8in was used, write the inner 6 pixels 1: vadd.i16 d2, d17, d17 // p6 + p6 vadd.i16 d4, d17, d18 // p6 + p5 vadd.i16 d6, d17, d19 // p6 + p4 vadd.i16 d8, d17, d20 // p6 + p3 vadd.i16 d12, d2, d4 vadd.i16 d10, d6, d8 vadd.i16 d6, d17, d21 // p6 + p2 vadd.i16 d12, d12, d10 vadd.i16 d8, d17, d22 // p6 + p1 vadd.i16 d10, d18, d23 // p5 + p0 vadd.i16 d6, d6, d8 vadd.i16 d8, d19, d24 // p4 + q0 vadd.i16 d12, d12, d6 vadd.i16 d10, d10, d8 vadd.i16 d6, d20, d25 // p3 + q1 vadd.i16 d12, d12, d10 vsub.i16 d6, d6, d2 vadd.i16 d2, d21, d26 // p2 + q2 vrshr.u16 d0, d12, #4 // out p5 vadd.i16 d12, d12, d6 // - (p6 + p6) + (p3 + q1) vsub.i16 d2, d2, d4 vadd.i16 d4, d22, d27 // p1 + q3 vadd.i16 d6, d17, d19 // p6 + p4 vrshr.u16 d1, d12, #4 // out p4 vadd.i16 d12, d12, d2 // - (p6 + p5) + (p2 + q2) vsub.i16 d4, d4, d6 vadd.i16 d6, d23, d28 // p0 + q4 vadd.i16 d8, d17, d20 // p6 + p3 vrshr.u16 d2, d12, #4 // out p3 vadd.i16 d12, d12, d4 // - (p6 + p4) + (p1 + q3) vsub.i16 d6, d6, d8 vadd.i16 d8, d24, d29 // q0 + q5 vadd.i16 d4, d17, d21 // p6 + p2 vrshr.u16 d3, d12, #4 // out p2 vadd.i16 d12, d12, d6 // - (p6 + p3) + (p0 + q4) vsub.i16 d8, d8, d4 vadd.i16 d6, d25, d30 // q1 + q6 vadd.i16 d10, d17, d22 // p6 + p1 vrshr.u16 d4, d12, #4 // out p1 vadd.i16 d12, d12, d8 // - (p6 + p2) + (q0 + q5) vsub.i16 d6, d6, d10 vadd.i16 d8, d26, d30 // q2 + q6 vbif d0, d18, d15 // out p5 vadd.i16 d10, d18, d23 // p5 + p0 vrshr.u16 d5, d12, #4 // out p0 vadd.i16 d12, d12, d6 // - (p6 + p1) + (q1 + q6) vsub.i16 d8, d8, d10 vadd.i16 d10, d27, d30 // q3 + q6 vbif d1, d19, d15 // out p4 vadd.i16 d18, d19, d24 // p4 + q0 vrshr.u16 d6, d12, #4 // out q0 vadd.i16 d12, d12, d8 // - (p5 + p0) + (q2 + q6) vsub.i16 d10, d10, d18 vadd.i16 d8, d28, d30 // q4 + q6 vbif d2, d20, d15 // out p3 vadd.i16 d18, d20, d25 // p3 + q1 vrshr.u16 d7, d12, #4 // out q1 vadd.i16 d12, d12, d10 // - (p4 + q0) + (q3 + q6) vsub.i16 d18, d8, d18 vadd.i16 d10, d29, d30 // q5 + q6 vbif d3, d21, d15 // out p2 vadd.i16 d20, d21, d26 // p2 + q2 vrshr.u16 d8, d12, #4 // out q2 vadd.i16 d12, d12, d18 // - (p3 + q1) + (q4 + q6) vsub.i16 d10, d10, d20 vadd.i16 d18, d30, d30 // q6 + q6 vbif d4, d22, d15 // out p1 vadd.i16 d20, d22, d27 // p1 + q3 vrshr.u16 d9, d12, #4 // out q3 vadd.i16 d12, d12, d10 // - (p2 + q2) + (q5 + q6) vsub.i16 d18, d18, d20 vbif d5, d23, d15 // out p0 vrshr.u16 d10, d12, #4 // out q4 vadd.i16 d12, d12, d18 // - (p1 + q3) + (q6 + q6) vrshr.u16 d11, d12, #4 // out q5 vbif d6, d24, d15 // out q0 vbif d7, d25, d15 // out q1 vbif d8, d26, d15 // out q2 vbif d9, d27, d15 // out q3 vbif d10, d28, d15 // out q4 vbif d11, d29, d15 // out q5 .endif bx lr .if \wd == 16 7: // Return to a shorter epilogue, writing only the inner 6 pixels bx r6 .endif .if \wd >= 8 8: // Return to a shorter epilogue, writing only the inner 4 pixels bx r7 .endif 9: // Return directly without writing back any pixels bx r12 endfunc .endm loop_filter 16 loop_filter 8 loop_filter 6 loop_filter 4 .macro lpf_4_wd16 adr r6, 7f + CONFIG_THUMB adr r7, 8f + CONFIG_THUMB bl lpf_4_wd16_neon .endm .macro lpf_4_wd8 adr r7, 8f + CONFIG_THUMB bl lpf_4_wd8_neon .endm .macro lpf_4_wd6 bl lpf_4_wd6_neon .endm .macro lpf_4_wd4 bl lpf_4_wd4_neon .endm function lpf_v_4_4_neon mov r12, lr sub r10, r0, r1, lsl #1 vld1.16 {d22}, [r10, :64], r1 // p1 vld1.16 {d24}, [r0, :64], r1 // q0 vld1.16 {d23}, [r10, :64], r1 // p0 vld1.16 {d25}, [r0, :64], r1 // q1 sub r0, r0, r1, lsl #1 lpf_4_wd4 sub r10, r0, r1, lsl #1 vst1.16 {d22}, [r10, :64], r1 // p1 vst1.16 {d24}, [r0, :64], r1 // q0 vst1.16 {d23}, [r10, :64], r1 // p0 vst1.16 {d25}, [r0, :64], r1 // q1 sub r0, r0, r1, lsl #1 bx r12 endfunc function lpf_h_4_4_neon mov r12, lr sub r10, r0, #4 add r0, r10, r1, lsl #1 vld1.16 {d22}, [r10], r1 vld1.16 {d24}, [r0], r1 vld1.16 {d23}, [r10], r1 vld1.16 {d25}, [r0], r1 add r0, r0, #4 transpose_4x4h q11, q12, d22, d23, d24, d25 lpf_4_wd4 sub r10, r0, r1, lsl #2 sub r10, r10, #4 transpose_4x4h q11, q12, d22, d23, d24, d25 add r0, r10, r1, lsl #1 vst1.16 {d22}, [r10], r1 vst1.16 {d24}, [r0], r1 vst1.16 {d23}, [r10], r1 vst1.16 {d25}, [r0], r1 add r0, r0, #4 bx r12 endfunc function lpf_v_6_4_neon mov r12, lr sub r10, r0, r1, lsl #1 sub r10, r10, r1 vld1.16 {d21}, [r10, :64], r1 // p2 vld1.16 {d24}, [r0, :64], r1 // q0 vld1.16 {d22}, [r10, :64], r1 // p1 vld1.16 {d25}, [r0, :64], r1 // q1 vld1.16 {d23}, [r10, :64], r1 // p0 vld1.16 {d26}, [r0, :64], r1 // q2 sub r0, r0, r1, lsl #1 sub r0, r0, r1 lpf_4_wd6 sub r10, r0, r1, lsl #1 vst1.16 {d22}, [r10, :64], r1 // p1 vst1.16 {d24}, [r0, :64], r1 // q0 vst1.16 {d23}, [r10, :64], r1 // p0 vst1.16 {d25}, [r0, :64], r1 // q1 sub r0, r0, r1, lsl #1 bx r12 endfunc function lpf_h_6_4_neon mov r12, lr sub r10, r0, #8 vld1.16 {d20}, [r10, :64], r1 vld1.16 {d24}, [r0, :64], r1 vld1.16 {d21}, [r10, :64], r1 vld1.16 {d25}, [r0, :64], r1 vld1.16 {d22}, [r10, :64], r1 vld1.16 {d26}, [r0, :64], r1 vld1.16 {d23}, [r10, :64], r1 vld1.16 {d27}, [r0, :64], r1 transpose_4x4h q10, q11, d20, d21, d22, d23 transpose_4x4h q12, q13, d24, d25, d26, d27 lpf_4_wd6 sub r0, r0, #4 transpose_4x4h q11, q12, d22, d23, d24, d25 sub r10, r0, r1, lsl #2 sub r0, r0, r1, lsl #1 vst1.16 {d22}, [r10], r1 vst1.16 {d24}, [r0], r1 vst1.16 {d23}, [r10], r1 vst1.16 {d25}, [r0], r1 add r0, r0, #4 bx r12 endfunc function lpf_v_8_4_neon mov r12, lr sub r10, r0, r1, lsl #2 vld1.16 {d20}, [r10, :64], r1 // p3 vld1.16 {d24}, [r0, :64], r1 // q0