diff mbox

[FFmpeg-devel,2/2] avcodec/mips: [loongson] optimize vp8 decoding in vp8dsp.

Message ID 1536143466-8610-2-git-send-email-yinshiyou-hf@loongson.cn
State Accepted
Commit 090647da84f975c7ffb163436040cc8aecf46a9c
Headers show

Commit Message

殷时友 Sept. 5, 2018, 10:31 a.m. UTC
From: gxw <guxiwei-hf@loongson.cn>

Optimize vp8 loop filter with mmi, four functions optimized:
1. ff_vp8_h_loop_filter8uv_mmi.
2. ff_vp8_v_loop_filter8uv_mmi.
3. ff_vp8_h_loop_filter16_mmi.
4. ff_vp8_v_loop_filter16_mmi.

Vp8 decoding speed improved about 50%(from 73fps to 110fps, Tested on loongson 3A3000).

Signed-off-by: Shiyou Yin <yinshiyou-hf@loongson.cn>
---
 libavcodec/mips/vp8dsp_mmi.c | 402 +++++++++++++++++++++++++++++++++++++++----
 libavutil/mips/mmiutils.h    |  28 +++
 2 files changed, 394 insertions(+), 36 deletions(-)

Comments

殷时友 Sept. 7, 2018, 3:38 a.m. UTC | #1
>-----Original Message-----
>From: ffmpeg-devel-bounces@ffmpeg.org [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of
>Shiyou Yin
>Sent: Wednesday, September 5, 2018 6:31 PM
>To: ffmpeg-devel@ffmpeg.org
>Cc: gxw
>Subject: [FFmpeg-devel] [PATCH 2/2] avcodec/mips: [loongson] optimize vp8 decoding in vp8dsp.
>
>From: gxw <guxiwei-hf@loongson.cn>
>
>Optimize vp8 loop filter with mmi, four functions optimized:
>1. ff_vp8_h_loop_filter8uv_mmi.
>2. ff_vp8_v_loop_filter8uv_mmi.
>3. ff_vp8_h_loop_filter16_mmi.
>4. ff_vp8_v_loop_filter16_mmi.
>
>Vp8 decoding speed improved about 50%(from 73fps to 110fps, Tested on loongson 3A3000).
>
>Signed-off-by: Shiyou Yin <yinshiyou-hf@loongson.cn>
>---
> libavcodec/mips/vp8dsp_mmi.c | 402 +++++++++++++++++++++++++++++++++++++++----
> libavutil/mips/mmiutils.h    |  28 +++
> 2 files changed, 394 insertions(+), 36 deletions(-)
>
>diff --git a/libavcodec/mips/vp8dsp_mmi.c b/libavcodec/mips/vp8dsp_mmi.c
>index f972628..b24a87a 100644
>--- a/libavcodec/mips/vp8dsp_mmi.c
>+++ b/libavcodec/mips/vp8dsp_mmi.c
>@@ -25,6 +25,221 @@
> #include "constants.h"
> #include "libavutil/mips/mmiutils.h"
>
>+#define DECLARE_DOUBLE_1            double db_1
>+#define DECLARE_DOUBLE_2            double db_2
>+#define DECLARE_UINT32_T            uint32_t  it_1
>+#define RESTRICT_ASM_DOUBLE_1       [db_1]"=&f"(db_1)
>+#define RESTRICT_ASM_DOUBLE_2       [db_2]"=&f"(db_2)
>+#define RESTRICT_ASM_UINT32_T       [it_1]"=&r"(it_1)
>+
>+#define MMI_PCMPGTUB(dst, src1, src2)                                       \
>+        "pcmpeqb    %[db_1],    "#src1",        "#src2"             \n\t"   \
>+        "pmaxub     %[db_2],    "#src1",        "#src2"             \n\t"   \
>+        "pcmpeqb    %[db_2],    %[db_2],        "#src1"             \n\t"   \
>+        "xor        "#dst",     %[db_2],        %[db_1]             \n\t"
>+
>+#define MMI_BTOH(dst_l, dst_r, src)                                         \
>+        "xor        %[db_1],    %[db_1],        %[db_1]             \n\t"   \
>+        "pcmpgtb    %[db_2],    %[db_1],        "#src"              \n\t"   \
>+        "punpcklbh  "#dst_r",   "#src",         %[db_2]             \n\t"   \
>+        "punpckhbh  "#dst_l",   "#src",         %[db_2]             \n\t"
>+
>+#define MMI_TRANSPOSE8x8_UB_UB(src_0, src_1, src_2, src_3,                  \
>+                               src_4, src_5, src_6, src_7,                  \
>+                               dst_0, dst_1, dst_2, dst_3,                  \
>+                               dst_4, dst_5, dst_6, dst_7)                  \
>+        "li         %[it_1],    0xe4                                \n\t"   \
>+        "dmtc1      %[it_1],    %[db_1]                             \n\t"   \
>+        "pshufh     %[db_2],    "#src_0",       %[db_1]             \n\t"   \
>+        "punpcklbh  "#dst_0",   "#src_0",       "#src_1"            \n\t"   \
>+        "punpckhbh  "#dst_1",   %[db_2],        "#src_1"            \n\t"   \
>+        "pshufh     %[db_2],    "#src_2",       %[db_1]             \n\t"   \
>+        "punpcklbh  "#dst_2",   "#src_2",       "#src_3"            \n\t"   \
>+        "punpckhbh  "#dst_3",   %[db_2],        "#src_3"            \n\t"   \
>+        "pshufh     %[db_2],    "#src_4",       %[db_1]             \n\t"   \
>+        "punpcklbh  "#dst_4",   "#src_4",       "#src_5"            \n\t"   \
>+        "punpckhbh  "#dst_5",   %[db_2],        "#src_5"            \n\t"   \
>+        "pshufh     %[db_2],    "#src_6",       %[db_1]             \n\t"   \
>+        "punpcklbh  "#dst_6",   "#src_6",       "#src_7"            \n\t"   \
>+        "punpckhbh  "#dst_7",   %[db_2],        "#src_7"            \n\t"   \
>+                                                                            \
>+        "pshufh     %[db_2],    "#dst_0",       %[db_1]             \n\t"   \
>+        "punpcklhw  "#dst_0",   "#dst_0",       "#dst_2"            \n\t"   \
>+        "punpckhhw  "#dst_2",   %[db_2],        "#dst_2"            \n\t"   \
>+        "pshufh     %[db_2],    "#dst_1",       %[db_1]             \n\t"   \
>+        "punpcklhw  "#dst_1",   "#dst_1",       "#dst_3"            \n\t"   \
>+        "punpckhhw  "#dst_3",   %[db_2],        "#dst_3"            \n\t"   \
>+        "pshufh     %[db_2],    "#dst_4",       %[db_1]             \n\t"   \
>+        "punpcklhw  "#dst_4",   "#dst_4",       "#dst_6"            \n\t"   \
>+        "punpckhhw  "#dst_6",   %[db_2],        "#dst_6"            \n\t"   \
>+        "pshufh     %[db_2],    "#dst_5",       %[db_1]             \n\t"   \
>+        "punpcklhw  "#dst_5",   "#dst_5",       "#dst_7"            \n\t"   \
>+        "punpckhhw  "#dst_7",   %[db_2],        "#dst_7"            \n\t"   \
>+                                                                            \
>+        "pshufh     %[db_2],    "#dst_0",       %[db_1]             \n\t"   \
>+        "punpcklwd  "#dst_0",   "#dst_0",       "#dst_4"            \n\t"   \
>+        "punpckhwd  "#dst_4",   %[db_2],        "#dst_4"            \n\t"   \
>+        "pshufh     %[db_2],    "#dst_1",       %[db_1]             \n\t"   \
>+        "punpcklwd  "#dst_1",   "#dst_1",       "#dst_5"            \n\t"   \
>+        "punpckhwd  "#dst_5",   %[db_2],        "#dst_5"            \n\t"   \
>+        "pshufh     %[db_2],    "#dst_2",       %[db_1]             \n\t"   \
>+        "punpcklwd  "#dst_2",   "#dst_2",       "#dst_6"            \n\t"   \
>+        "punpckhwd  "#dst_6",   %[db_2],        "#dst_6"            \n\t"   \
>+        "pshufh     %[db_2],    "#dst_3",       %[db_1]             \n\t"   \
>+        "punpcklwd  "#dst_3",   "#dst_3",       "#dst_7"            \n\t"   \
>+        "punpckhwd  "#dst_7",   %[db_2],        "#dst_7"            \n\t"   \
>+                                                                            \
>+        "pshufh     %[db_2],    "#dst_1",       %[db_1]             \n\t"   \
>+        "pshufh     "#dst_1",   "#dst_4",       %[db_1]             \n\t"   \
>+        "pshufh     "#dst_4",   %[db_2],        %[db_1]             \n\t"   \
>+        "pshufh     %[db_2],    "#dst_3",       %[db_1]             \n\t"   \
>+        "pshufh     "#dst_3",   "#dst_6",       %[db_1]             \n\t"   \
>+        "pshufh     "#dst_6",   %[db_2],        %[db_1]             \n\t"
>+
>+#define MMI_VP8_LOOP_FILTER                                                 \
>+        /* Calculation of hev */                                            \
>+        "dmtc1      %[thresh],  %[ftmp3]                            \n\t"   \
>+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        "pasubub    %[ftmp0],   %[p1],          %[p0]               \n\t"   \
>+        "pasubub    %[ftmp1],   %[q1],          %[q0]               \n\t"   \
>+        "pmaxub     %[ftmp0],   %[ftmp0],       %[ftmp1]            \n\t"   \
>+        MMI_PCMPGTUB(%[hev], %[ftmp0], %[ftmp3])                            \
>+        /* Calculation of mask */                                           \
>+        "pasubub    %[ftmp1],   %[p0],          %[q0]               \n\t"   \
>+        "paddusb    %[ftmp1],   %[ftmp1],       %[ftmp1]            \n\t"   \
>+        "pasubub    %[ftmp2],   %[p1],          %[q1]               \n\t"   \
>+        "li         %[tmp0],    0x09                                \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp3]                            \n\t"   \
>+        PSRLB_MMI(%[ftmp2],  %[ftmp3],  %[ftmp4],  %[ftmp5],  %[ftmp2])     \
>+        "paddusb    %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"   \
>+        "dmtc1      %[e],       %[ftmp3]                            \n\t"   \
>+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        MMI_PCMPGTUB(%[mask], %[ftmp1], %[ftmp3])                           \
>+        "pmaxub     %[mask],    %[mask],        %[ftmp0]            \n\t"   \
>+        "pasubub    %[ftmp1],   %[p3],          %[p2]               \n\t"   \
>+        "pasubub    %[ftmp2],   %[p2],          %[p1]               \n\t"   \
>+        "pmaxub     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"   \
>+        "pmaxub     %[mask],    %[mask],        %[ftmp1]            \n\t"   \
>+        "pasubub    %[ftmp1],   %[q3],          %[q2]               \n\t"   \
>+        "pasubub    %[ftmp2],   %[q2],          %[q1]               \n\t"   \
>+        "pmaxub     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"   \
>+        "pmaxub     %[mask],    %[mask],        %[ftmp1]            \n\t"   \
>+        "dmtc1      %[i],       %[ftmp3]                            \n\t"   \
>+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        MMI_PCMPGTUB(%[mask], %[mask], %[ftmp3])                            \
>+        "pcmpeqw    %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
>+        "xor        %[mask],    %[mask],        %[ftmp3]            \n\t"   \
>+        /* VP8_MBFILTER */                                                  \
>+        "li         %[tmp0],    0x80808080                          \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp7]                            \n\t"   \
>+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp7]            \n\t"   \
>+        "xor        %[p2],      %[p2],          %[ftmp7]            \n\t"   \
>+        "xor        %[p1],      %[p1],          %[ftmp7]            \n\t"   \
>+        "xor        %[p0],      %[p0],          %[ftmp7]            \n\t"   \
>+        "xor        %[q0],      %[q0],          %[ftmp7]            \n\t"   \
>+        "xor        %[q1],      %[q1],          %[ftmp7]            \n\t"   \
>+        "xor        %[q2],      %[q2],          %[ftmp7]            \n\t"   \
>+        "psubsb     %[ftmp4],   %[p1],          %[q1]               \n\t"   \
>+        "psubb      %[ftmp5],   %[q0],          %[p0]               \n\t"   \
>+        MMI_BTOH(%[ftmp1],  %[ftmp0],  %[ftmp5])                            \
>+        MMI_BTOH(%[ftmp3],  %[ftmp2],  %[ftmp4])                            \
>+        /* Right part */                                                    \
>+        "paddh      %[ftmp5],   %[ftmp0],       %[ftmp0]            \n\t"   \
>+        "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"   \
>+        "paddh      %[ftmp0],   %[ftmp2],       %[ftmp0]            \n\t"   \
>+        /* Left part */                                                     \
>+        "paddh      %[ftmp5],   %[ftmp1],       %[ftmp1]            \n\t"   \
>+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"   \
>+        "paddh      %[ftmp1],   %[ftmp3],       %[ftmp1]            \n\t"   \
>+        /* Combine left and right part */                                   \
>+        "packsshb   %[ftmp1],   %[ftmp0],       %[ftmp1]            \n\t"   \
>+        "and        %[ftmp1],   %[ftmp1],       %[mask]             \n\t"   \
>+        "and        %[ftmp2],   %[ftmp1],       %[hev]              \n\t"   \
>+        "li         %[tmp0],    0x04040404                          \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp0]                            \n\t"   \
>+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"   \
>+        "paddsb     %[ftmp3],   %[ftmp2],       %[ftmp0]            \n\t"   \
>+        "li         %[tmp0],    0x0B                                \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp4]                            \n\t"   \
>+        PSRAB_MMI(%[ftmp3],  %[ftmp4],  %[ftmp5],  %[ftmp6],  %[ftmp3])     \
>+        "li         %[tmp0],    0x03030303                          \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp0]                            \n\t"   \
>+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"   \
>+        "paddsb     %[ftmp4],   %[ftmp2],       %[ftmp0]            \n\t"   \
>+        "li         %[tmp0],    0x0B                                \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp2]                            \n\t"   \
>+        PSRAB_MMI(%[ftmp4],  %[ftmp2],  %[ftmp5],  %[ftmp6],  %[ftmp4])     \
>+        "psubsb     %[q0],      %[q0],          %[ftmp3]            \n\t"   \
>+        "paddsb     %[p0],      %[p0],          %[ftmp4]            \n\t"   \
>+        /* filt_val &= ~hev */                                              \
>+        "pcmpeqw    %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"   \
>+        "xor        %[hev],     %[hev],         %[ftmp0]            \n\t"   \
>+        "and        %[ftmp1],   %[ftmp1],       %[hev]              \n\t"   \
>+        MMI_BTOH(%[ftmp5],  %[ftmp6],  %[ftmp1])                            \
>+        "li         %[tmp0],    0x07                                \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp2]                            \n\t"   \
>+        "li         %[tmp0],    0x001b001b                          \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp1]                            \n\t"   \
>+        "punpcklwd  %[ftmp1],   %[ftmp1],       %[ftmp1]            \n\t"   \
>+        "li         %[tmp0],    0x003f003f                          \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp0]                            \n\t"   \
>+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"   \
>+        /* Right part */                                                    \
>+        "pmullh     %[ftmp3],   %[ftmp6],       %[ftmp1]            \n\t"   \
>+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"   \
>+        "psrah      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"   \
>+        /* Left part */                                                     \
>+        "pmullh     %[ftmp4],   %[ftmp5],       %[ftmp1]            \n\t"   \
>+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"   \
>+        "psrah      %[ftmp4],   %[ftmp4],       %[ftmp2]            \n\t"   \
>+        /* Combine left and right part */                                   \
>+        "packsshb   %[ftmp4],   %[ftmp3],       %[ftmp4]            \n\t"   \
>+        "psubsb     %[q0],      %[q0],          %[ftmp4]            \n\t"   \
>+        "xor        %[q0],      %[q0],          %[ftmp7]            \n\t"   \
>+        "paddsb     %[p0],      %[p0],          %[ftmp4]            \n\t"   \
>+        "xor        %[p0],      %[p0],          %[ftmp7]            \n\t"   \
>+        "li         %[tmp0],    0x00120012                          \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp1]                            \n\t"   \
>+        "punpcklwd  %[ftmp1],   %[ftmp1],       %[ftmp1]            \n\t"   \
>+        /* Right part */                                                    \
>+        "pmullh     %[ftmp3],   %[ftmp6],       %[ftmp1]            \n\t"   \
>+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"   \
>+        "psrah      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"   \
>+        /* Left part */                                                     \
>+        "pmullh     %[ftmp4],   %[ftmp5],       %[ftmp1]            \n\t"   \
>+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"   \
>+        "psrah      %[ftmp4],   %[ftmp4],       %[ftmp2]            \n\t"   \
>+        /* Combine left and right part */                                   \
>+        "packsshb   %[ftmp4],   %[ftmp3],       %[ftmp4]            \n\t"   \
>+        "psubsb     %[q1],      %[q1],          %[ftmp4]            \n\t"   \
>+        "xor        %[q1],      %[q1],          %[ftmp7]            \n\t"   \
>+        "paddsb     %[p1],      %[p1],          %[ftmp4]            \n\t"   \
>+        "xor        %[p1],      %[p1],          %[ftmp7]            \n\t"   \
>+        "li         %[tmp0],    0x03                                \n\t"   \
>+        "dmtc1      %[tmp0],    %[ftmp1]                            \n\t"   \
>+        /* Right part */                                                    \
>+        "psllh      %[ftmp3],   %[ftmp6],       %[ftmp1]            \n\t"   \
>+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp6]            \n\t"   \
>+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"   \
>+        "psrah      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"   \
>+        /* Left part */                                                     \
>+        "psllh      %[ftmp4],   %[ftmp5],       %[ftmp1]            \n\t"   \
>+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp5]            \n\t"   \
>+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"   \
>+        "psrah      %[ftmp4],   %[ftmp4],       %[ftmp2]            \n\t"   \
>+        /* Combine left and right part */                                   \
>+        "packsshb   %[ftmp4],   %[ftmp3],       %[ftmp4]            \n\t"   \
>+        "psubsb     %[q2],      %[q2],          %[ftmp4]            \n\t"   \
>+        "xor        %[q2],      %[q2],          %[ftmp7]            \n\t"   \
>+        "paddsb     %[p2],      %[p2],          %[ftmp4]            \n\t"   \
>+        "xor        %[p2],      %[p2],          %[ftmp7]            \n\t"
>+
> #define PUT_VP8_EPEL4_H6_MMI(src, dst)                                      \
>         MMI_ULWC1(%[ftmp1], src, 0x00)                                      \
>         "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"   \
>@@ -621,15 +836,71 @@ static av_always_inline int vp8_normal_limit(uint8_t *p, ptrdiff_t stride,
> static av_always_inline void vp8_v_loop_filter8_mmi(uint8_t *dst,
>         ptrdiff_t stride, int flim_E, int flim_I, int hev_thresh)
> {
>-    int i;
>-
>-    for (i = 0; i < 8; i++)
>-        if (vp8_normal_limit(dst + i * 1, stride, flim_E, flim_I)) {
>-            if (hev(dst + i * 1, stride, hev_thresh))
>-                vp8_filter_common_is4tap(dst + i * 1, stride);
>-            else
>-                filter_mbedge(dst + i * 1, stride);
>-        }
>+    double ftmp[18];
>+    uint32_t tmp[1];
>+    DECLARE_DOUBLE_1;
>+    DECLARE_DOUBLE_2;
>+    DECLARE_UINT32_T;
>+    __asm__ volatile(
>+        /* Get data from dst */
>+        "gsldlc1    %[q0],      0x07(%[dst])                      \n\t"
>+        "gsldrc1    %[q0],      0x00(%[dst])                      \n\t"
>+        PTR_SUBU    "%[tmp0],   %[dst],         %[stride]         \n\t"
>+        "gsldlc1    %[p0],      0x07(%[tmp0])                     \n\t"
>+        "gsldrc1    %[p0],      0x00(%[tmp0])                     \n\t"
>+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
>+        "gsldlc1    %[p1],      0x07(%[tmp0])                     \n\t"
>+        "gsldrc1    %[p1],      0x00(%[tmp0])                     \n\t"
>+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
>+        "gsldlc1    %[p2],      0x07(%[tmp0])                     \n\t"
>+        "gsldrc1    %[p2],      0x00(%[tmp0])                     \n\t"
>+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
>+        "gsldlc1    %[p3],      0x07(%[tmp0])                     \n\t"
>+        "gsldrc1    %[p3],      0x00(%[tmp0])                     \n\t"
>+        PTR_ADDU    "%[tmp0],   %[dst],         %[stride]         \n\t"
>+        "gsldlc1    %[q1],      0x07(%[tmp0])                     \n\t"
>+        "gsldrc1    %[q1],      0x00(%[tmp0])                     \n\t"
>+        PTR_ADDU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
>+        "gsldlc1    %[q2],      0x07(%[tmp0])                     \n\t"
>+        "gsldrc1    %[q2],      0x00(%[tmp0])                     \n\t"
>+        PTR_ADDU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
>+        "gsldlc1    %[q3],      0x07(%[tmp0])                     \n\t"
>+        "gsldrc1    %[q3],      0x00(%[tmp0])                     \n\t"
>+        MMI_VP8_LOOP_FILTER
>+        /* Move to dst */
>+        "gssdlc1    %[q0],      0x07(%[dst])                      \n\t"
>+        "gssdrc1    %[q0],      0x00(%[dst])                      \n\t"
>+        PTR_SUBU    "%[tmp0],   %[dst],         %[stride]         \n\t"
>+        "gssdlc1    %[p0],      0x07(%[tmp0])                     \n\t"
>+        "gssdrc1    %[p0],      0x00(%[tmp0])                     \n\t"
>+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
>+        "gssdlc1    %[p1],      0x07(%[tmp0])                     \n\t"
>+        "gssdrc1    %[p1],      0x00(%[tmp0])                     \n\t"
>+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
>+        "gssdlc1    %[p2],      0x07(%[tmp0])                     \n\t"
>+        "gssdrc1    %[p2],      0x00(%[tmp0])                     \n\t"
>+        PTR_ADDU    "%[tmp0],   %[dst],         %[stride]         \n\t"
>+        "gssdlc1    %[q1],      0x07(%[tmp0])                     \n\t"
>+        "gssdrc1    %[q1],      0x00(%[tmp0])                     \n\t"
>+        PTR_ADDU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
>+        "gssdlc1    %[q2],      0x07(%[tmp0])                     \n\t"
>+        "gssdrc1    %[q2],      0x00(%[tmp0])                     \n\t"
>+        : [p3]"=&f"(ftmp[0]),       [p2]"=&f"(ftmp[1]),
>+          [p1]"=&f"(ftmp[2]),       [p0]"=&f"(ftmp[3]),
>+          [q0]"=&f"(ftmp[4]),       [q1]"=&f"(ftmp[5]),
>+          [q2]"=&f"(ftmp[6]),       [q3]"=&f"(ftmp[7]),
>+          [ftmp0]"=&f"(ftmp[8]),    [ftmp1]"=&f"(ftmp[9]),
>+          [ftmp2]"=&f"(ftmp[10]),   [ftmp3]"=&f"(ftmp[11]),
>+          [hev]"=&f"(ftmp[12]),     [mask]"=&f"(ftmp[13]),
>+          [ftmp4]"=&f"(ftmp[14]),   [ftmp5]"=&f"(ftmp[15]),
>+          [ftmp6]"=&f"(ftmp[16]),   [ftmp7]"=&f"(ftmp[17]),
>+          [dst]"+&r"(dst),          [tmp0]"=&r"(tmp[0]),
>+          RESTRICT_ASM_DOUBLE_1,    RESTRICT_ASM_DOUBLE_2,
>+          RESTRICT_ASM_UINT32_T
>+        : [e]"r"((mips_reg)flim_E), [thresh]"r"((mips_reg)hev_thresh),
>+          [i]"r"((mips_reg)flim_I), [stride]"r"((mips_reg)stride)
>+        : "memory"
>+    );
> }
>
> static av_always_inline void vp8_v_loop_filter8_inner_mmi(uint8_t *dst,
>@@ -650,15 +921,87 @@ static av_always_inline void vp8_v_loop_filter8_inner_mmi(uint8_t *dst,
> static av_always_inline void vp8_h_loop_filter8_mmi(uint8_t *dst,
>         ptrdiff_t stride, int flim_E, int flim_I, int hev_thresh)
> {
>-    int i;
>-
>-    for (i = 0; i < 8; i++)
>-        if (vp8_normal_limit(dst + i * stride, 1, flim_E, flim_I)) {
>-            if (hev(dst + i * stride, 1, hev_thresh))
>-                vp8_filter_common_is4tap(dst + i * stride, 1);
>-            else
>-                filter_mbedge(dst + i * stride, 1);
>-        }
>+    double ftmp[18];
>+    uint32_t tmp[1];
>+    DECLARE_DOUBLE_1;
>+    DECLARE_DOUBLE_2;
>+    DECLARE_UINT32_T;
>+    __asm__ volatile(
>+        /* Get data from dst */
>+        "gsldlc1    %[p3],        0x03(%[dst])                    \n\t"
>+        "gsldrc1    %[p3],        -0x04(%[dst])                   \n\t"
>+        PTR_ADDU    "%[tmp0],     %[dst],           %[stride]     \n\t"
>+        "gsldlc1    %[p2],        0x03(%[tmp0])                   \n\t"
>+        "gsldrc1    %[p2],        -0x04(%[tmp0])                  \n\t"
>+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
>+        "gsldlc1    %[p1],        0x03(%[tmp0])                   \n\t"
>+        "gsldrc1    %[p1],        -0x04(%[tmp0])                  \n\t"
>+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
>+        "gsldlc1    %[p0],        0x03(%[tmp0])                   \n\t"
>+        "gsldrc1    %[p0],        -0x04(%[tmp0])                  \n\t"
>+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
>+        "gsldlc1    %[q0],        0x03(%[tmp0])                   \n\t"
>+        "gsldrc1    %[q0],        -0x04(%[tmp0])                  \n\t"
>+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
>+        "gsldlc1    %[q1],        0x03(%[tmp0])                   \n\t"
>+        "gsldrc1    %[q1],        -0x04(%[tmp0])                  \n\t"
>+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
>+        "gsldlc1    %[q2],        0x03(%[tmp0])                   \n\t"
>+        "gsldrc1    %[q2],        -0x04(%[tmp0])                  \n\t"
>+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
>+        "gsldlc1    %[q3],        0x03(%[tmp0])                   \n\t"
>+        "gsldrc1    %[q3],        -0x04(%[tmp0])                  \n\t"
>+        /* Matrix transpose */
>+        MMI_TRANSPOSE8x8_UB_UB(%[p3], %[p2], %[p1], %[p0],
>+                               %[q0], %[q1], %[q2], %[q3],
>+                               %[p3], %[p2], %[p1], %[p0],
>+                               %[q0], %[q1], %[q2], %[q3])
>+        MMI_VP8_LOOP_FILTER
>+        /* Matrix transpose */
>+        MMI_TRANSPOSE8x8_UB_UB(%[p3], %[p2], %[p1], %[p0],
>+                               %[q0], %[q1], %[q2], %[q3],
>+                               %[p3], %[p2], %[p1], %[p0],
>+                               %[q0], %[q1], %[q2], %[q3])
>+        /* Move to dst */
>+        "gssdlc1    %[p3],        0x03(%[dst])                    \n\t"
>+        "gssdrc1    %[p3],        -0x04(%[dst])                   \n\t"
>+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
>+        "gssdlc1    %[p2],        0x03(%[dst])                    \n\t"
>+        "gssdrc1    %[p2],        -0x04(%[dst])                   \n\t"
>+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
>+        "gssdlc1    %[p1],        0x03(%[dst])                    \n\t"
>+        "gssdrc1    %[p1],        -0x04(%[dst])                   \n\t"
>+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
>+        "gssdlc1    %[p0],        0x03(%[dst])                    \n\t"
>+        "gssdrc1    %[p0],        -0x04(%[dst])                   \n\t"
>+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
>+        "gssdlc1    %[q0],        0x03(%[dst])                    \n\t"
>+        "gssdrc1    %[q0],        -0x04(%[dst])                   \n\t"
>+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
>+        "gssdlc1    %[q1],        0x03(%[dst])                    \n\t"
>+        "gssdrc1    %[q1],        -0x04(%[dst])                   \n\t"
>+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
>+        "gssdlc1    %[q2],        0x03(%[dst])                    \n\t"
>+        "gssdrc1    %[q2],        -0x04(%[dst])                   \n\t"
>+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
>+        "gssdlc1    %[q3],        0x03(%[dst])                    \n\t"
>+        "gssdrc1    %[q3],        -0x04(%[dst])                   \n\t"
>+        : [p3]"=&f"(ftmp[0]),       [p2]"=&f"(ftmp[1]),
>+          [p1]"=&f"(ftmp[2]),       [p0]"=&f"(ftmp[3]),
>+          [q0]"=&f"(ftmp[4]),       [q1]"=&f"(ftmp[5]),
>+          [q2]"=&f"(ftmp[6]),       [q3]"=&f"(ftmp[7]),
>+          [ftmp0]"=&f"(ftmp[8]),    [ftmp1]"=&f"(ftmp[9]),
>+          [ftmp2]"=&f"(ftmp[10]),   [ftmp3]"=&f"(ftmp[11]),
>+          [hev]"=&f"(ftmp[12]),     [mask]"=&f"(ftmp[13]),
>+          [ftmp4]"=&f"(ftmp[14]),   [ftmp5]"=&f"(ftmp[15]),
>+          [ftmp6]"=&f"(ftmp[16]),   [ftmp7]"=&f"(ftmp[17]),
>+          [dst]"+&r"(dst),          [tmp0]"=&r"(tmp[0]),
>+          RESTRICT_ASM_DOUBLE_1,    RESTRICT_ASM_DOUBLE_2,
>+          RESTRICT_ASM_UINT32_T
>+        : [e]"r"((mips_reg)flim_E), [thresh]"r"((mips_reg)hev_thresh),
>+          [i]"r"((mips_reg)flim_I), [stride]"r"((mips_reg)stride)
>+        : "memory"
>+    );
> }
>
> static av_always_inline void vp8_h_loop_filter8_inner_mmi(uint8_t *dst,
>@@ -1083,29 +1426,16 @@ void ff_vp8_idct_dc_add4uv_mmi(uint8_t *dst, int16_t block[4][16],
> void ff_vp8_v_loop_filter16_mmi(uint8_t *dst, ptrdiff_t stride, int flim_E,
>         int flim_I, int hev_thresh)
> {
>-    int i;
>-
>-    for (i = 0; i < 16; i++)
>-        if (vp8_normal_limit(dst + i * 1, stride, flim_E, flim_I)) {
>-            if (hev(dst + i * 1, stride, hev_thresh))
>-                vp8_filter_common_is4tap(dst + i * 1, stride);
>-            else
>-                filter_mbedge(dst + i * 1, stride);
>-        }
>+    vp8_v_loop_filter8_mmi(dst, stride, flim_E, flim_I, hev_thresh);
>+    vp8_v_loop_filter8_mmi(dst + 8, stride, flim_E, flim_I, hev_thresh);
> }
>
> void ff_vp8_h_loop_filter16_mmi(uint8_t *dst, ptrdiff_t stride, int flim_E,
>         int flim_I, int hev_thresh)
> {
>-    int i;
>-
>-    for (i = 0; i < 16; i++)
>-        if (vp8_normal_limit(dst + i * stride, 1, flim_E, flim_I)) {
>-            if (hev(dst + i * stride, 1, hev_thresh))
>-                vp8_filter_common_is4tap(dst + i * stride, 1);
>-            else
>-                filter_mbedge(dst + i * stride, 1);
>-        }
>+    vp8_h_loop_filter8_mmi(dst, stride, flim_E, flim_I, hev_thresh);
>+    vp8_h_loop_filter8_mmi(dst + 8 * stride, stride, flim_E, flim_I,
>+                           hev_thresh);
> }
>
> void ff_vp8_v_loop_filter8uv_mmi(uint8_t *dstU, uint8_t *dstV, ptrdiff_t stride,
>diff --git a/libavutil/mips/mmiutils.h b/libavutil/mips/mmiutils.h
>index 2b1a521..b16edc4 100644
>--- a/libavutil/mips/mmiutils.h
>+++ b/libavutil/mips/mmiutils.h
>@@ -275,6 +275,34 @@
>         "punpcklwd  "#m3",  "#t2",  "#t4"                           \n\t" \
>         "punpckhwd  "#m4",  "#t2",  "#t4"                           \n\t"
>
>+/**
>+ * brief: Parallel SRA for 8 byte packaged data.
>+ * fr_i0: src
>+ * fr_i1: SRA number(SRAB number + 8)
>+ * fr_t0, fr_t1: temporary register
>+ * fr_d0: dst
>+ */
>+#define PSRAB_MMI(fr_i0, fr_i1, fr_t0, fr_t1, fr_d0)                      \
>+        "punpcklbh    "#fr_t0",   "#fr_t0",   "#fr_i0"              \n\t" \
>+        "punpckhbh    "#fr_t1",   "#fr_t1",   "#fr_i0"              \n\t" \
>+        "psrah        "#fr_t0",   "#fr_t0",   "#fr_i1"              \n\t" \
>+        "psrah        "#fr_t1",   "#fr_t1",   "#fr_i1"              \n\t" \
>+        "packsshb     "#fr_d0",   "#fr_t0",   "#fr_t1"              \n\t"
>+
>+/**
>+ * brief: Parallel SRL for 8 byte packaged data.
>+ * fr_i0: src
>+ * fr_i1: SRL number(SRLB number + 8)
>+ * fr_t0, fr_t1: temporary register
>+ * fr_d0: dst
>+ */
>+#define PSRLB_MMI(fr_i0, fr_i1, fr_t0, fr_t1, fr_d0)                      \
>+        "punpcklbh    "#fr_t0",   "#fr_t0",   "#fr_i0"              \n\t" \
>+        "punpckhbh    "#fr_t1",   "#fr_t1",   "#fr_i0"              \n\t" \
>+        "psrlh        "#fr_t0",   "#fr_t0",   "#fr_i1"              \n\t" \
>+        "psrlh        "#fr_t1",   "#fr_t1",   "#fr_i1"              \n\t" \
>+        "packsshb     "#fr_d0",   "#fr_t0",   "#fr_t1"              \n\t"
>+
>
> #define PSRAH_4_MMI(fp1, fp2, fp3, fp4, shift)                              \
>         "psrah      "#fp1",     "#fp1",     "#shift"                \n\t"   \
>--
>2.1.0

Hi Michael, could you please help to review this patch.
diff mbox

Patch

diff --git a/libavcodec/mips/vp8dsp_mmi.c b/libavcodec/mips/vp8dsp_mmi.c
index f972628..b24a87a 100644
--- a/libavcodec/mips/vp8dsp_mmi.c
+++ b/libavcodec/mips/vp8dsp_mmi.c
@@ -25,6 +25,221 @@ 
 #include "constants.h"
 #include "libavutil/mips/mmiutils.h"
 
+#define DECLARE_DOUBLE_1            double db_1
+#define DECLARE_DOUBLE_2            double db_2
+#define DECLARE_UINT32_T            uint32_t  it_1
+#define RESTRICT_ASM_DOUBLE_1       [db_1]"=&f"(db_1)
+#define RESTRICT_ASM_DOUBLE_2       [db_2]"=&f"(db_2)
+#define RESTRICT_ASM_UINT32_T       [it_1]"=&r"(it_1)
+
+#define MMI_PCMPGTUB(dst, src1, src2)                                       \
+        "pcmpeqb    %[db_1],    "#src1",        "#src2"             \n\t"   \
+        "pmaxub     %[db_2],    "#src1",        "#src2"             \n\t"   \
+        "pcmpeqb    %[db_2],    %[db_2],        "#src1"             \n\t"   \
+        "xor        "#dst",     %[db_2],        %[db_1]             \n\t"
+
+#define MMI_BTOH(dst_l, dst_r, src)                                         \
+        "xor        %[db_1],    %[db_1],        %[db_1]             \n\t"   \
+        "pcmpgtb    %[db_2],    %[db_1],        "#src"              \n\t"   \
+        "punpcklbh  "#dst_r",   "#src",         %[db_2]             \n\t"   \
+        "punpckhbh  "#dst_l",   "#src",         %[db_2]             \n\t"
+
+#define MMI_TRANSPOSE8x8_UB_UB(src_0, src_1, src_2, src_3,                  \
+                               src_4, src_5, src_6, src_7,                  \
+                               dst_0, dst_1, dst_2, dst_3,                  \
+                               dst_4, dst_5, dst_6, dst_7)                  \
+        "li         %[it_1],    0xe4                                \n\t"   \
+        "dmtc1      %[it_1],    %[db_1]                             \n\t"   \
+        "pshufh     %[db_2],    "#src_0",       %[db_1]             \n\t"   \
+        "punpcklbh  "#dst_0",   "#src_0",       "#src_1"            \n\t"   \
+        "punpckhbh  "#dst_1",   %[db_2],        "#src_1"            \n\t"   \
+        "pshufh     %[db_2],    "#src_2",       %[db_1]             \n\t"   \
+        "punpcklbh  "#dst_2",   "#src_2",       "#src_3"            \n\t"   \
+        "punpckhbh  "#dst_3",   %[db_2],        "#src_3"            \n\t"   \
+        "pshufh     %[db_2],    "#src_4",       %[db_1]             \n\t"   \
+        "punpcklbh  "#dst_4",   "#src_4",       "#src_5"            \n\t"   \
+        "punpckhbh  "#dst_5",   %[db_2],        "#src_5"            \n\t"   \
+        "pshufh     %[db_2],    "#src_6",       %[db_1]             \n\t"   \
+        "punpcklbh  "#dst_6",   "#src_6",       "#src_7"            \n\t"   \
+        "punpckhbh  "#dst_7",   %[db_2],        "#src_7"            \n\t"   \
+                                                                            \
+        "pshufh     %[db_2],    "#dst_0",       %[db_1]             \n\t"   \
+        "punpcklhw  "#dst_0",   "#dst_0",       "#dst_2"            \n\t"   \
+        "punpckhhw  "#dst_2",   %[db_2],        "#dst_2"            \n\t"   \
+        "pshufh     %[db_2],    "#dst_1",       %[db_1]             \n\t"   \
+        "punpcklhw  "#dst_1",   "#dst_1",       "#dst_3"            \n\t"   \
+        "punpckhhw  "#dst_3",   %[db_2],        "#dst_3"            \n\t"   \
+        "pshufh     %[db_2],    "#dst_4",       %[db_1]             \n\t"   \
+        "punpcklhw  "#dst_4",   "#dst_4",       "#dst_6"            \n\t"   \
+        "punpckhhw  "#dst_6",   %[db_2],        "#dst_6"            \n\t"   \
+        "pshufh     %[db_2],    "#dst_5",       %[db_1]             \n\t"   \
+        "punpcklhw  "#dst_5",   "#dst_5",       "#dst_7"            \n\t"   \
+        "punpckhhw  "#dst_7",   %[db_2],        "#dst_7"            \n\t"   \
+                                                                            \
+        "pshufh     %[db_2],    "#dst_0",       %[db_1]             \n\t"   \
+        "punpcklwd  "#dst_0",   "#dst_0",       "#dst_4"            \n\t"   \
+        "punpckhwd  "#dst_4",   %[db_2],        "#dst_4"            \n\t"   \
+        "pshufh     %[db_2],    "#dst_1",       %[db_1]             \n\t"   \
+        "punpcklwd  "#dst_1",   "#dst_1",       "#dst_5"            \n\t"   \
+        "punpckhwd  "#dst_5",   %[db_2],        "#dst_5"            \n\t"   \
+        "pshufh     %[db_2],    "#dst_2",       %[db_1]             \n\t"   \
+        "punpcklwd  "#dst_2",   "#dst_2",       "#dst_6"            \n\t"   \
+        "punpckhwd  "#dst_6",   %[db_2],        "#dst_6"            \n\t"   \
+        "pshufh     %[db_2],    "#dst_3",       %[db_1]             \n\t"   \
+        "punpcklwd  "#dst_3",   "#dst_3",       "#dst_7"            \n\t"   \
+        "punpckhwd  "#dst_7",   %[db_2],        "#dst_7"            \n\t"   \
+                                                                            \
+        "pshufh     %[db_2],    "#dst_1",       %[db_1]             \n\t"   \
+        "pshufh     "#dst_1",   "#dst_4",       %[db_1]             \n\t"   \
+        "pshufh     "#dst_4",   %[db_2],        %[db_1]             \n\t"   \
+        "pshufh     %[db_2],    "#dst_3",       %[db_1]             \n\t"   \
+        "pshufh     "#dst_3",   "#dst_6",       %[db_1]             \n\t"   \
+        "pshufh     "#dst_6",   %[db_2],        %[db_1]             \n\t"
+
+#define MMI_VP8_LOOP_FILTER                                                 \
+        /* Calculation of hev */                                            \
+        "dmtc1      %[thresh],  %[ftmp3]                            \n\t"   \
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        "pasubub    %[ftmp0],   %[p1],          %[p0]               \n\t"   \
+        "pasubub    %[ftmp1],   %[q1],          %[q0]               \n\t"   \
+        "pmaxub     %[ftmp0],   %[ftmp0],       %[ftmp1]            \n\t"   \
+        MMI_PCMPGTUB(%[hev], %[ftmp0], %[ftmp3])                            \
+        /* Calculation of mask */                                           \
+        "pasubub    %[ftmp1],   %[p0],          %[q0]               \n\t"   \
+        "paddusb    %[ftmp1],   %[ftmp1],       %[ftmp1]            \n\t"   \
+        "pasubub    %[ftmp2],   %[p1],          %[q1]               \n\t"   \
+        "li         %[tmp0],    0x09                                \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp3]                            \n\t"   \
+        PSRLB_MMI(%[ftmp2],  %[ftmp3],  %[ftmp4],  %[ftmp5],  %[ftmp2])     \
+        "paddusb    %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"   \
+        "dmtc1      %[e],       %[ftmp3]                            \n\t"   \
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        MMI_PCMPGTUB(%[mask], %[ftmp1], %[ftmp3])                           \
+        "pmaxub     %[mask],    %[mask],        %[ftmp0]            \n\t"   \
+        "pasubub    %[ftmp1],   %[p3],          %[p2]               \n\t"   \
+        "pasubub    %[ftmp2],   %[p2],          %[p1]               \n\t"   \
+        "pmaxub     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"   \
+        "pmaxub     %[mask],    %[mask],        %[ftmp1]            \n\t"   \
+        "pasubub    %[ftmp1],   %[q3],          %[q2]               \n\t"   \
+        "pasubub    %[ftmp2],   %[q2],          %[q1]               \n\t"   \
+        "pmaxub     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"   \
+        "pmaxub     %[mask],    %[mask],        %[ftmp1]            \n\t"   \
+        "dmtc1      %[i],       %[ftmp3]                            \n\t"   \
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        MMI_PCMPGTUB(%[mask], %[mask], %[ftmp3])                            \
+        "pcmpeqw    %[ftmp3],   %[ftmp3],       %[ftmp3]            \n\t"   \
+        "xor        %[mask],    %[mask],        %[ftmp3]            \n\t"   \
+        /* VP8_MBFILTER */                                                  \
+        "li         %[tmp0],    0x80808080                          \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp7]                            \n\t"   \
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp7]            \n\t"   \
+        "xor        %[p2],      %[p2],          %[ftmp7]            \n\t"   \
+        "xor        %[p1],      %[p1],          %[ftmp7]            \n\t"   \
+        "xor        %[p0],      %[p0],          %[ftmp7]            \n\t"   \
+        "xor        %[q0],      %[q0],          %[ftmp7]            \n\t"   \
+        "xor        %[q1],      %[q1],          %[ftmp7]            \n\t"   \
+        "xor        %[q2],      %[q2],          %[ftmp7]            \n\t"   \
+        "psubsb     %[ftmp4],   %[p1],          %[q1]               \n\t"   \
+        "psubb      %[ftmp5],   %[q0],          %[p0]               \n\t"   \
+        MMI_BTOH(%[ftmp1],  %[ftmp0],  %[ftmp5])                            \
+        MMI_BTOH(%[ftmp3],  %[ftmp2],  %[ftmp4])                            \
+        /* Right part */                                                    \
+        "paddh      %[ftmp5],   %[ftmp0],       %[ftmp0]            \n\t"   \
+        "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"   \
+        "paddh      %[ftmp0],   %[ftmp2],       %[ftmp0]            \n\t"   \
+        /* Left part */                                                     \
+        "paddh      %[ftmp5],   %[ftmp1],       %[ftmp1]            \n\t"   \
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"   \
+        "paddh      %[ftmp1],   %[ftmp3],       %[ftmp1]            \n\t"   \
+        /* Combine left and right part */                                   \
+        "packsshb   %[ftmp1],   %[ftmp0],       %[ftmp1]            \n\t"   \
+        "and        %[ftmp1],   %[ftmp1],       %[mask]             \n\t"   \
+        "and        %[ftmp2],   %[ftmp1],       %[hev]              \n\t"   \
+        "li         %[tmp0],    0x04040404                          \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp0]                            \n\t"   \
+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"   \
+        "paddsb     %[ftmp3],   %[ftmp2],       %[ftmp0]            \n\t"   \
+        "li         %[tmp0],    0x0B                                \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp4]                            \n\t"   \
+        PSRAB_MMI(%[ftmp3],  %[ftmp4],  %[ftmp5],  %[ftmp6],  %[ftmp3])     \
+        "li         %[tmp0],    0x03030303                          \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp0]                            \n\t"   \
+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"   \
+        "paddsb     %[ftmp4],   %[ftmp2],       %[ftmp0]            \n\t"   \
+        "li         %[tmp0],    0x0B                                \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp2]                            \n\t"   \
+        PSRAB_MMI(%[ftmp4],  %[ftmp2],  %[ftmp5],  %[ftmp6],  %[ftmp4])     \
+        "psubsb     %[q0],      %[q0],          %[ftmp3]            \n\t"   \
+        "paddsb     %[p0],      %[p0],          %[ftmp4]            \n\t"   \
+        /* filt_val &= ~hev */                                              \
+        "pcmpeqw    %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"   \
+        "xor        %[hev],     %[hev],         %[ftmp0]            \n\t"   \
+        "and        %[ftmp1],   %[ftmp1],       %[hev]              \n\t"   \
+        MMI_BTOH(%[ftmp5],  %[ftmp6],  %[ftmp1])                            \
+        "li         %[tmp0],    0x07                                \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp2]                            \n\t"   \
+        "li         %[tmp0],    0x001b001b                          \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp1]                            \n\t"   \
+        "punpcklwd  %[ftmp1],   %[ftmp1],       %[ftmp1]            \n\t"   \
+        "li         %[tmp0],    0x003f003f                          \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp0]                            \n\t"   \
+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"   \
+        /* Right part */                                                    \
+        "pmullh     %[ftmp3],   %[ftmp6],       %[ftmp1]            \n\t"   \
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"   \
+        "psrah      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"   \
+        /* Left part */                                                     \
+        "pmullh     %[ftmp4],   %[ftmp5],       %[ftmp1]            \n\t"   \
+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"   \
+        "psrah      %[ftmp4],   %[ftmp4],       %[ftmp2]            \n\t"   \
+        /* Combine left and right part */                                   \
+        "packsshb   %[ftmp4],   %[ftmp3],       %[ftmp4]            \n\t"   \
+        "psubsb     %[q0],      %[q0],          %[ftmp4]            \n\t"   \
+        "xor        %[q0],      %[q0],          %[ftmp7]            \n\t"   \
+        "paddsb     %[p0],      %[p0],          %[ftmp4]            \n\t"   \
+        "xor        %[p0],      %[p0],          %[ftmp7]            \n\t"   \
+        "li         %[tmp0],    0x00120012                          \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp1]                            \n\t"   \
+        "punpcklwd  %[ftmp1],   %[ftmp1],       %[ftmp1]            \n\t"   \
+        /* Right part */                                                    \
+        "pmullh     %[ftmp3],   %[ftmp6],       %[ftmp1]            \n\t"   \
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"   \
+        "psrah      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"   \
+        /* Left part */                                                     \
+        "pmullh     %[ftmp4],   %[ftmp5],       %[ftmp1]            \n\t"   \
+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"   \
+        "psrah      %[ftmp4],   %[ftmp4],       %[ftmp2]            \n\t"   \
+        /* Combine left and right part */                                   \
+        "packsshb   %[ftmp4],   %[ftmp3],       %[ftmp4]            \n\t"   \
+        "psubsb     %[q1],      %[q1],          %[ftmp4]            \n\t"   \
+        "xor        %[q1],      %[q1],          %[ftmp7]            \n\t"   \
+        "paddsb     %[p1],      %[p1],          %[ftmp4]            \n\t"   \
+        "xor        %[p1],      %[p1],          %[ftmp7]            \n\t"   \
+        "li         %[tmp0],    0x03                                \n\t"   \
+        "dmtc1      %[tmp0],    %[ftmp1]                            \n\t"   \
+        /* Right part */                                                    \
+        "psllh      %[ftmp3],   %[ftmp6],       %[ftmp1]            \n\t"   \
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp6]            \n\t"   \
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"   \
+        "psrah      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"   \
+        /* Left part */                                                     \
+        "psllh      %[ftmp4],   %[ftmp5],       %[ftmp1]            \n\t"   \
+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp5]            \n\t"   \
+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"   \
+        "psrah      %[ftmp4],   %[ftmp4],       %[ftmp2]            \n\t"   \
+        /* Combine left and right part */                                   \
+        "packsshb   %[ftmp4],   %[ftmp3],       %[ftmp4]            \n\t"   \
+        "psubsb     %[q2],      %[q2],          %[ftmp4]            \n\t"   \
+        "xor        %[q2],      %[q2],          %[ftmp7]            \n\t"   \
+        "paddsb     %[p2],      %[p2],          %[ftmp4]            \n\t"   \
+        "xor        %[p2],      %[p2],          %[ftmp7]            \n\t"
+
 #define PUT_VP8_EPEL4_H6_MMI(src, dst)                                      \
         MMI_ULWC1(%[ftmp1], src, 0x00)                                      \
         "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"   \
@@ -621,15 +836,71 @@  static av_always_inline int vp8_normal_limit(uint8_t *p, ptrdiff_t stride,
 static av_always_inline void vp8_v_loop_filter8_mmi(uint8_t *dst,
         ptrdiff_t stride, int flim_E, int flim_I, int hev_thresh)
 {
-    int i;
-
-    for (i = 0; i < 8; i++)
-        if (vp8_normal_limit(dst + i * 1, stride, flim_E, flim_I)) {
-            if (hev(dst + i * 1, stride, hev_thresh))
-                vp8_filter_common_is4tap(dst + i * 1, stride);
-            else
-                filter_mbedge(dst + i * 1, stride);
-        }
+    double ftmp[18];
+    uint32_t tmp[1];
+    DECLARE_DOUBLE_1;
+    DECLARE_DOUBLE_2;
+    DECLARE_UINT32_T;
+    __asm__ volatile(
+        /* Get data from dst */
+        "gsldlc1    %[q0],      0x07(%[dst])                      \n\t"
+        "gsldrc1    %[q0],      0x00(%[dst])                      \n\t"
+        PTR_SUBU    "%[tmp0],   %[dst],         %[stride]         \n\t"
+        "gsldlc1    %[p0],      0x07(%[tmp0])                     \n\t"
+        "gsldrc1    %[p0],      0x00(%[tmp0])                     \n\t"
+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
+        "gsldlc1    %[p1],      0x07(%[tmp0])                     \n\t"
+        "gsldrc1    %[p1],      0x00(%[tmp0])                     \n\t"
+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
+        "gsldlc1    %[p2],      0x07(%[tmp0])                     \n\t"
+        "gsldrc1    %[p2],      0x00(%[tmp0])                     \n\t"
+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
+        "gsldlc1    %[p3],      0x07(%[tmp0])                     \n\t"
+        "gsldrc1    %[p3],      0x00(%[tmp0])                     \n\t"
+        PTR_ADDU    "%[tmp0],   %[dst],         %[stride]         \n\t"
+        "gsldlc1    %[q1],      0x07(%[tmp0])                     \n\t"
+        "gsldrc1    %[q1],      0x00(%[tmp0])                     \n\t"
+        PTR_ADDU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
+        "gsldlc1    %[q2],      0x07(%[tmp0])                     \n\t"
+        "gsldrc1    %[q2],      0x00(%[tmp0])                     \n\t"
+        PTR_ADDU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
+        "gsldlc1    %[q3],      0x07(%[tmp0])                     \n\t"
+        "gsldrc1    %[q3],      0x00(%[tmp0])                     \n\t"
+        MMI_VP8_LOOP_FILTER
+        /* Move to dst */
+        "gssdlc1    %[q0],      0x07(%[dst])                      \n\t"
+        "gssdrc1    %[q0],      0x00(%[dst])                      \n\t"
+        PTR_SUBU    "%[tmp0],   %[dst],         %[stride]         \n\t"
+        "gssdlc1    %[p0],      0x07(%[tmp0])                     \n\t"
+        "gssdrc1    %[p0],      0x00(%[tmp0])                     \n\t"
+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
+        "gssdlc1    %[p1],      0x07(%[tmp0])                     \n\t"
+        "gssdrc1    %[p1],      0x00(%[tmp0])                     \n\t"
+        PTR_SUBU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
+        "gssdlc1    %[p2],      0x07(%[tmp0])                     \n\t"
+        "gssdrc1    %[p2],      0x00(%[tmp0])                     \n\t"
+        PTR_ADDU    "%[tmp0],   %[dst],         %[stride]         \n\t"
+        "gssdlc1    %[q1],      0x07(%[tmp0])                     \n\t"
+        "gssdrc1    %[q1],      0x00(%[tmp0])                     \n\t"
+        PTR_ADDU    "%[tmp0],   %[tmp0],        %[stride]         \n\t"
+        "gssdlc1    %[q2],      0x07(%[tmp0])                     \n\t"
+        "gssdrc1    %[q2],      0x00(%[tmp0])                     \n\t"
+        : [p3]"=&f"(ftmp[0]),       [p2]"=&f"(ftmp[1]),
+          [p1]"=&f"(ftmp[2]),       [p0]"=&f"(ftmp[3]),
+          [q0]"=&f"(ftmp[4]),       [q1]"=&f"(ftmp[5]),
+          [q2]"=&f"(ftmp[6]),       [q3]"=&f"(ftmp[7]),
+          [ftmp0]"=&f"(ftmp[8]),    [ftmp1]"=&f"(ftmp[9]),
+          [ftmp2]"=&f"(ftmp[10]),   [ftmp3]"=&f"(ftmp[11]),
+          [hev]"=&f"(ftmp[12]),     [mask]"=&f"(ftmp[13]),
+          [ftmp4]"=&f"(ftmp[14]),   [ftmp5]"=&f"(ftmp[15]),
+          [ftmp6]"=&f"(ftmp[16]),   [ftmp7]"=&f"(ftmp[17]),
+          [dst]"+&r"(dst),          [tmp0]"=&r"(tmp[0]),
+          RESTRICT_ASM_DOUBLE_1,    RESTRICT_ASM_DOUBLE_2,
+          RESTRICT_ASM_UINT32_T
+        : [e]"r"((mips_reg)flim_E), [thresh]"r"((mips_reg)hev_thresh),
+          [i]"r"((mips_reg)flim_I), [stride]"r"((mips_reg)stride)
+        : "memory"
+    );
 }
 
 static av_always_inline void vp8_v_loop_filter8_inner_mmi(uint8_t *dst,
@@ -650,15 +921,87 @@  static av_always_inline void vp8_v_loop_filter8_inner_mmi(uint8_t *dst,
 static av_always_inline void vp8_h_loop_filter8_mmi(uint8_t *dst,
         ptrdiff_t stride, int flim_E, int flim_I, int hev_thresh)
 {
-    int i;
-
-    for (i = 0; i < 8; i++)
-        if (vp8_normal_limit(dst + i * stride, 1, flim_E, flim_I)) {
-            if (hev(dst + i * stride, 1, hev_thresh))
-                vp8_filter_common_is4tap(dst + i * stride, 1);
-            else
-                filter_mbedge(dst + i * stride, 1);
-        }
+    double ftmp[18];
+    uint32_t tmp[1];
+    DECLARE_DOUBLE_1;
+    DECLARE_DOUBLE_2;
+    DECLARE_UINT32_T;
+    __asm__ volatile(
+        /* Get data from dst */
+        "gsldlc1    %[p3],        0x03(%[dst])                    \n\t"
+        "gsldrc1    %[p3],        -0x04(%[dst])                   \n\t"
+        PTR_ADDU    "%[tmp0],     %[dst],           %[stride]     \n\t"
+        "gsldlc1    %[p2],        0x03(%[tmp0])                   \n\t"
+        "gsldrc1    %[p2],        -0x04(%[tmp0])                  \n\t"
+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
+        "gsldlc1    %[p1],        0x03(%[tmp0])                   \n\t"
+        "gsldrc1    %[p1],        -0x04(%[tmp0])                  \n\t"
+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
+        "gsldlc1    %[p0],        0x03(%[tmp0])                   \n\t"
+        "gsldrc1    %[p0],        -0x04(%[tmp0])                  \n\t"
+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
+        "gsldlc1    %[q0],        0x03(%[tmp0])                   \n\t"
+        "gsldrc1    %[q0],        -0x04(%[tmp0])                  \n\t"
+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
+        "gsldlc1    %[q1],        0x03(%[tmp0])                   \n\t"
+        "gsldrc1    %[q1],        -0x04(%[tmp0])                  \n\t"
+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
+        "gsldlc1    %[q2],        0x03(%[tmp0])                   \n\t"
+        "gsldrc1    %[q2],        -0x04(%[tmp0])                  \n\t"
+        PTR_ADDU    "%[tmp0],     %[tmp0],          %[stride]     \n\t"
+        "gsldlc1    %[q3],        0x03(%[tmp0])                   \n\t"
+        "gsldrc1    %[q3],        -0x04(%[tmp0])                  \n\t"
+        /* Matrix transpose */
+        MMI_TRANSPOSE8x8_UB_UB(%[p3], %[p2], %[p1], %[p0],
+                               %[q0], %[q1], %[q2], %[q3],
+                               %[p3], %[p2], %[p1], %[p0],
+                               %[q0], %[q1], %[q2], %[q3])
+        MMI_VP8_LOOP_FILTER
+        /* Matrix transpose */
+        MMI_TRANSPOSE8x8_UB_UB(%[p3], %[p2], %[p1], %[p0],
+                               %[q0], %[q1], %[q2], %[q3],
+                               %[p3], %[p2], %[p1], %[p0],
+                               %[q0], %[q1], %[q2], %[q3])
+        /* Move to dst */
+        "gssdlc1    %[p3],        0x03(%[dst])                    \n\t"
+        "gssdrc1    %[p3],        -0x04(%[dst])                   \n\t"
+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
+        "gssdlc1    %[p2],        0x03(%[dst])                    \n\t"
+        "gssdrc1    %[p2],        -0x04(%[dst])                   \n\t"
+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
+        "gssdlc1    %[p1],        0x03(%[dst])                    \n\t"
+        "gssdrc1    %[p1],        -0x04(%[dst])                   \n\t"
+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
+        "gssdlc1    %[p0],        0x03(%[dst])                    \n\t"
+        "gssdrc1    %[p0],        -0x04(%[dst])                   \n\t"
+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
+        "gssdlc1    %[q0],        0x03(%[dst])                    \n\t"
+        "gssdrc1    %[q0],        -0x04(%[dst])                   \n\t"
+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
+        "gssdlc1    %[q1],        0x03(%[dst])                    \n\t"
+        "gssdrc1    %[q1],        -0x04(%[dst])                   \n\t"
+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
+        "gssdlc1    %[q2],        0x03(%[dst])                    \n\t"
+        "gssdrc1    %[q2],        -0x04(%[dst])                   \n\t"
+        PTR_ADDU    "%[dst],      %[dst],           %[stride]     \n\t"
+        "gssdlc1    %[q3],        0x03(%[dst])                    \n\t"
+        "gssdrc1    %[q3],        -0x04(%[dst])                   \n\t"
+        : [p3]"=&f"(ftmp[0]),       [p2]"=&f"(ftmp[1]),
+          [p1]"=&f"(ftmp[2]),       [p0]"=&f"(ftmp[3]),
+          [q0]"=&f"(ftmp[4]),       [q1]"=&f"(ftmp[5]),
+          [q2]"=&f"(ftmp[6]),       [q3]"=&f"(ftmp[7]),
+          [ftmp0]"=&f"(ftmp[8]),    [ftmp1]"=&f"(ftmp[9]),
+          [ftmp2]"=&f"(ftmp[10]),   [ftmp3]"=&f"(ftmp[11]),
+          [hev]"=&f"(ftmp[12]),     [mask]"=&f"(ftmp[13]),
+          [ftmp4]"=&f"(ftmp[14]),   [ftmp5]"=&f"(ftmp[15]),
+          [ftmp6]"=&f"(ftmp[16]),   [ftmp7]"=&f"(ftmp[17]),
+          [dst]"+&r"(dst),          [tmp0]"=&r"(tmp[0]),
+          RESTRICT_ASM_DOUBLE_1,    RESTRICT_ASM_DOUBLE_2,
+          RESTRICT_ASM_UINT32_T
+        : [e]"r"((mips_reg)flim_E), [thresh]"r"((mips_reg)hev_thresh),
+          [i]"r"((mips_reg)flim_I), [stride]"r"((mips_reg)stride)
+        : "memory"
+    );
 }
 
 static av_always_inline void vp8_h_loop_filter8_inner_mmi(uint8_t *dst,
@@ -1083,29 +1426,16 @@  void ff_vp8_idct_dc_add4uv_mmi(uint8_t *dst, int16_t block[4][16],
 void ff_vp8_v_loop_filter16_mmi(uint8_t *dst, ptrdiff_t stride, int flim_E,
         int flim_I, int hev_thresh)
 {
-    int i;
-
-    for (i = 0; i < 16; i++)
-        if (vp8_normal_limit(dst + i * 1, stride, flim_E, flim_I)) {
-            if (hev(dst + i * 1, stride, hev_thresh))
-                vp8_filter_common_is4tap(dst + i * 1, stride);
-            else
-                filter_mbedge(dst + i * 1, stride);
-        }
+    vp8_v_loop_filter8_mmi(dst, stride, flim_E, flim_I, hev_thresh);
+    vp8_v_loop_filter8_mmi(dst + 8, stride, flim_E, flim_I, hev_thresh);
 }
 
 void ff_vp8_h_loop_filter16_mmi(uint8_t *dst, ptrdiff_t stride, int flim_E,
         int flim_I, int hev_thresh)
 {
-    int i;
-
-    for (i = 0; i < 16; i++)
-        if (vp8_normal_limit(dst + i * stride, 1, flim_E, flim_I)) {
-            if (hev(dst + i * stride, 1, hev_thresh))
-                vp8_filter_common_is4tap(dst + i * stride, 1);
-            else
-                filter_mbedge(dst + i * stride, 1);
-        }
+    vp8_h_loop_filter8_mmi(dst, stride, flim_E, flim_I, hev_thresh);
+    vp8_h_loop_filter8_mmi(dst + 8 * stride, stride, flim_E, flim_I,
+                           hev_thresh);
 }
 
 void ff_vp8_v_loop_filter8uv_mmi(uint8_t *dstU, uint8_t *dstV, ptrdiff_t stride,
diff --git a/libavutil/mips/mmiutils.h b/libavutil/mips/mmiutils.h
index 2b1a521..b16edc4 100644
--- a/libavutil/mips/mmiutils.h
+++ b/libavutil/mips/mmiutils.h
@@ -275,6 +275,34 @@ 
         "punpcklwd  "#m3",  "#t2",  "#t4"                           \n\t" \
         "punpckhwd  "#m4",  "#t2",  "#t4"                           \n\t"
 
+/**
+ * brief: Parallel SRA for 8 byte packaged data.
+ * fr_i0: src
+ * fr_i1: SRA number(SRAB number + 8)
+ * fr_t0, fr_t1: temporary register
+ * fr_d0: dst
+ */
+#define PSRAB_MMI(fr_i0, fr_i1, fr_t0, fr_t1, fr_d0)                      \
+        "punpcklbh    "#fr_t0",   "#fr_t0",   "#fr_i0"              \n\t" \
+        "punpckhbh    "#fr_t1",   "#fr_t1",   "#fr_i0"              \n\t" \
+        "psrah        "#fr_t0",   "#fr_t0",   "#fr_i1"              \n\t" \
+        "psrah        "#fr_t1",   "#fr_t1",   "#fr_i1"              \n\t" \
+        "packsshb     "#fr_d0",   "#fr_t0",   "#fr_t1"              \n\t"
+
+/**
+ * brief: Parallel SRL for 8 byte packaged data.
+ * fr_i0: src
+ * fr_i1: SRL number(SRLB number + 8)
+ * fr_t0, fr_t1: temporary register
+ * fr_d0: dst
+ */
+#define PSRLB_MMI(fr_i0, fr_i1, fr_t0, fr_t1, fr_d0)                      \
+        "punpcklbh    "#fr_t0",   "#fr_t0",   "#fr_i0"              \n\t" \
+        "punpckhbh    "#fr_t1",   "#fr_t1",   "#fr_i0"              \n\t" \
+        "psrlh        "#fr_t0",   "#fr_t0",   "#fr_i1"              \n\t" \
+        "psrlh        "#fr_t1",   "#fr_t1",   "#fr_i1"              \n\t" \
+        "packsshb     "#fr_d0",   "#fr_t0",   "#fr_t1"              \n\t"
+
 
 #define PSRAH_4_MMI(fp1, fp2, fp3, fp4, shift)                              \
         "psrah      "#fp1",     "#fp1",     "#shift"                \n\t"   \