/* * Loongson LSX optimized swscale * * Copyright (c) 2023 Loongson Technology Corporation Limited * Contributed by Lu Wang * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavcodec/loongarch/loongson_asm.S" /* void planar_rgb_to_y_lsx(uint8_t *_dst, const uint8_t *src[4], * int width, int32_t *rgb2yuv) */ function planar_rgb_to_y_lsx ld.d a5, a1, 0 ld.d a6, a1, 8 ld.d a7, a1, 16 ld.w t1, a3, 0 // ry ld.w t2, a3, 4 // gy ld.w t3, a3, 8 // by li.w t4, 9 li.w t5, 524544 li.w t7, 4 li.w t8, 8 vldi vr7, 0 vreplgr2vr.w vr1, t1 vreplgr2vr.w vr2, t2 vreplgr2vr.w vr3, t3 vreplgr2vr.w vr4, t4 vreplgr2vr.w vr5, t5 bge a2, t8, .WIDTH8 bge a2, t7, .WIDTH4 blt zero, a2, .WIDTH b .END .WIDTH8: vld vr8, a5, 0 vld vr9, a6, 0 vld vr10, a7, 0 vilvl.b vr11, vr7, vr8 vilvl.b vr12, vr7, vr9 vilvl.b vr13, vr7, vr10 vilvl.h vr14, vr7, vr11 vilvl.h vr15, vr7, vr12 vilvl.h vr16, vr7, vr13 vilvh.h vr17, vr7, vr11 vilvh.h vr18, vr7, vr12 vilvh.h vr19, vr7, vr13 vmul.w vr20, vr1, vr16 vmul.w vr21, vr1, vr19 vmadd.w vr20, vr2, vr14 vmadd.w vr20, vr3, vr15 vmadd.w vr21, vr2, vr17 vmadd.w vr21, vr3, vr18 vadd.w vr20, vr20, vr5 vadd.w vr21, vr21, vr5 vsra.w vr20, vr20, vr4 vsra.w vr21, vr21, vr4 vpickev.h vr20, vr21, vr20 vst vr20, a0, 0 addi.d a2, a2, -8 addi.d a5, a5, 8 addi.d a6, a6, 8 addi.d a7, a7, 8 addi.d a0, a0, 16 bge a2, t8, .WIDTH8 bge a2, t7, .WIDTH4 blt zero, a2, .WIDTH b .END .WIDTH4: vld vr8, a5, 0 vld vr9, a6, 0 vld vr10, a7, 0 vilvl.b vr11, vr7, vr8 vilvl.b vr12, vr7, vr9 vilvl.b vr13, vr7, vr10 vilvl.h vr14, vr7, vr11 vilvl.h vr15, vr7, vr12 vilvl.h vr16, vr7, vr13 vmul.w vr17, vr1, vr16 vmadd.w vr17, vr2, vr14 vmadd.w vr17, vr3, vr15 vadd.w vr17, vr17, vr5 vsra.w vr17, vr17, vr4 vpickev.h vr17, vr17, vr17 vstelm.d vr17, a0, 0, 0 addi.d a2, a2, -4 addi.d a5, a5, 4 addi.d a6, a6, 4 addi.d a7, a7, 4 addi.d a0, a0, 8 bge a2, t7, .WIDTH4 blt zero, a2, .WIDTH b .END .WIDTH: ld.bu t0, a5, 0 ld.bu t4, a6, 0 ld.bu t6, a7, 0 mul.w t8, t6, t1 mul.w t7, t0, t2 add.w t8, t8, t7 mul.w t7, t4, t3 add.w t8, t8, t7 add.w t8, t8, t5 srai.w t8, t8, 9 st.h t8, a0, 0 addi.d a2, a2, -1 addi.d a5, a5, 1 addi.d a6, a6, 1 addi.d a7, a7, 1 addi.d a0, a0, 2 blt zero, a2, .WIDTH .END: endfunc /* void planar_rgb_to_uv_lsx(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *src[4], * int width, int32_t *rgb2yuv) */ function planar_rgb_to_uv_lsx addi.d sp, sp, -24 st.d s1, sp, 0 st.d s2, sp, 8 st.d s3, sp, 16 ld.d a5, a2, 0 ld.d a6, a2, 8 ld.d a7, a2, 16 ld.w t1, a4, 12 // ru ld.w t2, a4, 16 // gu ld.w t3, a4, 20 // bu ld.w s1, a4, 24 // rv ld.w s2, a4, 28 // gv ld.w s3, a4, 32 // bv li.w t4, 9 li.w t5, 4194560 li.w t7, 4 li.w t8, 8 vldi vr0, 0 vreplgr2vr.w vr1, t1 vreplgr2vr.w vr2, t2 vreplgr2vr.w vr3, t3 vreplgr2vr.w vr4, s1 vreplgr2vr.w vr5, s2 vreplgr2vr.w vr6, s3 vreplgr2vr.w vr7, t4 vreplgr2vr.w vr8, t5 bge a2, t8, .LOOP_WIDTH8 bge a2, t7, .LOOP_WIDTH4 blt zero, a2, .LOOP_WIDTH b .LOOP_END .LOOP_WIDTH8: vld vr9, a5, 0 vld vr10, a6, 0 vld vr11, a7, 0 vilvl.b vr9, vr0, vr9 vilvl.b vr10, vr0, vr10 vilvl.b vr11, vr0, vr11 vilvl.h vr12, vr0, vr9 vilvl.h vr13, vr0, vr10 vilvl.h vr14, vr0, vr11 vilvh.h vr15, vr0, vr9 vilvh.h vr16, vr0, vr10 vilvh.h vr17, vr0, vr11 vmul.w vr18, vr1, vr14 vmul.w vr19, vr1, vr17 vmul.w vr20, vr4, vr14 vmul.w vr21, vr4, vr17 vmadd.w vr18, vr2, vr12 vmadd.w vr18, vr3, vr13 vmadd.w vr19, vr2, vr15 vmadd.w vr19, vr3, vr16 vmadd.w vr20, vr5, vr12 vmadd.w vr20, vr6, vr13 vmadd.w vr21, vr5, vr15 vmadd.w vr21, vr6, vr16 vadd.w vr18, vr18, vr8 vadd.w vr19, vr19, vr8 vadd.w vr20, vr20, vr8 vadd.w vr21, vr21, vr8 vsra.w vr18, vr18, vr7 vsra.w vr19, vr19, vr7 vsra.w vr20, vr20, vr7 vsra.w vr21, vr21, vr7 vpickev.h vr18, vr19, vr18 vpickev.h vr20, vr21, vr20 vst vr18, a0, 0 vst vr20, a1, 0 addi.d a3, a3, -8 addi.d a5, a5, 8 addi.d a6, a6, 8 addi.d a7, a7, 8 addi.d a0, a0, 16 addi.d a1, a1, 16 bge a3, t8, .LOOP_WIDTH8 bge a3, t7, .LOOP_WIDTH4 blt zero, a3, .LOOP_WIDTH b .LOOP_END .LOOP_WIDTH4: vld vr9, a5, 0 vld vr10, a6, 0 vld vr11, a7, 0 vilvl.b vr9, vr0, vr9 vilvl.b vr10, vr0, vr10 vilvl.b vr11, vr0, vr11 vilvl.h vr12, vr0, vr9 vilvl.h vr13, vr0, vr10 vilvl.h vr14, vr0, vr11 vmul.w vr18, vr1, vr14 vmul.w vr19, vr4, vr14 vmadd.w vr18, vr2, vr12 vmadd.w vr18, vr3, vr13 vmadd.w vr19, vr5, vr12 vmadd.w vr19, vr6, vr13 vadd.w vr18, vr18, vr8 vadd.w vr19, vr19, vr8 vsra.w vr18, vr18, vr7 vsra.w vr19, vr19, vr7 vpickev.h vr18, vr18, vr18 vpickev.h vr19, vr19, vr19 vstelm.d vr18, a0, 0, 0 vstelm.d vr19, a1, 0, 0 addi.d a3, a3, -4 addi.d a5, a5, 4 addi.d a6, a6, 4 addi.d a7, a7, 4 addi.d a0, a0, 8 addi.d a1, a1, 8 bge a3, t7, .LOOP_WIDTH4 blt zero, a3, .LOOP_WIDTH b .LOOP_END .LOOP_WIDTH: ld.bu t0, a5, 0 ld.bu t4, a6, 0 ld.bu t6, a7, 0 mul.w t8, t6, t1 mul.w t7, t0, t2 add.w t8, t8, t7 mul.w t7, t4, t3 add.w t8, t8, t7 add.w t8, t8, t5 srai.w t8, t8, 9 st.h t8, a0, 0 mul.w t8, t6, s1 mul.w t7, t0, s2 add.w t8, t8, t7 mul.w t7, t4, s3 add.w t8, t8, t7 add.w t8, t8, t5 srai.w t8, t8, 9 st.h t8, a1, 0 addi.d a3, a3, -1 addi.d a5, a5, 1 addi.d a6, a6, 1 addi.d a7, a7, 1 addi.d a0, a0, 2 addi.d a1, a1, 2 blt zero, a3, .LOOP_WIDTH .LOOP_END: ld.d s1, sp, 0 ld.d s2, sp, 8 ld.d s3, sp, 16 addi.d sp, sp, 24 endfunc /* * void yuy2ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1, * const uint8_t *src2, int width, uint32_t *unused, void *opq) */ function yuy2ToUV_lsx andi t0, a5, 7 srli.d a5, a5, 3 beqz a5, 2f 1: vld vr0, a3, 1 vld vr1, a3, 17 addi.d a5, a5, -1 addi.d a3, a3, 32 vpickev.b vr2, vr1, vr0 vpickev.b vr0, vr2, vr2 vpickod.b vr1, vr2, vr2 fst.d f0, a0, 0 fst.d f1, a1, 0 addi.d a0, a0, 8 addi.d a1, a1, 8 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 1 ld.b t2, a3, 3 addi.d a3, a3, 4 addi.d t0, t0, -1 st.b t1, a0, 0 st.b t2, a1, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc function yuy2ToUV_lasx andi t0, a5, 15 srli.d a5, a5, 4 beqz a5, 2f 1: xvld xr0, a3, 1 xvld xr1, a3, 33 addi.d a5, a5, -1 addi.d a3, a3, 64 xvpickev.b xr2, xr1, xr0 xvpermi.d xr2, xr2, 0xd8 xvpickev.b xr0, xr2, xr2 xvpermi.d xr0, xr0, 0xd8 xvpickod.b xr1, xr2, xr2 xvpermi.d xr1, xr1, 0xd8 vst vr0, a0, 0 vst vr1, a1, 0 addi.d a0, a0, 16 addi.d a1, a1, 16 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 1 ld.b t2, a3, 3 addi.d a3, a3, 4 addi.d t0, t0, -1 st.b t1, a0, 0 st.b t2, a1, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc /* * void yvy2ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1, * const uint8_t *src2, int width, uint32_t *unused, void *opq) */ function yvy2ToUV_lsx andi t0, a5, 7 srli.d a5, a5, 3 beqz a5, 2f 1: vld vr0, a3, 1 vld vr1, a3, 17 addi.d a5, a5, -1 addi.d a3, a3, 32 vpickev.b vr2, vr1, vr0 vpickev.b vr0, vr2, vr2 vpickod.b vr1, vr2, vr2 fst.d f0, a1, 0 fst.d f1, a0, 0 addi.d a0, a0, 8 addi.d a1, a1, 8 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 1 ld.b t2, a3, 3 addi.d a3, a3, 4 addi.d t0, t0, -1 st.b t1, a1, 0 st.b t2, a0, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc function yvy2ToUV_lasx andi t0, a5, 15 srli.d a5, a5, 4 beqz a5, 2f 1: xvld xr0, a3, 1 xvld xr1, a3, 33 addi.d a5, a5, -1 addi.d a3, a3, 64 xvpickev.b xr2, xr1, xr0 xvpermi.d xr2, xr2, 0xd8 xvpickev.b xr0, xr2, xr2 xvpermi.d xr0, xr0, 0xd8 xvpickod.b xr1, xr2, xr2 xvpermi.d xr1, xr1, 0xd8 vst vr0, a1, 0 vst vr1, a0, 0 addi.d a0, a0, 16 addi.d a1, a1, 16 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 1 ld.b t2, a3, 3 addi.d a3, a3, 4 addi.d t0, t0, -1 st.b t1, a1, 0 st.b t2, a0, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc /* * void uyvyToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1, * const uint8_t *src2, int width, uint32_t *unused, void *opq) */ function uyvyToUV_lsx andi t0, a5, 7 srli.d a5, a5, 3 beqz a5, 2f 1: vld vr0, a3, 0 vld vr1, a3, 16 addi.d a5, a5, -1 addi.d a3, a3, 32 vpickev.b vr2, vr1, vr0 vpickev.b vr0, vr2, vr2 vpickod.b vr1, vr2, vr2 fst.d f0, a0, 0 fst.d f1, a1, 0 addi.d a0, a0, 8 addi.d a1, a1, 8 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 1 ld.b t2, a3, 3 addi.d a3, a3, 4 addi.d t0, t0, -1 st.b t1, a0, 0 st.b t2, a1, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc function uyvyToUV_lasx andi t0, a5, 15 srli.d a5, a5, 4 beqz a5, 2f 1: xvld xr0, a3, 0 xvld xr1, a3, 32 addi.d a5, a5, -1 addi.d a3, a3, 64 xvpickev.b xr2, xr1, xr0 xvpermi.d xr2, xr2, 0xd8 xvpickev.b xr0, xr2, xr2 xvpermi.d xr0, xr0, 0xd8 xvpickod.b xr1, xr2, xr2 xvpermi.d xr1, xr1, 0xd8 vst vr0, a0, 0 vst vr1, a1, 0 addi.d a0, a0, 16 addi.d a1, a1, 16 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 1 ld.b t2, a3, 3 addi.d a3, a3, 4 addi.d t0, t0, -1 st.b t1, a0, 0 st.b t2, a1, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc /* * void nv12ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1, * const uint8_t *src2, int width, uint32_t *unused, void *opq) */ function nv12ToUV_lsx andi t0, a5, 15 srli.d a5, a5, 4 beqz a5, 2f 1: vld vr0, a3, 0 vld vr1, a3, 16 addi.d a5, a5, -1 addi.d a3, a3, 32 vpickev.b vr2, vr1, vr0 vpickod.b vr3, vr1, vr0 vst vr2, a0, 0 vst vr3, a1, 0 addi.d a0, a0, 16 addi.d a1, a1, 16 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 0 ld.b t2, a3, 1 addi.d a3, a3, 2 addi.d t0, t0, -1 st.b t1, a0, 0 st.b t2, a1, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc function nv12ToUV_lasx andi t0, a5, 31 srli.d a5, a5, 5 beqz a5, 2f 1: xvld xr0, a3, 0 xvld xr1, a3, 32 addi.d a5, a5, -1 addi.d a3, a3, 64 xvpickev.b xr2, xr1, xr0 xvpickod.b xr3, xr1, xr0 xvpermi.d xr2, xr2, 0xd8 xvpermi.d xr3, xr3, 0xd8 xvst xr2, a0, 0 xvst xr3, a1, 0 addi.d a0, a0, 32 addi.d a1, a1, 32 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 0 ld.b t2, a3, 1 addi.d a3, a3, 2 addi.d t0, t0, -1 st.b t1, a0, 0 st.b t2, a1, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc /* * void nv21ToUV_lsx(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src1, * const uint8_t *src2, int width, uint32_t *unused, void *opq) */ function nv21ToUV_lsx andi t0, a5, 15 srli.d a5, a5, 4 beqz a5, 2f 1: vld vr0, a3, 0 vld vr1, a3, 16 addi.d a5, a5, -1 addi.d a3, a3, 32 vpickev.b vr2, vr1, vr0 vpickod.b vr3, vr1, vr0 vst vr2, a1, 0 vst vr3, a0, 0 addi.d a0, a0, 16 addi.d a1, a1, 16 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 0 ld.b t2, a3, 1 addi.d a3, a3, 2 addi.d t0, t0, -1 st.b t1, a1, 0 st.b t2, a0, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc function nv21ToUV_lasx andi t0, a5, 31 srli.d a5, a5, 5 beqz a5, 2f 1: xvld xr0, a3, 0 xvld xr1, a3, 32 addi.d a5, a5, -1 addi.d a3, a3, 64 xvpickev.b xr2, xr1, xr0 xvpickod.b xr3, xr1, xr0 xvpermi.d xr2, xr2, 0xd8 xvpermi.d xr3, xr3, 0xd8 xvst xr2, a1, 0 xvst xr3, a0, 0 addi.d a0, a0, 32 addi.d a1, a1, 32 bnez a5, 1b 2: beqz t0, 4f 3: ld.b t1, a3, 0 ld.b t2, a3, 1 addi.d a3, a3, 2 addi.d t0, t0, -1 st.b t1, a1, 0 st.b t2, a0, 0 addi.d a0, a0, 1 addi.d a1, a1, 1 bnez t0, 3b 4: endfunc /* *void abgrToA_lsx(uint8_t *_dst, const uint8_t *src, const uint8_t *unused1, * const uint8_t *unused2, int width, uint32_t *unused, void *opq) */ function abgrToA_lsx andi t0, a4, 7 srli.d a4, a4, 3 vxor.v vr0, vr0, vr0 beqz a4, 2f 1: vld vr1, a1, 0 vld vr2, a1, 16 addi.d a4, a4, -1 addi.d a1, a1, 32 vpickev.b vr3, vr2, vr1 vpackev.b vr3, vr0, vr3 vslli.h vr1, vr3, 6 vsrli.h vr2, vr3, 2 vor.v vr3, vr2, vr1 vst vr3, a0, 0 addi.d a0, a0, 16 bnez a4, 1b 2: beqz t0, 4f 3: ld.b t1, a1, 3 addi.d t0, t0, -1 addi.d a1, a1, 4 andi t1, t1, 0xff slli.w t2, t1, 6 srli.w t3, t1, 2 or t1, t2, t3 st.h t1, a0, 0 addi.d a0, a0, 2 bnez t0, 3b 4: endfunc function abgrToA_lasx andi t0, a4, 15 srli.d a4, a4, 4 xvxor.v xr0, xr0, xr0 beqz a4, 2f 1: xvld xr1, a1, 0 xvld xr2, a1, 32 addi.d a4, a4, -1 addi.d a1, a1, 64 xvpickev.b xr3, xr2, xr1 xvpermi.d xr3, xr3, 0xd8 xvpackev.b xr3, xr0, xr3 xvslli.h xr1, xr3, 6 xvsrli.h xr2, xr3, 2 xvor.v xr3, xr2, xr1 xvst xr3, a0, 0 addi.d a0, a0, 32 bnez a4, 1b 2: beqz t0, 4f 3: ld.b t1, a1, 3 addi.d t0, t0, -1 addi.d a1, a1, 4 andi t1, t1, 0xff slli.w t2, t1, 6 srli.w t3, t1, 2 or t1, t2, t3 st.h t1, a0, 0 addi.d a0, a0, 2 bnez t0, 3b 4: endfunc /* *void rgbaToA_lsx(uint8_t *_dst, const uint8_t *src, const uint8_t *unused1, * const uint8_t *unused2, int width, uint32_t *unused, void *opq) */ function rgbaToA_lsx andi t0, a4, 7 srli.d a4, a4, 3 vxor.v vr0, vr0, vr0 beqz a4, 2f 1: vld vr1, a1, 3 vld vr2, a1, 19 addi.d a4, a4, -1 addi.d a1, a1, 32 vpickev.b vr3, vr2, vr1 vpackev.b vr3, vr0, vr3 vslli.h vr1, vr3, 6 vsrli.h vr2, vr3, 2 vor.v vr3, vr2, vr1 vst vr3, a0, 0 addi.d a0, a0, 16 bnez a4, 1b 2: beqz t0, 4f 3: ld.b t1, a1, 3 addi.d t0, t0, -1 addi.d a1, a1, 4 andi t1, t1, 0xff slli.w t2, t1, 6 srli.w t3, t1, 2 or t1, t2, t3 st.h t1, a0, 0 addi.d a0, a0, 2 bnez t0, 3b 4: endfunc function rgbaToA_lasx andi t0, a4, 15 srli.d a4, a4, 4 xvxor.v xr0, xr0, xr0 beqz a4, 2f 1: xvld xr1, a1, 3 xvld xr2, a1, 35 addi.d a4, a4, -1 addi.d a1, a1, 64 xvpickev.b xr3, xr2, xr1 xvpermi.d xr3, xr3, 0xd8 xvpackev.b xr3, xr0, xr3 xvslli.h xr1, xr3, 6 xvsrli.h xr2, xr3, 2 xvor.v xr3, xr2, xr1 xvst xr3, a0, 0 addi.d a0, a0, 32 bnez a4, 1b 2: beqz t0, 4f 3: ld.b t1, a1, 3 addi.d t0, t0, -1 addi.d a1, a1, 4 andi t1, t1, 0xff slli.w t2, t1, 6 srli.w t3, t1, 2 or t1, t2, t3 st.h t1, a0, 0 addi.d a0, a0, 2 bnez t0, 3b 4: endfunc