/*****************************************************************************
 * Copyright (C) 2024 MulticoreWare, Inc
 *
 * Authors: Peng Zhou <zhoupeng@loongson.cn>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
 *
 * This program is also available under a commercial proprietary license.
 * For more information, contact us at license @ x265.com.
 *****************************************************************************/

#include "loongson_asm.S"

const shuf_1
.byte 14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1
.byte 14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1
endconst

const shuf_2
.byte 12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3
endconst

const shift_1
.byte 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
endconst

const shift_2
.byte 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
endconst

const shift_3
.byte 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
endconst

const entropyStateBits
.int 0x02007B23, 0x000085F9, 0x040074A0, 0x00008CBC, 0x06006EE4, 0x02009354, 0x080067F4, 0x04009C1B
.int 0x0A0060B0, 0x0400A62A, 0x0C005A9C, 0x0800AF5B, 0x0E00548D, 0x0800B955, 0x10004F56, 0x0A00C2A9
.int 0x12004A87, 0x0C00CBF7, 0x140045D6, 0x0E00D5C3, 0x16004144, 0x1000E01B, 0x18003D88, 0x1200E937
.int 0x1A0039E0, 0x1200F2CD, 0x1C003663, 0x1600FC9E, 0x1E003347, 0x16010600, 0x20003050, 0x18010F95
.int 0x22002D4D, 0x1A011A02, 0x24002AD3, 0x1A012333, 0x2600286E, 0x1E012CAD, 0x28002604, 0x1E0136DF
.int 0x2A002425, 0x20013F48, 0x2C0021F4, 0x200149C4, 0x2E00203E, 0x2401527B, 0x30001E4D, 0x24015D00
.int 0x32001C99, 0x260166DE, 0x34001B18, 0x26017017, 0x360019A5, 0x2A017988, 0x38001841, 0x2A018327
.int 0x3A0016DF, 0x2C018D50, 0x3C0015D9, 0x2C019547, 0x3E00147C, 0x2E01A083, 0x4000138E, 0x3001A8A3
.int 0x42001251, 0x3001B418, 0x44001166, 0x3201BD27, 0x46001068, 0x3401C77B, 0x48000F7F, 0x3401D18E
.int 0x4A000EDA, 0x3601D91A, 0x4C000E19, 0x3601E254, 0x4E000D4F, 0x3801EC9A, 0x50000C90, 0x3A01F6E0
.int 0x52000C01, 0x3A01FEF8, 0x54000B5F, 0x3C0208B1, 0x56000AB6, 0x3C021362, 0x58000A15, 0x3C021E46
.int 0x5A000988, 0x3E02285D, 0x5C000934, 0x40022EA8, 0x5E0008A8, 0x400239B2, 0x6000081D, 0x42024577
.int 0x620007C9, 0x42024CE6, 0x64000763, 0x42025663, 0x66000710, 0x44025E8F, 0x680006A0, 0x44026A26
.int 0x6A000672, 0x46026F23, 0x6C0005E8, 0x46027EF8, 0x6E0005BA, 0x460284B5, 0x7000055E, 0x48029057
.int 0x7200050C, 0x48029BAB, 0x740004C1, 0x4802A674, 0x760004A7, 0x4A02AA5E, 0x7800046F, 0x4A02B32F
.int 0x7A00041F, 0x4A02C0AD, 0x7C0003E7, 0x4C02CA8D, 0x7C0003BA, 0x4C02D323, 0x7E00010C, 0x7E03BFBB
endconst

const table_dct16
.int 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
.int 90, 87, 80, 70, 57, 43, 25,  9, -9, -25, -43, -57, -70, -80, -87, -90
.int 89, 75, 50, 18, -18, -50, -75, -89, -89, -75, -50, -18, 18, 50, 75, 89
.int 87, 57,  9, -43, -80, -90, -70, -25, 25, 70, 90, 80, 43, -9, -57, -87
.int 83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83
.int 80,  9, -70, -87, -25, 57, 90, 43, -43, -90, -57, 25, 87, 70, -9, -80
.int 75, -18, -89, -50, 50, 89, 18, -75, -75, 18, 89, 50, -50, -89, -18, 75
.int 70, -43, -87,  9, 90, 25, -80, -57, 57, 80, -25, -90, -9, 87, 43, -70
.int 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64
.int 57, -80, -25, 90, -9, -87, 43, 70, -70, -43, 87,  9, -90, 25, 80, -57
.int 50, -89, 18, 75, -75, -18, 89, -50, -50, 89, -18, -75, 75, 18, -89, 50
.int 43, -90, 57, 25, -87, 70,  9, -80, 80, -9, -70, 87, -25, -57, 90, -43
.int 36, -83, 83, -36, -36, 83, -83, 36, 36, -83, 83, -36, -36, 83, -83, 36
.int 25, -70, 90, -80, 43,  9, -57, 87, -87, 57, -9, -43, 80, -90, 70, -25
.int 18, -50, 75, -89, 89, -75, 50, -18, -18, 50, -75, 89, -89, 75, -50, 18
.int  9, -25, 43, -57, 70, -80, 87, -90, 90, -87, 80, -70, 57, -43, 25, -9
endconst

const table_dct32
.int 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
.int 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13,  4, -4, -13, -22, -31, -38, -46, -54, -61, -67, -73, -78, -82, -85, -88, -90, -90
.int 90, 87, 80, 70, 57, 43, 25,  9, -9, -25, -43, -57, -70, -80, -87, -90, -90, -87, -80, -70, -57, -43, -25, -9,  9, 25, 43, 57, 70, 80, 87, 90
.int 90, 82, 67, 46, 22, -4, -31, -54, -73, -85, -90, -88, -78, -61, -38, -13, 13, 38, 61, 78, 88, 90, 85, 73, 54, 31,  4, -22, -46, -67, -82, -90
.int 89, 75, 50, 18, -18, -50, -75, -89, -89, -75, -50, -18, 18, 50, 75, 89, 89, 75, 50, 18, -18, -50, -75, -89, -89, -75, -50, -18, 18, 50, 75, 89
.int 88, 67, 31, -13, -54, -82, -90, -78, -46, -4, 38, 73, 90, 85, 61, 22, -22, -61, -85, -90, -73, -38,  4, 46, 78, 90, 82, 54, 13, -31, -67, -88
.int 87, 57,  9, -43, -80, -90, -70, -25, 25, 70, 90, 80, 43, -9, -57, -87, -87, -57, -9, 43, 80, 90, 70, 25, -25, -70, -90, -80, -43,  9, 57, 87
.int 85, 46, -13, -67, -90, -73, -22, 38, 82, 88, 54, -4, -61, -90, -78, -31, 31, 78, 90, 61,  4, -54, -88, -82, -38, 22, 73, 90, 67, 13, -46, -85
.int 83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83
.int 82, 22, -54, -90, -61, 13, 78, 85, 31, -46, -90, -67,  4, 73, 88, 38, -38, -88, -73, -4, 67, 90, 46, -31, -85, -78, -13, 61, 90, 54, -22, -82
.int 80,  9, -70, -87, -25, 57, 90, 43, -43, -90, -57, 25, 87, 70, -9, -80, -80, -9, 70, 87, 25, -57, -90, -43, 43, 90, 57, -25, -87, -70,  9, 80
.int 78, -4, -82, -73, 13, 85, 67, -22, -88, -61, 31, 90, 54, -38, -90, -46, 46, 90, 38, -54, -90, -31, 61, 88, 22, -67, -85, -13, 73, 82,  4, -78
.int 75, -18, -89, -50, 50, 89, 18, -75, -75, 18, 89, 50, -50, -89, -18, 75, 75, -18, -89, -50, 50, 89, 18, -75, -75, 18, 89, 50, -50, -89, -18, 75
.int 73, -31, -90, -22, 78, 67, -38, -90, -13, 82, 61, -46, -88, -4, 85, 54, -54, -85,  4, 88, 46, -61, -82, 13, 90, 38, -67, -78, 22, 90, 31, -73
.int 70, -43, -87,  9, 90, 25, -80, -57, 57, 80, -25, -90, -9, 87, 43, -70, -70, 43, 87, -9, -90, -25, 80, 57, -57, -80, 25, 90,  9, -87, -43, 70
.int 67, -54, -78, 38, 85, -22, -90,  4, 90, 13, -88, -31, 82, 46, -73, -61, 61, 73, -46, -82, 31, 88, -13, -90, -4, 90, 22, -85, -38, 78, 54, -67
.int 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64, 64, -64, -64, 64
.int 61, -73, -46, 82, 31, -88, -13, 90, -4, -90, 22, 85, -38, -78, 54, 67, -67, -54, 78, 38, -85, -22, 90,  4, -90, 13, 88, -31, -82, 46, 73, -61
.int 57, -80, -25, 90, -9, -87, 43, 70, -70, -43, 87,  9, -90, 25, 80, -57, -57, 80, 25, -90,  9, 87, -43, -70, 70, 43, -87, -9, 90, -25, -80, 57
.int 54, -85, -4, 88, -46, -61, 82, 13, -90, 38, 67, -78, -22, 90, -31, -73, 73, 31, -90, 22, 78, -67, -38, 90, -13, -82, 61, 46, -88,  4, 85, -54
.int 50, -89, 18, 75, -75, -18, 89, -50, -50, 89, -18, -75, 75, 18, -89, 50, 50, -89, 18, 75, -75, -18, 89, -50, -50, 89, -18, -75, 75, 18, -89, 50
.int 46, -90, 38, 54, -90, 31, 61, -88, 22, 67, -85, 13, 73, -82,  4, 78, -78, -4, 82, -73, -13, 85, -67, -22, 88, -61, -31, 90, -54, -38, 90, -46
.int 43, -90, 57, 25, -87, 70,  9, -80, 80, -9, -70, 87, -25, -57, 90, -43, -43, 90, -57, -25, 87, -70, -9, 80, -80,  9, 70, -87, 25, 57, -90, 43
.int 38, -88, 73, -4, -67, 90, -46, -31, 85, -78, 13, 61, -90, 54, 22, -82, 82, -22, -54, 90, -61, -13, 78, -85, 31, 46, -90, 67,  4, -73, 88, -38
.int 36, -83, 83, -36, -36, 83, -83, 36, 36, -83, 83, -36, -36, 83, -83, 36, 36, -83, 83, -36, -36, 83, -83, 36, 36, -83, 83, -36, -36, 83, -83, 36
.int 31, -78, 90, -61,  4, 54, -88, 82, -38, -22, 73, -90, 67, -13, -46, 85, -85, 46, 13, -67, 90, -73, 22, 38, -82, 88, -54, -4, 61, -90, 78, -31
.int 25, -70, 90, -80, 43,  9, -57, 87, -87, 57, -9, -43, 80, -90, 70, -25, -25, 70, -90, 80, -43, -9, 57, -87, 87, -57,  9, 43, -80, 90, -70, 25
.int 22, -61, 85, -90, 73, -38, -4, 46, -78, 90, -82, 54, -13, -31, 67, -88, 88, -67, 31, 13, -54, 82, -90, 78, -46,  4, 38, -73, 90, -85, 61, -22
.int 18, -50, 75, -89, 89, -75, 50, -18, -18, 50, -75, 89, -89, 75, -50, 18, 18, -50, 75, -89, 89, -75, 50, -18, -18, 50, -75, 89, -89, 75, -50, 18
.int 13, -38, 61, -78, 88, -90, 85, -73, 54, -31,  4, 22, -46, 67, -82, 90, -90, 82, -67, 46, -22, -4, 31, -54, 73, -85, 90, -88, 78, -61, 38, -13
.int  9, -25, 43, -57, 70, -80, 87, -90, 90, -87, 80, -70, 57, -43, 25, -9, -9, 25, -43, 57, -70, 80, -87, 90, -90, 87, -80, 70, -57, 43, -25,  9
.int  4, -13, 22, -31, 38, -46, 54, -61, 67, -73, 78, -82, 85, -88, 90, -90, 90, -90, 88, -85, 82, -78, 73, -67, 61, -54, 46, -38, 31, -22, 13, -4
endconst

const gt_entropyBits
.int 31523,34297,29856,36028,28388,37716,26612,39963,24752,42538,23196,44891,21645,47445,20310,49833
.int 19079,52215,17878,54723,16708,57371,15752,59703,14816,62157,13923,64670,13127,67072,12368,69525
.int 11597,72194,10963,74547,10350,76973,9732,79583,9253,81736,8692,84420,8254,86651,7757,89344
.int 7321,91870,6936,94231,6565,96648,6209,99111,5855,101712,5593,103751,5244,106627,5006,108707
.int 4689,111640,4454,113959,4200,116603,3967,119182,3802,121114,3609,123476,3407,126106,3216,128736
.int 3073,130808,2911,133297,2742,136034,2581,138822,2440,141405,2356,143016,2216,145842,2077,148855
.int 1993,150758,1891,153187,1808,155279,1696,158246,1650,159523,1512,163576,1466,165045,1374,168023
.int 1292,170923,1217,173684,1191,174686,1135,176943,1055,180397,999,182925,954,185123,268,245691
endconst

const gt_nextState
.byte 2, 1, 0, 3, 4, 0, 1, 5, 6, 2, 3, 7, 8, 4, 5, 9
.byte 10, 4, 5, 11, 12, 8, 9, 13, 14, 8, 9, 15, 16, 10, 11, 17
.byte 18, 12, 13, 19, 20, 14, 15, 21, 22, 16, 17, 23, 24, 18, 19, 25
.byte 26, 18, 19, 27, 28, 22, 23, 29, 30, 22, 23, 31, 32, 24, 25, 33
.byte 34, 26, 27, 35, 36, 26, 27, 37, 38, 30, 31, 39, 40, 30, 31, 41
.byte 42, 32, 33, 43, 44, 32, 33, 45, 46, 36, 37, 47, 48, 36, 37, 49
.byte 50, 38, 39, 51, 52, 38, 39, 53, 54, 42, 43, 55, 56, 42, 43, 57
.byte 58, 44, 45, 59, 60, 44, 45, 61, 62, 46, 47, 63, 64, 48, 49, 65
.byte 66, 48, 49, 67, 68, 50, 51, 69, 70, 52, 53, 71, 72, 52, 53, 73
.byte 74, 54, 55, 75, 76, 54, 55, 77, 78, 56, 57, 79, 80, 58, 59, 81
.byte 82, 58, 59, 83, 84, 60, 61, 85, 86, 60, 61, 87, 88, 60, 61, 89
.byte 90, 62, 63, 91, 92, 64, 65, 93, 94, 64, 65, 95, 96, 66, 67, 97
.byte 98, 66, 67, 99, 100, 66, 67, 101, 102, 68, 69, 103, 104, 68, 69, 105
.byte 106, 70, 71, 107, 108, 70, 71, 109, 110, 70, 71, 111, 112, 72, 73, 113
.byte 114, 72, 73, 115, 116, 72, 73, 117, 118, 74, 75, 119, 120, 74, 75, 121
.byte 122, 74, 75, 123, 124, 76, 77, 125, 124, 76, 77, 125, 126, 126, 127, 127
endconst

/*
 * Description : Transpose 4x4 block with word elements in vectors
 * Arguments   : Inputs  - in0, in1, in2, in3
 *               Outputs - out0, out1, out2, out3
 * Details     :
 * Example     :
 *               1, 2, 3, 4            1, 5, 9,13
 *               5, 6, 7, 8    to      2, 6,10,14
 *               9,10,11,12  =====>    3, 7,11,15
 *              13,14,15,16            4, 8,12,16
 */
.macro LSX_TRANSPOSE4x4_W_EXTRA in0, in1, in2, in3, out0, out1, out2, out3

    vilvl.w    \out0,   \in1,    \in0
    vilvl.w    \out2,   \in3,    \in2
    vilvh.d    \out1,   \out2,   \out0
    vilvl.d    \out0,   \out2,   \out0

    vilvh.w    \in1,    \in1,    \in0
    vilvh.w    \in3,    \in3,    \in2
    vilvl.d    \out2,   \in3,    \in1
    vilvh.d    \out3,   \in3,    \in1
.endm

/*
 * Description : Transpose 8x8 block with word elements in vectors
 * Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7
 *               Outputs - out0, out1, out2, out3, out4, out5, out6,
 *               _out7
 * Tip         : (in0, in1, in2, in3) these four input registers will be modified.
 * Example     :
 *         in0 : 1,2,3,4,5,6,7,8
 *         in1 : 2,2,3,4,5,6,7,8
 *         in2 : 3,2,3,4,5,6,7,8
 *         in3 : 4,2,3,4,5,6,7,8
 *         in4 : 5,2,3,4,5,6,7,8
 *         in5 : 6,2,3,4,5,6,7,8
 *         in6 : 7,2,3,4,5,6,7,8
 *         in7 : 8,2,3,4,5,6,7,8
 *
 *        out0 : 1,2,3,4,5,6,7,8
 *        out1 : 2,2,2,2,2,2,2,2
 *        out2 : 3,3,3,3,3,3,3,3
 *        out3 : 4,4,4,4,4,4,4,4
 *        out4 : 5,5,5,5,5,5,5,5
 *        out5 : 6,6,6,6,6,6,6,6
 *        out6 : 7,7,7,7,7,7,7,7
 *        out7 : 8,8,8,8,8,8,8,8
 */
.macro LASX_TRANSPOSE8x8_W_EXTRA in0, in1, in2, in3, in4, in5, in6, in7,\
                                 out0, out1, out2, out3, out4, out5, out6, out7
    xvilvl.w    \out4,   \in2,    \in0
    xvilvl.w    \out5,   \in3,    \in1
    xvilvh.w    \out6,   \in2,    \in0
    xvilvh.w    \out7,   \in3,    \in1
    xvilvl.w    \out0,   \out5,   \out4
    xvilvh.w    \out1,   \out5,   \out4
    xvilvl.w    \out2,   \out7,   \out6
    xvilvh.w    \out3,   \out7,   \out6

    xvilvl.w    \in0,    \in6,    \in4
    xvilvl.w    \in1,    \in7,    \in5
    xvilvh.w    \in2,    \in6,    \in4
    xvilvh.w    \in3,    \in7,    \in5
    xvilvl.w    \out4,   \in1,    \in0
    xvilvh.w    \out5,   \in1,    \in0
    xvilvl.w    \out6,   \in3,    \in2
    xvilvh.w    \out7,   \in3,    \in2

    xmov        \in0,    \out0
    xmov        \in1,    \out1
    xmov        \in2,    \out2
    xmov        \in3,    \out3
    xvpermi.q   \out0,   \out4,   0x02
    xvpermi.q   \out1,   \out5,   0x02
    xvpermi.q   \out2,   \out6,   0x02
    xvpermi.q   \out3,   \out7,   0x02
    xvpermi.q   \out4,   \in0,    0x31
    xvpermi.q   \out5,   \in1,    0x31
    xvpermi.q   \out6,   \in2,    0x31
    xvpermi.q   \out7,   \in3,    0x31
.endm

/*
 *  _out0 ... _out3: E[0...15]
 *  _out4 ... _out7: O[0...15]
 *  temp reg: vr20, vr21, vr22, vr23
 */
.macro LOAD_DCT32 _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7, _in
    vld          vr20,  \_in,    0    //src[0...7]
    vld          vr21,  \_in,    16   //src[8...15]
    vld          vr22,  \_in,    32   //src[16...23]
    vld          vr23,  \_in,    48   //src[24...31]

    vshuf.b      vr22, vr22, vr22, vr31
    vshuf.b      vr23, vr23, vr23, vr31

    vaddwev.w.h   \_out4,  vr20,    vr23
    vaddwod.w.h   \_out5,  vr20,    vr23
    vilvl.w       \_out0,  \_out5,  \_out4  //E[0...3]
    vilvh.w       \_out1,  \_out5,  \_out4  //E[4...7]
    vaddwev.w.h   \_out4,  vr21,    vr22
    vaddwod.w.h   \_out5,  vr21,    vr22
    vilvl.w       \_out2,  \_out5,  \_out4  //E[8...11]
    vilvh.w       \_out3,  \_out5,  \_out4  //E[12...15]

    vsubwev.w.h   \_out6,  vr20,    vr23
    vsubwod.w.h   \_out7,  vr20,    vr23
    vilvl.w       \_out4,  \_out7,  \_out6  //O[0...3]
    vilvh.w       \_out5,  \_out7,  \_out6  //O[4...7]
    vsubwev.w.h   vr20,    vr21,    vr22
    vsubwod.w.h   vr23,    vr21,    vr22
    vilvl.w       \_out6,  vr23,    vr20    //O[8...11]
    vilvh.w       \_out7,  vr23,    vr20    //O[12...15]
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(calculate 2 outputs)
 * temp reg: vr8~vr11
 */
.macro LSX_CAL_DCT_4_ELE_2 _rin, _in0, _in1, _in2, _in3, \
                           _out0, _out1, _si0, _si1, _si2, _si3
    vldrepl.w    vr8,     \_rin,    \_si0
    vldrepl.w    vr9,     \_rin,    \_si1
    vldrepl.w    vr10,    \_rin,    \_si2
    vldrepl.w    vr11,    \_rin,    \_si3
    vmul.w       \_out0,  \_in0,    vr8
    vmadd.w      \_out0,  \_in1,    vr9
    vmadd.w      \_out0,  \_in2,    vr10
    vmadd.w      \_out0,  \_in3,    vr11
    vmul.w       \_out1,  \_in0,    vr11
    vmsub.w      \_out1,  \_in1,    vr10
    vmadd.w      \_out1,  \_in2,    vr9
    vmsub.w      \_out1,  \_in3,    vr8
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: vr8~vr11
 */
.macro LSX_CAL_DCT_4_ELE_2X _rin, _in0, _in1, _in2, _in3, \
                            _out0, _out1, _si0, _si1, _si2, _si3
    vldrepl.w    vr8,     \_rin,    \_si0
    vldrepl.w    vr9,     \_rin,    \_si1
    vldrepl.w    vr10,    \_rin,    \_si2
    vldrepl.w    vr11,    \_rin,    \_si3
    vmul.w       \_out0,  \_in0,    vr8
    vmadd.w      \_out0,  \_in1,    vr9
    vmadd.w      \_out0,  \_in2,    vr10
    vmadd.w      \_out0,  \_in3,    vr11
    vmul.w       \_out1,  \_in3,    vr8
    vmsub.w      \_out1,  \_in2,    vr9
    vmadd.w      \_out1,  \_in1,    vr10
    vmsub.w      \_out1,  \_in0,    vr11
.endm

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * temp reg: \_tmp0~\_tmp7
 */
.macro LSX_CAL_DCT_8_ELE_2 _rin, _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                           _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7, \
                           _out0, _out1, _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7
    vldrepl.w    \_tmp0,  \_rin,    \_si0
    vldrepl.w    \_tmp1,  \_rin,    \_si1
    vldrepl.w    \_tmp2,  \_rin,    \_si2
    vldrepl.w    \_tmp3,  \_rin,    \_si3
    vldrepl.w    \_tmp4,  \_rin,    \_si4
    vldrepl.w    \_tmp5,  \_rin,    \_si5
    vldrepl.w    \_tmp6,  \_rin,    \_si6
    vldrepl.w    \_tmp7,  \_rin,    \_si7
    vmul.w       \_out0,  \_in0,    \_tmp0
    vmul.w       \_out1,  \_in0,    \_tmp7
    vmadd.w      \_out0,  \_in1,    \_tmp1
    vmsub.w      \_out1,  \_in1,    \_tmp6
    vmadd.w      \_out0,  \_in2,    \_tmp2
    vmadd.w      \_out1,  \_in2,    \_tmp5
    vmadd.w      \_out0,  \_in3,    \_tmp3
    vmsub.w      \_out1,  \_in3,    \_tmp4
    vmadd.w      \_out0,  \_in4,    \_tmp4
    vmadd.w      \_out1,  \_in4,    \_tmp3
    vmadd.w      \_out0,  \_in5,    \_tmp5
    vmsub.w      \_out1,  \_in5,    \_tmp2
    vmadd.w      \_out0,  \_in6,    \_tmp6
    vmadd.w      \_out1,  \_in6,    \_tmp1
    vmadd.w      \_out0,  \_in7,    \_tmp7
    vmsub.w      \_out1,  \_in7,    \_tmp0
.endm

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: _tmp0~_tmp7
 */
.macro LSX_CAL_DCT_8_ELE_2X _rin, _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                            _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7, \
                            _out0, _out1, _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7
    vldrepl.w    \_tmp0,  \_rin,    \_si0
    vldrepl.w    \_tmp1,  \_rin,    \_si1
    vldrepl.w    \_tmp2,  \_rin,    \_si2
    vldrepl.w    \_tmp3,  \_rin,    \_si3
    vldrepl.w    \_tmp4,  \_rin,    \_si4
    vldrepl.w    \_tmp5,  \_rin,    \_si5
    vldrepl.w    \_tmp6,  \_rin,    \_si6
    vldrepl.w    \_tmp7,  \_rin,    \_si7
    vmul.w       \_out0,  \_in0,    \_tmp0
    vmul.w       \_out1,  \_in7,    \_tmp0
    vmadd.w      \_out0,  \_in1,    \_tmp1
    vmsub.w      \_out1,  \_in6,    \_tmp1
    vmadd.w      \_out0,  \_in2,    \_tmp2
    vmadd.w      \_out1,  \_in5,    \_tmp2
    vmadd.w      \_out0,  \_in3,    \_tmp3
    vmsub.w      \_out1,  \_in4,    \_tmp3
    vmadd.w      \_out0,  \_in4,    \_tmp4
    vmadd.w      \_out1,  \_in3,    \_tmp4
    vmadd.w      \_out0,  \_in5,    \_tmp5
    vmsub.w      \_out1,  \_in2,    \_tmp5
    vmadd.w      \_out0,  \_in6,    \_tmp6
    vmadd.w      \_out1,  \_in1,    \_tmp6
    vmadd.w      \_out0,  \_in7,    \_tmp7
    vmsub.w      \_out1,  \_in0,    \_tmp7
.endm

/*
 * Description : Transpose 4x4x2 block with half-word elements in vectors
 * Arguments   : Inputs  - in0, in1, in2, in3
 *               Outputs - out0, out1, out2, out3
 * Example     :
 *               1, 2, 3, 4, 1, 2, 3, 4           1, 5, 9,13, 1, 5, 9,13
 *               5, 6, 7, 8, 5, 6, 7, 8   to      2, 6,10,14, 2, 6,10,14
 *               9,10,11,12, 9,10,11,12  =====>   3, 7,11,15, 3, 7,11,15
 *              13,14,15,16,13,14,15,16           4, 8,12,16, 4, 8,12,16
 */
.macro LSX_TRANSPOSE4x4x2_H in0, in1, in2, in3, out0, out1, out2, out3, \
                             tmp0, tmp1
    vpackev.h   \tmp0,  \in1,   \in0
    vpackev.h   \tmp1,  \in3,   \in2
    vpackev.w   \out0,  \tmp1,  \tmp0
    vpackod.w   \out2,  \tmp1,  \tmp0
    vpackod.h   \tmp0,  \in1,   \in0
    vpackod.h   \tmp1,  \in3,   \in2
    vpackev.w   \out1,  \tmp1,  \tmp0
    vpackod.w   \out3,  \tmp1,  \tmp0
.endm

.macro LSX_DCT16_4_LINE _shift, _rout
    LSX_TRANSPOSE4x4x2_H vr0, vr1, vr2, vr3, vr12, vr13, vr14, vr15, vr20, vr21
    LSX_TRANSPOSE4x4x2_H vr4, vr5, vr6, vr7, vr16, vr17, vr18, vr19, vr20, vr21

    /* src[0...8] */
    vsllwil.w.h   vr0,     vr12,    0
    vexth.w.h     vr4,     vr12
    vsllwil.w.h   vr1,     vr13,    0
    vexth.w.h     vr5,     vr13
    vsllwil.w.h   vr2,     vr14,    0
    vexth.w.h     vr6,     vr14
    vsllwil.w.h   vr3,     vr15,    0
    vexth.w.h     vr7,     vr15

    /* src[9...15] */
    vsllwil.w.h   vr8,     vr16,    0
    vexth.w.h     vr12,    vr16
    vsllwil.w.h   vr9,     vr17,    0
    vexth.w.h     vr13,    vr17
    vsllwil.w.h   vr10,    vr18,    0
    vexth.w.h     vr14,    vr18
    vsllwil.w.h   vr11,    vr19,    0
    vexth.w.h     vr15,    vr19

    /* O[0...7] */
    vsub.w        vr16,    vr0,     vr15
    vsub.w        vr17,    vr1,     vr14
    vsub.w        vr18,    vr2,     vr13
    vsub.w        vr19,    vr3,     vr12
    vsub.w        vr20,    vr4,     vr11
    vsub.w        vr21,    vr5,     vr10
    vsub.w        vr22,    vr6,     vr9
    vsub.w        vr23,    vr7,     vr8

    /* E[0...7] */
    vadd.w        vr15,    vr0,     vr15
    vadd.w        vr14,    vr1,     vr14
    vadd.w        vr13,    vr2,     vr13
    vadd.w        vr12,    vr3,     vr12
    vadd.w        vr11,    vr4,     vr11
    vadd.w        vr10,    vr5,     vr10
    vadd.w        vr9,     vr6,     vr9
    vadd.w        vr8,     vr7,     vr8

    /* EE[0...3] */
    vadd.w        vr0,     vr15,    vr8
    vadd.w        vr1,     vr14,    vr9
    vadd.w        vr2,     vr13,    vr10
    vadd.w        vr3,     vr12,    vr11

    /* EO[0...3] */
    vsub.w        vr4,     vr15,    vr8
    vsub.w        vr5,     vr14,    vr9
    vsub.w        vr6,     vr13,    vr10
    vsub.w        vr7,     vr12,    vr11
    vadd.w        vr8,     vr0,     vr3  // EEE[0]
    vadd.w        vr9,     vr1,     vr2  // EEE[1]
    vsub.w        vr10,    vr0,     vr3  // EEO[0]
    vsub.w        vr11,    vr1,     vr2  // EEO[1]

    /* CAL0-8-4-12*/
    vldrepl.w     vr12,    t1,      0
    vldrepl.w     vr13,    t1,      64 * 4
    vldrepl.w     vr14,    t1,      64 * 4 + 4
    vmul.w        vr0,     vr8,     vr12
    vmadd.w       vr0,     vr9,     vr12  //dst[0]
    vmul.w        vr1,     vr10,    vr13
    vmadd.w       vr1,     vr11,    vr14  //dst[4]
    vmul.w        vr2,     vr8,     vr12
    vmsub.w       vr2,     vr9,     vr12  //dst[8]
    vmul.w        vr3,     vr10,    vr14
    vmsub.w       vr3,     vr11,    vr13  //dst[12]

    /* CAL2-6-10-14*/
    LSX_CAL_DCT_4_ELE_2 t1, vr4, vr5, vr6, vr7, vr12, vr15, \
                        64 * 2, 64 * 2 + 4, 64 * 2 + 8, 64 * 2 + 12
    LSX_CAL_DCT_4_ELE_2X t1, vr4, vr5, vr6, vr7, vr13, vr14, \
                         64 * 6, 64 * 6 + 4, 64 * 6 + 8, 64 * 6 + 12

    vssrarni.h.w    vr12,   vr0,    \_shift
    vssrarni.h.w    vr13,   vr1,    \_shift
    vssrarni.h.w    vr14,   vr2,    \_shift
    vssrarni.h.w    vr15,   vr3,    \_shift

    vstelm.d        vr12,   \_rout, 0,            0
    vstelm.d        vr12,   \_rout, 32 * 2,       1
    vstelm.d        vr13,   \_rout, 32 * 4,       0
    vstelm.d        vr13,   \_rout, 32 * 6,       1
    vstelm.d        vr14,   \_rout, 32 * 8,       0
    vstelm.d        vr14,   \_rout, 32 * 10,      1
    vstelm.d        vr15,   \_rout, 32 * 12,      0
    vstelm.d        vr15,   \_rout, 32 * 14,      1

    /* CAL1-3-5-7...*/
    LSX_CAL_DCT_8_ELE_2 t1, vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                        vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                        vr0, vr7, 64 * 1, 64 * 1 + 4, 64 * 1 + 8, 64 * 1 + 12, \
                        64 * 1 + 16, 64 * 1 + 20, 64 * 1 + 24, 64 * 1 + 28
    LSX_CAL_DCT_8_ELE_2X t1, vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                         vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                         vr1, vr6, 64 * 3, 64 * 3 + 4, 64 * 3 + 8, 64 * 3 + 12, \
                         64 * 3 + 16, 64 * 3 + 20, 64 * 3 + 24, 64 * 3 + 28
    LSX_CAL_DCT_8_ELE_2 t1, vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                        vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                        vr2, vr5, 64 * 5, 64 * 5 + 4, 64 * 5 + 8, 64 * 5 + 12, \
                        64 * 5 + 16, 64 * 5 + 20, 64 * 5 + 24, 64 * 5 + 28
    LSX_CAL_DCT_8_ELE_2X t1, vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                         vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                         vr3, vr4, 64 * 7, 64 * 7 + 4, 64 * 7 + 8, 64 * 7 + 12, \
                         64 * 7 + 16, 64 * 7 + 20, 64 * 7 + 24, 64 * 7 + 28

    vssrarni.h.w    vr1,    vr0,    \_shift
    vssrarni.h.w    vr3,    vr2,    \_shift
    vssrarni.h.w    vr5,    vr4,    \_shift
    vssrarni.h.w    vr7,    vr6,    \_shift

    vstelm.d        vr1,    \_rout, 32 * 1,       0
    vstelm.d        vr1,    \_rout, 32 * 3,       1
    vstelm.d        vr3,    \_rout, 32 * 5,       0
    vstelm.d        vr3,    \_rout, 32 * 7,       1
    vstelm.d        vr5,    \_rout, 32 * 9,       0
    vstelm.d        vr5,    \_rout, 32 * 11,      1
    vstelm.d        vr7,    \_rout, 32 * 13,      0
    vstelm.d        vr7,    \_rout, 32 * 15,      1
.endm

/* void x265_dct16_lsx(const int16_t* src, int16_t* dst, intptr_t srcStride) */
function x265_dct16_lsx
    addi.d        sp,      sp,      -512 //-(16*16*2) si12 Immediate overflow
    la.local      t1,      table_dct16
    slli.d        a3,      a2,      1  //stride
    slli.d        a4,      a2,      2  //stride2
    slli.d        a6,      a2,      3  //stride4
    add.d         a5,      a4,      a3 //stride3

    /*
     * The first butterfly operation.
     */
    vld           vr0,     a0,      0    //line0_l
    vldx          vr1,     a0,      a3   //line1_l
    vldx          vr2,     a0,      a4   //line2_l
    vldx          vr3,     a0,      a5   //line3_l
    addi.d        t3,      a0,      16
    vld           vr4,     t3,      0    //line0_h
    vldx          vr5,     t3,      a3   //line1_h
    vldx          vr6,     t3,      a4   //line2_h
    vldx          vr7,     t3,      a5   //line3_h
    LSX_DCT16_4_LINE 3, sp
    addi.d        t2,      sp,      8

    add.d         a0,      a0,      a6
    vld           vr0,     a0,      0    //line4_l
    vldx          vr1,     a0,      a3   //line5_l
    vldx          vr2,     a0,      a4   //line6_l
    vldx          vr3,     a0,      a5   //line7_l
    addi.d        t3,      a0,      16
    vld           vr4,     t3,      0    //line4_h
    vldx          vr5,     t3,      a3   //line5_h
    vldx          vr6,     t3,      a4   //line6_h
    vldx          vr7,     t3,      a5   //line7_h
    LSX_DCT16_4_LINE 3, t2
    addi.d        t2,      t2,      8

    add.d         a0,      a0,      a6
    vld           vr0,     a0,      0    //line8_l
    vldx          vr1,     a0,      a3   //line9_l
    vldx          vr2,     a0,      a4   //line10_l
    vldx          vr3,     a0,      a5   //line11_l
    addi.d        t3,      a0,      16
    vld           vr4,     t3,      0    //line8_h
    vldx          vr5,     t3,      a3   //line9_h
    vldx          vr6,     t3,      a4   //line10_h
    vldx          vr7,     t3,      a5   //line11_h
    LSX_DCT16_4_LINE 3, t2
    addi.d        t2,      t2,      8

    add.d         a0,      a0,      a6
    vld           vr0,     a0,      0    //line12_l
    vldx          vr1,     a0,      a3   //line13_l
    vldx          vr2,     a0,      a4   //line14_l
    vldx          vr3,     a0,      a5   //line15_l
    addi.d        t3,      a0,      16
    vld           vr4,     t3,      0    //line12_h
    vldx          vr5,     t3,      a3   //line13_h
    vldx          vr6,     t3,      a4   //line14_h
    vldx          vr7,     t3,      a5   //line15_h
    LSX_DCT16_4_LINE 3, t2

    /*
     * The second butterfly operation.
     */
    vld           vr0,     sp,      0    //line0_l
    vld           vr1,     sp,      32   //line1_l
    vld           vr2,     sp,      64   //line2_l
    vld           vr3,     sp,      96   //line3_l
    vld           vr4,     sp,      16   //line0_h
    vld           vr5,     sp,      48   //line1_h
    vld           vr6,     sp,      80   //line2_h
    vld           vr7,     sp,      112  //line3_h
    LSX_DCT16_4_LINE 10, a1
    addi.d        t2,      a1,      8

    vld           vr0,     sp,      128  //line4_l
    vld           vr1,     sp,      160  //line5_l
    vld           vr2,     sp,      192  //line6_l
    vld           vr3,     sp,      224  //line7_l
    vld           vr4,     sp,      144  //line4_h
    vld           vr5,     sp,      176  //line5_h
    vld           vr6,     sp,      208  //line6_h
    vld           vr7,     sp,      240  //line7_h
    LSX_DCT16_4_LINE 10, t2
    addi.d        t2,      t2,      8

    vld           vr0,     sp,      256  //line8_l
    vld           vr1,     sp,      288  //line9_l
    vld           vr2,     sp,      320  //line10_l
    vld           vr3,     sp,      352  //line11_l
    vld           vr4,     sp,      272  //line8_h
    vld           vr5,     sp,      304  //line9_h
    vld           vr6,     sp,      336  //line10_h
    vld           vr7,     sp,      368  //line11_h
    LSX_DCT16_4_LINE 10, t2
    addi.d        t2,      t2,      8

    vld           vr0,     sp,      384  //line12_l
    vld           vr1,     sp,      416  //line13_l
    vld           vr2,     sp,      448  //line14_l
    vld           vr3,     sp,      480  //line15_l
    vld           vr4,     sp,      400  //line12_h
    vld           vr5,     sp,      432  //line13_h
    vld           vr6,     sp,      464  //line14_h
    vld           vr7,     sp,      496  //line15_h
    LSX_DCT16_4_LINE 10, t2

    addi.d        sp,      sp,   512
endfunc

/*
 * Description : Multiplication and addition calculation of 16 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * IN reg      :
 * vr20, vr21, vr22, vr23
 * vr4,  vr8,  vr12, vr16
 * vr5,  vr9,  vr13, vr17
 * vr6,  vr10, vr14, vr18
 *
 * Temp reg    : vr7,vr11, vr15, vr19
 */
.macro LSX_CAL_DCT_16_ELE_2 _rin, _out0, _out1, \
                            _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7, \
                            _si8, _si9, _si10, _si11, _si12, _si13, _si14, _si15
    vldrepl.w     vr7,     \_rin,    \_si0
    vldrepl.w     vr11,    \_rin,    \_si1
    vldrepl.w     vr15,    \_rin,    \_si2
    vldrepl.w     vr19,    \_rin,    \_si3
    vmul.w        \_out0,  vr20,     vr7
    vmul.w        \_out1,  vr6,      vr19
    vmadd.w       \_out0,  vr21,     vr11
    vmsub.w       \_out1,  vr10,     vr15
    vmadd.w       \_out0,  vr22,     vr15
    vmadd.w       \_out1,  vr14,     vr11
    vmadd.w       \_out0,  vr23,     vr19
    vmsub.w       \_out1,  vr18,     vr7

    vldrepl.w     vr7,     \_rin,    \_si4
    vldrepl.w     vr11,    \_rin,    \_si5
    vldrepl.w     vr15,    \_rin,    \_si6
    vldrepl.w     vr19,    \_rin,    \_si7
    vmadd.w       \_out0,  vr4,      vr7
    vmadd.w       \_out1,  vr5,      vr19
    vmadd.w       \_out0,  vr8,      vr11
    vmsub.w       \_out1,  vr9,      vr15
    vmadd.w       \_out0,  vr12,     vr15
    vmadd.w       \_out1,  vr13,     vr11
    vmadd.w       \_out0,  vr16,     vr19
    vmsub.w       \_out1,  vr17,     vr7

    vldrepl.w     vr7,     \_rin,    \_si8
    vldrepl.w     vr11,    \_rin,    \_si9
    vldrepl.w     vr15,    \_rin,    \_si10
    vldrepl.w     vr19,    \_rin,    \_si11
    vmadd.w       \_out0,  vr5,      vr7
    vmadd.w       \_out1,  vr4,      vr19
    vmadd.w       \_out0,  vr9,      vr11
    vmsub.w       \_out1,  vr8,      vr15
    vmadd.w       \_out0,  vr13,     vr15
    vmadd.w       \_out1,  vr12,     vr11
    vmadd.w       \_out0,  vr17,     vr19
    vmsub.w       \_out1,  vr16,     vr7

    vldrepl.w     vr7,     \_rin,    \_si12
    vldrepl.w     vr11,    \_rin,    \_si13
    vldrepl.w     vr15,    \_rin,    \_si14
    vldrepl.w     vr19,    \_rin,    \_si15
    vmadd.w       \_out0,  vr6,      vr7
    vmadd.w       \_out1,  vr20,     vr19
    vmadd.w       \_out0,  vr10,     vr11
    vmsub.w       \_out1,  vr21,     vr15
    vmadd.w       \_out0,  vr14,     vr15
    vmadd.w       \_out1,  vr22,     vr11
    vmadd.w       \_out0,  vr18,     vr19
    vmsub.w       \_out1,  vr23,     vr7
.endm

/*
 * Description : Multiplication and addition calculation of 16 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * IN reg      :
 * vr20, vr21, vr22, vr23
 * vr4,  vr8,  vr12, vr16
 * vr5,  vr9,  vr13, vr17
 * vr6,  vr10, vr14, vr18
 *
 * Temp reg    : vr7,vr11, vr15, vr19
 */
.macro LSX_CAL_DCT_16_ELE_2X _rin, _out0, _out1, \
                             _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7, \
                             _si8, _si9, _si10, _si11, _si12, _si13, _si14, _si15
    vldrepl.w     vr7,     \_rin,    \_si0
    vldrepl.w     vr11,    \_rin,    \_si1
    vldrepl.w     vr15,    \_rin,    \_si2
    vldrepl.w     vr19,    \_rin,    \_si3
    vmul.w        \_out0,  vr20,     vr7
    vmul.w        \_out1,  vr18,     vr7
    vmadd.w       \_out0,  vr21,     vr11
    vmsub.w       \_out1,  vr14,     vr11
    vmadd.w       \_out0,  vr22,     vr15
    vmadd.w       \_out1,  vr10,     vr15
    vmadd.w       \_out0,  vr23,     vr19
    vmsub.w       \_out1,  vr6,      vr19

    vldrepl.w     vr7,     \_rin,    \_si4
    vldrepl.w     vr11,    \_rin,    \_si5
    vldrepl.w     vr15,    \_rin,    \_si6
    vldrepl.w     vr19,    \_rin,    \_si7
    vmadd.w       \_out0,  vr4,      vr7
    vmadd.w       \_out1,  vr17,     vr7
    vmadd.w       \_out0,  vr8,      vr11
    vmsub.w       \_out1,  vr13,     vr11
    vmadd.w       \_out0,  vr12,     vr15
    vmadd.w       \_out1,  vr9,      vr15
    vmadd.w       \_out0,  vr16,     vr19
    vmsub.w       \_out1,  vr5,      vr19

    vldrepl.w     vr7,     \_rin,    \_si8
    vldrepl.w     vr11,    \_rin,    \_si9
    vldrepl.w     vr15,    \_rin,    \_si10
    vldrepl.w     vr19,    \_rin,    \_si11
    vmadd.w       \_out0,  vr5,      vr7
    vmadd.w       \_out1,  vr16,     vr7
    vmadd.w       \_out0,  vr9,      vr11
    vmsub.w       \_out1,  vr12,     vr11
    vmadd.w       \_out0,  vr13,     vr15
    vmadd.w       \_out1,  vr8,      vr15
    vmadd.w       \_out0,  vr17,     vr19
    vmsub.w       \_out1,  vr4,      vr19

    vldrepl.w     vr7,     \_rin,    \_si12
    vldrepl.w     vr11,    \_rin,    \_si13
    vldrepl.w     vr15,    \_rin,    \_si14
    vldrepl.w     vr19,    \_rin,    \_si15
    vmadd.w       \_out0,  vr6,      vr7
    vmadd.w       \_out1,  vr23,     vr7
    vmadd.w       \_out0,  vr10,     vr11
    vmsub.w       \_out1,  vr22,     vr11
    vmadd.w       \_out0,  vr14,     vr15
    vmadd.w       \_out1,  vr21,     vr15
    vmadd.w       \_out0,  vr18,     vr19
    vmsub.w       \_out1,  vr20,     vr19
.endm

.macro CLA_DCT32_O_ALL _shift
    LSX_TRANSPOSE4x4_W_EXTRA vr0, vr4, vr24, vr28, vr20, vr21, vr22, vr23
    LSX_TRANSPOSE4x4_W_EXTRA vr1, vr5, vr25, vr29, vr4,  vr8,  vr12, vr16
    LSX_TRANSPOSE4x4_W_EXTRA vr2, vr6, vr26, vr30, vr5,  vr9,  vr13, vr17
    LSX_TRANSPOSE4x4_W_EXTRA vr3, vr7, vr27, vr31, vr6,  vr10, vr14, vr18

    addi.d        t3,      t2,      64 * 14
    addi.d        t5,      t3,      64 * 14

    LSX_CAL_DCT_16_ELE_2 t1, vr25, vr3, 128 * 1, 128 * 1 + 4, 128 * 1 + 8, 128 * 1 + 12, \
                         128 * 1 + 16, 128 * 1 + 20, 128 * 1 + 24, 128 * 1 + 28, \
                         128 * 1 + 32, 128 * 1 + 36, 128 * 1 + 40, 128 * 1 + 44, \
                         128 * 1 + 48, 128 * 1 + 52, 128 * 1 + 56, 128 * 1 + 60
    LSX_CAL_DCT_16_ELE_2X t1, vr26, vr2, \
                          128 * 3, 128 * 3 + 4, 128 * 3 + 8, 128 * 3 + 12, \
                          128 * 3 + 16, 128 * 3 + 20, 128 * 3 + 24, 128 * 3 + 28, \
                          128 * 3 + 32, 128 * 3 + 36, 128 * 3 + 40, 128 * 3 + 44, \
                          128 * 3 + 48, 128 * 3 + 52, 128 * 3 + 56, 128 * 3 + 60
    vssrarni.h.w  vr26,    vr25,    \_shift
    vssrarni.h.w  vr3,     vr2,     \_shift

    LSX_CAL_DCT_16_ELE_2 t1, vr25, vr1, 128 * 5, 128 * 5 + 4, 128 * 5 + 8, 128 * 5 + 12, \
                         128 * 5 + 16, 128 * 5 + 20, 128 * 5 + 24, 128 * 5 + 28, \
                         128 * 5 + 32, 128 * 5 + 36, 128 * 5 + 40, 128 * 5 + 44, \
                         128 * 5 + 48, 128 * 5 + 52, 128 * 5 + 56, 128 * 5 + 60
    LSX_CAL_DCT_16_ELE_2X t1, vr27, vr2, \
                          128 * 7, 128 * 7 + 4, 128 * 7 + 8, 128 * 7 + 12, \
                          128 * 7 + 16, 128 * 7 + 20, 128 * 7 + 24, 128 * 7 + 28, \
                          128 * 7 + 32, 128 * 7 + 36, 128 * 7 + 40, 128 * 7 + 44, \
                          128 * 7 + 48, 128 * 7 + 52, 128 * 7 + 56, 128 * 7 + 60
    vssrarni.h.w  vr27,    vr25,    \_shift
    vssrarni.h.w  vr1,     vr2,     \_shift

    LSX_CAL_DCT_16_ELE_2 t1, vr25, vr0, 128 * 9, 128 * 9 + 4, 128 * 9 + 8, 128 * 9 + 12, \
                         128 * 9 + 16, 128 * 9 + 20, 128 * 9 + 24, 128 * 9 + 28, \
                         128 * 9 + 32, 128 * 9 + 36, 128 * 9 + 40, 128 * 9 + 44, \
                         128 * 9 + 48, 128 * 9 + 52, 128 * 9 + 56, 128 * 9 + 60
    LSX_CAL_DCT_16_ELE_2X t1, vr28, vr2, \
                          128 * 11, 128 * 11 + 4, 128 * 11 + 8, 128 * 11 + 12, \
                          128 * 11 + 16, 128 * 11 + 20, 128 * 11 + 24, 128 * 11 + 28, \
                          128 * 11 + 32, 128 * 11 + 36, 128 * 11 + 40, 128 * 11 + 44, \
                          128 * 11 + 48, 128 * 11 + 52, 128 * 11 + 56, 128 * 11 + 60
    vssrarni.h.w  vr28,    vr25,    \_shift
    vssrarni.h.w  vr0,     vr2,     \_shift

    LSX_CAL_DCT_16_ELE_2 t1, vr25, vr31, \
                         128 * 13, 128 * 13 + 4, 128 * 13 + 8, 128 * 13 + 12, \
                         128 * 13 + 16, 128 * 13 + 20, 128 * 13 + 24, 128 * 13 + 28, \
                         128 * 13 + 32, 128 * 13 + 36, 128 * 13 + 40, 128 * 13 + 44, \
                         128 * 13 + 48, 128 * 13 + 52, 128 * 13 + 56, 128 * 13 + 60
    LSX_CAL_DCT_16_ELE_2X t1, vr29, vr2, \
                          128 * 15, 128 * 15 + 4, 128 * 15 + 8, 128 * 15 + 12, \
                          128 * 15 + 16, 128 * 15 + 20, 128 * 15 + 24, 128 * 15 + 28, \
                          128 * 15 + 32, 128 * 15 + 36, 128 * 15 + 40, 128 * 15 + 44, \
                          128 * 15 + 48, 128 * 15 + 52, 128 * 15 + 56, 128 * 15 + 60
    vssrarni.h.w  vr29,    vr25,    \_shift
    vssrarni.h.w  vr31,    vr2,     \_shift

    vstelm.d      vr26,    t2,      64 * 1,  0  // k = 1
    vstelm.d      vr26,    t2,      64 * 3,  1  // k = 3
    vstelm.d      vr27,    t2,      64 * 5,  0  // k = 5
    vstelm.d      vr27,    t2,      64 * 7,  1  // k = 7
    vstelm.d      vr28,    t2,      64 * 9,  0  // k = 9
    vstelm.d      vr28,    t2,      64 * 11, 1  // k = 11
    vstelm.d      vr29,    t2,      64 * 13, 0  // k = 13
    vstelm.d      vr29,    t3,      64 * 1,  1  // k = 15
    vstelm.d      vr31,    t3,      64 * 3,  0  // k = 17
    vstelm.d      vr31,    t3,      64 * 5,  1  // k = 19
    vstelm.d      vr0,     t3,      64 * 7,  0  // k = 21
    vstelm.d      vr0,     t3,      64 * 9,  1  // k = 23
    vstelm.d      vr1,     t3,      64 * 11, 0  // k = 25
    vstelm.d      vr1,     t3,      64 * 13, 1  // k = 27
    vstelm.d      vr3,     t5,      64 * 1,  0  // k = 29
    vstelm.d      vr3,     t5,      64 * 3,  1  // k = 31
.endm

.macro CLA_DCT32_E_ALL _shift
    LSX_TRANSPOSE4x4_W_EXTRA vr4,  vr5,  vr6,  vr7,  vr0,  vr1,  vr2,  vr3
    LSX_TRANSPOSE4x4_W_EXTRA vr8,  vr9,  vr10, vr11, vr4,  vr5,  vr6,  vr7
    LSX_TRANSPOSE4x4_W_EXTRA vr12, vr13, vr14, vr15, vr8,  vr9,  vr10, vr11
    LSX_TRANSPOSE4x4_W_EXTRA vr16, vr17, vr18, vr19, vr12, vr13, vr14, vr15

    /* EO[0...7] */
    vsub.w        vr16,    vr0,     vr15
    vsub.w        vr17,    vr1,     vr14
    vsub.w        vr18,    vr2,     vr13
    vsub.w        vr19,    vr3,     vr12
    vsub.w        vr20,    vr4,     vr11
    vsub.w        vr21,    vr5,     vr10
    vsub.w        vr22,    vr6,     vr9
    vsub.w        vr23,    vr7,     vr8

    /* EE[0...7] */
    vadd.w        vr15,    vr0,     vr15
    vadd.w        vr14,    vr1,     vr14
    vadd.w        vr13,    vr2,     vr13
    vadd.w        vr12,    vr3,     vr12
    vadd.w        vr11,    vr4,     vr11
    vadd.w        vr10,    vr5,     vr10
    vadd.w        vr9,     vr6,     vr9
    vadd.w        vr8,     vr7,     vr8

    /* EEE[0...3] */
    vadd.w        vr0,     vr15,    vr8
    vadd.w        vr1,     vr14,    vr9
    vadd.w        vr2,     vr13,    vr10
    vadd.w        vr3,     vr12,    vr11

    /* EEO[0...3] */
    vsub.w        vr4,     vr15,    vr8
    vsub.w        vr5,     vr14,    vr9
    vsub.w        vr6,     vr13,    vr10
    vsub.w        vr7,     vr12,    vr11
    vadd.w        vr8,     vr0,     vr3  // EEEE[0]
    vadd.w        vr9,     vr1,     vr2  // EEEE[1]
    vsub.w        vr10,    vr0,     vr3  // EEEO[0]
    vsub.w        vr11,    vr1,     vr2  // EEEO[1]

    addi.d        t3,      t2,      64 * 16
    addi.d        t5,      t1,      128 * 15

    /* CAL0-16-8-24*/
    vldrepl.w     vr12,    t1,      0
    vldrepl.w     vr13,    t1,      128 * 8
    vldrepl.w     vr14,    t1,      128 * 8 + 4
    vmul.w        vr0,     vr8,     vr12
    vmadd.w       vr0,     vr9,     vr12  //dst[0]
    vmul.w        vr1,     vr10,    vr13
    vmadd.w       vr1,     vr11,    vr14  //dst[8]
    vmul.w        vr2,     vr8,     vr12
    vmsub.w       vr2,     vr9,     vr12  //dst[16]
    vmul.w        vr3,     vr10,    vr14
    vmsub.w       vr3,     vr11,    vr13  //dst[24]

    /* CAL4-12-20-28*/
    LSX_CAL_DCT_4_ELE_2 t1, vr4, vr5, vr6, vr7, vr12, vr15, \
                        128 * 4, 128 * 4 + 4, 128 * 4 + 8, 128 * 4 + 12
    LSX_CAL_DCT_4_ELE_2X t1, vr4, vr5, vr6, vr7, vr13, vr14, \
                         128 * 12, 128 * 12 + 4, 128 * 12 + 8, 128 * 12 + 12

    vssrarni.h.w    vr12,   vr0,    \_shift
    vssrarni.h.w    vr13,   vr1,    \_shift
    vssrarni.h.w    vr14,   vr2,    \_shift
    vssrarni.h.w    vr15,   vr3,    \_shift

    vstelm.d        vr12,   t2,     0,            0
    vstelm.d        vr12,   t2,     64 * 4,       1
    vstelm.d        vr13,   t2,     64 * 8,       0
    vstelm.d        vr13,   t2,     64 * 12,      1
    vstelm.d        vr14,   t3,     0,            0
    vstelm.d        vr14,   t3,     64 * 4,       1
    vstelm.d        vr15,   t3,     64 * 8,       0
    vstelm.d        vr15,   t3,     64 * 12,      1

    /* CAL2-6-10-14...*/
    LSX_CAL_DCT_8_ELE_2 t1, vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                        vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                        vr0, vr7, 128 * 2, 128 * 2 + 4, 128 * 2 + 8, 128 * 2 + 12, \
                        128 * 2 + 16, 128 * 2 + 20, 128 * 2 + 24, 128 * 2 + 28
    LSX_CAL_DCT_8_ELE_2X t1, vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                         vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                         vr1, vr6, 128 * 6, 128 * 6 + 4, 128 * 6 + 8, 128 * 6 + 12, \
                         128 * 6 + 16, 128 * 6 + 20, 128 * 6 + 24, 128 * 6 + 28
    LSX_CAL_DCT_8_ELE_2 t1, vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                        vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                        vr2, vr5, 128 * 10, 128 * 10 + 4, 128 * 10 + 8, 128 * 10 + 12, \
                        128 * 10 + 16, 128 * 10 + 20, 128 * 10 + 24, 128 * 10 + 28
    LSX_CAL_DCT_8_ELE_2X t1, vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                         vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                         vr3, vr4,128 * 14, 128 * 14 + 4, 128 * 14 + 8, 128 * 14 + 12, \
                         128 * 14 + 16, 128 * 14 + 20, 128 * 14 + 24, 128 * 14 + 28

    vssrarni.h.w    vr1,    vr0,    \_shift
    vssrarni.h.w    vr3,    vr2,    \_shift
    vssrarni.h.w    vr5,    vr4,    \_shift
    vssrarni.h.w    vr7,    vr6,    \_shift

    vstelm.d        vr1,    t2,     64 * 2,       0
    vstelm.d        vr1,    t2,     64 * 6,       1
    vstelm.d        vr3,    t2,     64 * 10,      0
    vstelm.d        vr3,    t2,     64 * 14,      1
    vstelm.d        vr5,    t3,     64 * 2,       0
    vstelm.d        vr5,    t3,     64 * 6,       1
    vstelm.d        vr7,    t3,     64 * 10,      0
    vstelm.d        vr7,    t3,     64 * 14,      1
.endm

.macro DCT32_4_LINE_1
    vld           vr31,    t0,      0

    LOAD_DCT32    vr4, vr8, vr12, vr16, vr0, vr1, vr2, vr3, a0
    add.d         a0,      a0,      a2
    vst           vr0,     t4,      0
    vst           vr1,     t4,      16
    vst           vr2,     t4,      16 * 2
    vst           vr3,     t4,      16 * 3
    LOAD_DCT32    vr5, vr9, vr13, vr17, vr0, vr1, vr2, vr3, a0
    add.d         a0,      a0,      a2
    vst           vr0,     t4,      16 * 4
    vst           vr1,     t4,      16 * 5
    vst           vr2,     t4,      16 * 6
    vst           vr3,     t4,      16 * 7
    LOAD_DCT32    vr6, vr10, vr14, vr18, vr24, vr25, vr26, vr27, a0
    add.d         a0,      a0,      a2
    LOAD_DCT32    vr7, vr11, vr15, vr19, vr28, vr29, vr30, vr31, a0
    add.d         a0,      a0,      a2

    CLA_DCT32_E_ALL 4

    vld           vr0,     t4,      0
    vld           vr1,     t4,      16
    vld           vr2,     t4,      16 * 2
    vld           vr3,     t4,      16 * 3
    vld           vr4,     t4,      16 * 4
    vld           vr5,     t4,      16 * 5
    vld           vr6,     t4,      16 * 6
    vld           vr7,     t4,      16 * 7
    CLA_DCT32_O_ALL 4

    addi.d        t2,      t2,      8
.endm

.macro DCT32_4_LINE_2
    vld           vr31,    t0,      0

    LOAD_DCT32    vr4, vr8, vr12, vr16, vr0, vr1, vr2, vr3, a3
    addi.d        a3,      a3,      64
    vst           vr0,     t4,      0
    vst           vr1,     t4,      16
    vst           vr2,     t4,      16 * 2
    vst           vr3,     t4,      16 * 3
    LOAD_DCT32    vr5, vr9, vr13, vr17, vr0, vr1, vr2, vr3, a3
    addi.d        a3,      a3,      64
    vst           vr0,     t4,      16 * 4
    vst           vr1,     t4,      16 * 5
    vst           vr2,     t4,      16 * 6
    vst           vr3,     t4,      16 * 7
    LOAD_DCT32    vr6, vr10, vr14, vr18, vr24, vr25, vr26, vr27, a3
    addi.d        a3,      a3,      64
    LOAD_DCT32    vr7, vr11, vr15, vr19, vr28, vr29, vr30, vr31, a3
    addi.d        a3,      a3,      64

    CLA_DCT32_E_ALL 11

    vld           vr0,     t4,      0
    vld           vr1,     t4,      16
    vld           vr2,     t4,      16 * 2
    vld           vr3,     t4,      16 * 3
    vld           vr4,     t4,      16 * 4
    vld           vr5,     t4,      16 * 5
    vld           vr6,     t4,      16 * 6
    vld           vr7,     t4,      16 * 7
    CLA_DCT32_O_ALL 11

    addi.d        t2,      t2,      8
.endm

/* void x265_dct32_lsx(const int16_t* src, int16_t* dst, intptr_t srcStride) */
function x265_dct32_lsx
    addi.d        sp,      sp,      -1120 //-(64 + 8*16 + 32*32*2) si12 Immediate overflow
    addi.d        sp,      sp,      -1120
    fst.d         f24,     sp,      0
    fst.d         f25,     sp,      8
    fst.d         f26,     sp,      16
    fst.d         f27,     sp,      24
    fst.d         f28,     sp,      32
    fst.d         f29,     sp,      40
    fst.d         f30,     sp,      48
    fst.d         f31,     sp,      56
    la.local      t0,      shuf_1
    la.local      t1,      table_dct32
    slli.d        a2,      a2,      1  //stride

    /*
     * The first butterfly operation.
     */
    addi.d        t2,      sp,      64 + 8 * 16
    addi.d        t4,      sp,      64

    /* line 0 ~ 3  */
    DCT32_4_LINE_1
    /* line 4 ~ 7  */
    DCT32_4_LINE_1
    /* line 8 ~ 11  */
    DCT32_4_LINE_1
    /* line 12 ~ 15  */
    DCT32_4_LINE_1
    /* line 16 ~ 19  */
    DCT32_4_LINE_1
    /* line 20 ~ 23  */
    DCT32_4_LINE_1
    /* line 24 ~ 27  */
    DCT32_4_LINE_1
    /* line 28 ~ 31  */
    DCT32_4_LINE_1

    /*
     * The second butterfly operation.
     */
    addi.d        t2,      a1,      0
    addi.d        a3,      sp,      64 + 8 * 16

    /* line 0 ~ 3  */
    DCT32_4_LINE_2
    /* line 4 ~ 7  */
    DCT32_4_LINE_2
    /* line 8 ~ 11  */
    DCT32_4_LINE_2
    /* line 12 ~ 15  */
    DCT32_4_LINE_2
    /* line 16 ~ 19  */
    DCT32_4_LINE_2
    /* line 20 ~ 23  */
    DCT32_4_LINE_2
    /* line 24 ~ 27  */
    DCT32_4_LINE_2
    /* line 28 ~ 31  */
    DCT32_4_LINE_2

    fld.d         f24,   sp,   0
    fld.d         f25,   sp,   8
    fld.d         f26,   sp,   16
    fld.d         f27,   sp,   24
    fld.d         f28,   sp,   32
    fld.d         f29,   sp,   40
    fld.d         f30,   sp,   48
    fld.d         f31,   sp,   56
    addi.d        sp,    sp,   1120
    addi.d        sp,    sp,   1120
endfunc

.macro DCT8_BUFFER_FLY _shift
    LSX_TRANSPOSE8x8_H vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                       vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                       vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23

    /* O[0...3] */
    vsubwev.w.h   vr24,   vr8,     vr15
    vsubwod.w.h   vr25,   vr8,     vr15
    vilvl.w       vr16,   vr25,    vr24  //[0...3]
    vilvh.w       vr17,   vr25,    vr24  //[4...7]
    vsubwev.w.h   vr24,   vr9,     vr14
    vsubwod.w.h   vr25,   vr9,     vr14
    vilvl.w       vr18,   vr25,    vr24  //[0...3]
    vilvh.w       vr19,   vr25,    vr24  //[4...7]
    vsubwev.w.h   vr24,   vr10,    vr13
    vsubwod.w.h   vr25,   vr10,    vr13
    vilvl.w       vr20,   vr25,    vr24  //[0...3]
    vilvh.w       vr21,   vr25,    vr24  //[4...7]
    vsubwev.w.h   vr24,   vr11,    vr12
    vsubwod.w.h   vr25,   vr11,    vr12
    vilvl.w       vr22,   vr25,    vr24  //[0...3]
    vilvh.w       vr23,   vr25,    vr24  //[4...7]

    vldrepl.w     vr24,   t1,      128 * 1
    vldrepl.w     vr25,   t1,      128 * 1 + 4
    vldrepl.w     vr26,   t1,      128 * 1 + 8
    vldrepl.w     vr27,   t1,      128 * 1 + 12
    vldrepl.w     vr29,   t1,      128 * 3 + 4
    vldrepl.w     vr30,   t1,      128 * 3 + 8
    vldrepl.w     vr31,   t1,      128 * 3 + 12
    vmul.w        vr28,   vr16,    vr24
    vmul.w        vr1,    vr17,    vr24
    vmadd.w       vr28,   vr18,    vr25
    vmadd.w       vr1,    vr19,    vr25
    vmadd.w       vr28,   vr20,    vr26
    vmadd.w       vr1,    vr21,    vr26
    vmadd.w       vr28,   vr22,    vr27
    vmadd.w       vr1,    vr23,    vr27
    vssrarni.h.w  vr1,    vr28,    \_shift

    vmul.w        vr28,   vr16,    vr25
    vmul.w        vr3,    vr17,    vr25
    vmadd.w       vr28,   vr18,    vr29
    vmadd.w       vr3,    vr19,    vr29
    vmadd.w       vr28,   vr20,    vr30
    vmadd.w       vr3,    vr21,    vr30
    vmadd.w       vr28,   vr22,    vr31
    vmadd.w       vr3,    vr23,    vr31
    vssrarni.h.w  vr3,    vr28,    \_shift

    vmul.w        vr28,   vr16,    vr26
    vmul.w        vr5,    vr17,    vr26
    vmadd.w       vr28,   vr18,    vr30
    vmadd.w       vr5,    vr19,    vr30
    vmadd.w       vr28,   vr20,    vr27
    vmadd.w       vr5,    vr21,    vr27
    vmadd.w       vr28,   vr22,    vr25
    vmadd.w       vr5,    vr23,    vr25
    vssrarni.h.w  vr5,    vr28,    \_shift

    vmul.w        vr28,   vr16,    vr27
    vmul.w        vr7,    vr17,    vr27
    vmadd.w       vr28,   vr18,    vr31
    vmadd.w       vr7,    vr19,    vr31
    vmadd.w       vr28,   vr20,    vr25
    vmadd.w       vr7,    vr21,    vr25
    vmadd.w       vr28,   vr22,    vr30
    vmadd.w       vr7,    vr23,    vr30
    vssrarni.h.w  vr7,    vr28,    \_shift

    /* E[0...3] */
    vaddwev.w.h   vr24,   vr8,     vr15
    vaddwod.w.h   vr25,   vr8,     vr15
    vilvl.w       vr16,   vr25,    vr24  //[0...3]
    vilvh.w       vr17,   vr25,    vr24  //[4...7]
    vaddwev.w.h   vr24,   vr9,     vr14
    vaddwod.w.h   vr25,   vr9,     vr14
    vilvl.w       vr18,   vr25,    vr24  //[0...3]
    vilvh.w       vr19,   vr25,    vr24  //[4...7]
    vaddwev.w.h   vr24,   vr10,    vr13
    vaddwod.w.h   vr25,   vr10,    vr13
    vilvl.w       vr20,   vr25,    vr24  //[0...3]
    vilvh.w       vr21,   vr25,    vr24  //[4...7]
    vaddwev.w.h   vr24,   vr11,    vr12
    vaddwod.w.h   vr25,   vr11,    vr12
    vilvl.w       vr22,   vr25,    vr24  //[0...3]
    vilvh.w       vr23,   vr25,    vr24  //[4...7]

    vadd.w        vr8,    vr16,    vr22
    vadd.w        vr9,    vr17,    vr23  //EE[0]
    vadd.w        vr10,   vr18,    vr20
    vadd.w        vr11,   vr19,    vr21  //EE[1]
    vsub.w        vr12,   vr16,    vr22
    vsub.w        vr13,   vr17,    vr23  //EO[0]
    vsub.w        vr14,   vr18,    vr20
    vsub.w        vr15,   vr19,    vr21  //EO[1]

    vldrepl.w     vr24,   t1,      0
    vldrepl.w     vr25,   t1,      128 * 2
    vldrepl.w     vr26,   t1,      128 * 2 + 4
    vldrepl.w     vr27,   t1,      128 * 4 + 4
    vldrepl.w     vr29,   t1,      128 * 6 + 4
    vmul.w        vr28,   vr8,     vr24
    vmul.w        vr0,    vr9,     vr24
    vmadd.w       vr28,   vr10,    vr24
    vmadd.w       vr0,    vr11,    vr24
    vssrarni.h.w  vr0,    vr28,    \_shift

    vmul.w        vr28,   vr12,    vr25
    vmul.w        vr2,    vr13,    vr25
    vmadd.w       vr28,   vr14,    vr26
    vmadd.w       vr2,    vr15,    vr26
    vssrarni.h.w  vr2,    vr28,    \_shift

    vmul.w        vr28,   vr8,     vr24
    vmul.w        vr4,    vr9,     vr24
    vmadd.w       vr28,   vr10,    vr27
    vmadd.w       vr4,    vr11,    vr27
    vssrarni.h.w  vr4,    vr28,    \_shift

    vmul.w        vr28,   vr12,    vr26
    vmul.w        vr6,    vr13,    vr26
    vmadd.w       vr28,   vr14,    vr29
    vmadd.w       vr6,    vr15,    vr29
    vssrarni.h.w  vr6,    vr28,    \_shift
.endm

/* void x265_dct8_lsx(const int16_t* src, int16_t* dst, intptr_t srcStride) */
function x265_dct8_lsx
    addi.d        sp,      sp,      -64
    fst.d         f24,     sp,      0
    fst.d         f25,     sp,      8
    fst.d         f26,     sp,      16
    fst.d         f27,     sp,      24
    fst.d         f28,     sp,      32
    fst.d         f29,     sp,      40
    fst.d         f30,     sp,      48
    fst.d         f31,     sp,      56
    la.local      t1,      table_dct16
    slli.d        a3,      a2,      1  //stride
    slli.d        a4,      a2,      2  //stride2
    slli.d        a6,      a2,      3  //stride4
    add.d         a5,      a4,      a3 //stride3
    add.d         a7,      a6,      a3 //stride5
    add.d         t7,      a6,      a4 //stride6
    add.d         t8,      a6,      a5 //stride7

    /*
     * The first butterfly operation.
     */
    vld           vr0,     a0,      0    //line0
    vldx          vr1,     a0,      a3   //line1
    vldx          vr2,     a0,      a4   //line2
    vldx          vr3,     a0,      a5   //line3
    vldx          vr4,     a0,      a6   //line4
    vldx          vr5,     a0,      a7   //line5
    vldx          vr6,     a0,      t7   //line6
    vldx          vr7,     a0,      t8   //line7

    DCT8_BUFFER_FLY 2

    /*
     * The second butterfly operation.
     */
    DCT8_BUFFER_FLY 9
    vst           vr0,     a1,     0
    vst           vr1,     a1,     16
    vst           vr2,     a1,     32
    vst           vr3,     a1,     48
    vst           vr4,     a1,     64
    vst           vr5,     a1,     80
    vst           vr6,     a1,     96
    vst           vr7,     a1,     112

    fld.d         f24,   sp,   0
    fld.d         f25,   sp,   8
    fld.d         f26,   sp,   16
    fld.d         f27,   sp,   24
    fld.d         f28,   sp,   32
    fld.d         f29,   sp,   40
    fld.d         f30,   sp,   48
    fld.d         f31,   sp,   56
    addi.d        sp,    sp,   64
endfunc

.macro DCT4_BUFFER_FLY
    LSX_TRANSPOSE4x4_W_EXTRA vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7

    vadd.w        vr8,     vr4,     vr7 // E[0]
    vadd.w        vr9,     vr5,     vr6 // E[1]
    vsub.w        vr10,    vr4,     vr7 // O[0]
    vsub.w        vr11,    vr5,     vr6 // O[1]

    vmul.w        vr0,     vr8,     vr12
    vmul.w        vr2,     vr8,     vr12
    vmul.w        vr1,     vr10,    vr13
    vmul.w        vr3,     vr10,    vr14
    vmadd.w       vr0,     vr9,     vr12
    vmadd.w       vr2,     vr9,     vr15
    vmadd.w       vr1,     vr11,    vr14
    vmadd.w       vr3,     vr11,    vr16
.endm

/* void x265_dct4_lsx(const int16_t* src, int16_t* dst, intptr_t srcStride) */
function x265_dct4_lsx
    la.local      t1,      table_dct16
    slli.d        a3,      a2,      1  //stride
    slli.d        a4,      a2,      2  //stride2
    add.d         a5,      a4,      a3 //stride3

    vldi          vr12,    0x840       // 64 g_t4[0][0] g_t4[0][1] g_t4[2][0]
    vldi          vr13,    0x853       // 83 g_t4[1][0]
    vldi          vr14,    0x824       // 36 g_t4[1][1] g_t4[3][0]
    vldrepl.w     vr15,    t1,      256 * 2 + 4 // -64 g_t4[2][1]
    vldrepl.w     vr16,    t1,      256 * 3 + 4
    /*
     * The first butterfly operation.
     */
    vld           vr0,     a0,      0    //line0
    vldx          vr1,     a0,      a3   //line1
    vldx          vr2,     a0,      a4   //line2
    vldx          vr3,     a0,      a5   //line3

    vsllwil.w.h   vr0,     vr0,     0
    vsllwil.w.h   vr1,     vr1,     0
    vsllwil.w.h   vr2,     vr2,     0
    vsllwil.w.h   vr3,     vr3,     0

    DCT4_BUFFER_FLY

    vsrari.w      vr0,     vr0,     1
    vsrari.w      vr1,     vr1,     1
    vsrari.w      vr2,     vr2,     1
    vsrari.w      vr3,     vr3,     1

    /*
     * The second butterfly operation.
     */
    DCT4_BUFFER_FLY

    vssrarni.h.w  vr1,     vr0,    8
    vssrarni.h.w  vr3,     vr2,    8

    vst           vr1,     a1,     0
    vst           vr3,     a1,     16
endfunc

.macro DST4_4_LINE
    LSX_TRANSPOSE4x4_W_EXTRA vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7

    vadd.w        vr8,     vr4,     vr7  // c[0]
    vadd.w        vr9,     vr5,     vr7  // c[1]
    vsub.w        vr10,    vr4,     vr5  // c[2]
    vmul.w        vr11,    vr6,     vr12 // c[3]

    vmul.w        vr0,     vr8,     vr13
    vmul.w        vr2,     vr10,    vr13
    vadd.w        vr1,     vr4,     vr5
    vsub.w        vr1,     vr1,     vr7
    vmadd.w       vr2,     vr8,     vr14
    vmadd.w       vr0,     vr9,     vr14
    vmul.w        vr1,     vr1,     vr12
    vadd.w        vr0,     vr0,     vr11
    vsub.w        vr2,     vr2,     vr11
    vmadd.w       vr11,    vr10,    vr14
    vmul.w        vr3,     vr9,     vr13
    vsub.w        vr3,     vr11,    vr3
.endm

/* void x265_dst4_lsx(const int16_t* src, int16_t* dst, intptr_t srcStride) */
function x265_dst4_lsx
    slli.d        a3,      a2,      1  //stride
    vldi          vr12,    0x84A       // 74
    vldi          vr13,    0x81D       // 29
    vldi          vr14,    0x837       // 55

    /*
     * The first butterfly operation.
     */
    vld           vr0,     a0,      0    //line0
    vldx          vr1,     a0,      a3   //line1
    alsl.d        a0,      a3,      a0,  1
    vld           vr2,     a0,      0    //line0
    vldx          vr3,     a0,      a3   //line1

    vsllwil.w.h   vr0,     vr0,     0
    vsllwil.w.h   vr1,     vr1,     0
    vsllwil.w.h   vr2,     vr2,     0
    vsllwil.w.h   vr3,     vr3,     0

    DST4_4_LINE

    vsrari.w      vr0,     vr0,     1
    vsrari.w      vr1,     vr1,     1
    vsrari.w      vr2,     vr2,     1
    vsrari.w      vr3,     vr3,     1

    /*
     * The second butterfly operation.
     */
    DST4_4_LINE

    vssrarni.h.w  vr1,     vr0,    8
    vssrarni.h.w  vr3,     vr2,    8

    vst           vr1,     a1,     0
    vst           vr3,     a1,     16
endfunc

.macro IDST4_4_LINE
    vadd.w        vr4,     vr0,     vr2  //c[0]
    vadd.w        vr5,     vr2,     vr3  //c[1]
    vsub.w        vr6,     vr0,     vr3  //c[2]
    vmul.w        vr7,     vr1,     vr12 //c[3]


    vmul.w        vr8,     vr4,     vr13
    vsub.w        vr10,    vr0,     vr2
    vmul.w        vr9,     vr6,     vr14
    vadd.w        vr10,    vr10,    vr3
    vmul.w        vr11,    vr4,     vr14
    vmadd.w       vr8,     vr5,     vr14
    vadd.w        vr8,     vr8,     vr7
    vmsub.w       vr9,     vr5,     vr13
    vmadd.w       vr11,    vr6,     vr13
    vadd.w        vr9,     vr9,     vr7
    vmul.w        vr10,    vr10,    vr12
    vsub.w        vr11,    vr11,    vr7

    LSX_TRANSPOSE4x4_W_EXTRA vr8, vr9, vr10, vr11, vr0, vr1, vr2, vr3
.endm

/* void x265_idst4_c(const int16_t* src, int16_t* dst, intptr_t dstStride) */
function x265_idst4_lsx
    slli.d        a3,      a2,     1  //stride
    vldi          vr12,    0x84A       // 74
    vldi          vr13,    0x81D       // 29
    vldi          vr14,    0x837       // 55

    /*
     * The first butterfly operation.
     */
    vld           vr4,     a0,     0    //line01
    vld           vr5,     a0,     16   //line23

    vsllwil.w.h   vr0,     vr4,    0
    vexth.w.h     vr1,     vr4
    vsllwil.w.h   vr2,     vr5,    0
    vexth.w.h     vr3,     vr5

    IDST4_4_LINE

    vsrari.w      vr0,     vr0,    7
    vsrari.w      vr1,     vr1,    7
    vsrari.w      vr2,     vr2,    7
    vsrari.w      vr3,     vr3,    7

    /*
     * The second butterfly operation.
     */
    IDST4_4_LINE

    vssrarni.h.w  vr1,     vr0,    12
    vssrarni.h.w  vr3,     vr2,    12

    vstelm.d      vr1,     a1,     0,   0
    add.d         a1,      a1,     a3
    vstelm.d      vr1,     a1,     0,   1
    add.d         a1,      a1,     a3
    vstelm.d      vr3,     a1,     0,   0
    add.d         a1,      a1,     a3
    vstelm.d      vr3,     a1,     0,   1
endfunc

/*
 * Description : Half word signed extension to words.
 * Arguments   : Inputs  - in
 *               Outputs - out0, out1
 * Details     :
 * Example     :
 *               in :1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
 *               =====>
 *               out0: 1, 2, 3, 4, 5, 6, 7, 8,
 *               out1: 9, 10, 11, 12, 13, 14, 15,
 */
.macro LASX_EXT_W_H _in, _out0, _out1
    xvpermi.d     \_out1,  \_in,    0xd8
    xvsllwil.w.h  \_out0,  \_out1,  0
    xvexth.w.h    \_out1,  \_out1
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * temp reg: xr8~xr11
 */
.macro LASX_CAL_DCT_4_ELE_2 _rin, _in0, _in1, _in2, _in3, \
                            _out0, _out1, _si0, _si1, _si2, _si3
    xvldrepl.w    xr8,     \_rin,    \_si0
    xvldrepl.w    xr9,     \_rin,    \_si1
    xvldrepl.w    xr10,    \_rin,    \_si2
    xvldrepl.w    xr11,    \_rin,    \_si3
    xvmul.w       \_out0,  \_in0,    xr8
    xvmadd.w      \_out0,  \_in1,    xr9
    xvmadd.w      \_out0,  \_in2,    xr10
    xvmadd.w      \_out0,  \_in3,    xr11
    xvmul.w       \_out1,  \_in0,    xr11
    xvmsub.w      \_out1,  \_in1,    xr10
    xvmadd.w      \_out1,  \_in2,    xr9
    xvmsub.w      \_out1,  \_in3,    xr8
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: xr8~xr11
 */
.macro LASX_CAL_DCT_4_ELE_2X _rin, _in0, _in1, _in2, _in3, \
                             _out0, _out1, _si0, _si1, _si2, _si3
    xvldrepl.w    xr8,     \_rin,    \_si0
    xvldrepl.w    xr9,     \_rin,    \_si1
    xvldrepl.w    xr10,    \_rin,    \_si2
    xvldrepl.w    xr11,    \_rin,    \_si3
    xvmul.w       \_out0,  \_in0,    xr8
    xvmadd.w      \_out0,  \_in1,    xr9
    xvmadd.w      \_out0,  \_in2,    xr10
    xvmadd.w      \_out0,  \_in3,    xr11
    xvmul.w       \_out1,  \_in3,    xr8
    xvmsub.w      \_out1,  \_in2,    xr9
    xvmadd.w      \_out1,  \_in1,    xr10
    xvmsub.w      \_out1,  \_in0,    xr11
.endm

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * temp reg: xr8~xr15
 */
.macro LASX_CAL_DCT_8_ELE_2 _rin, _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                            _out0, _out1, _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7
    xvldrepl.w    xr8,     \_rin,    \_si0
    xvldrepl.w    xr9,     \_rin,    \_si1
    xvldrepl.w    xr10,    \_rin,    \_si2
    xvldrepl.w    xr11,    \_rin,    \_si3
    xvldrepl.w    xr12,    \_rin,    \_si4
    xvldrepl.w    xr13,    \_rin,    \_si5
    xvldrepl.w    xr14,    \_rin,    \_si6
    xvldrepl.w    xr15,    \_rin,    \_si7
    xvmul.w       \_out0,  \_in0,    xr8
    xvmul.w       \_out1,  \_in0,    xr15
    xvmadd.w      \_out0,  \_in1,    xr9
    xvmsub.w      \_out1,  \_in1,    xr14
    xvmadd.w      \_out0,  \_in2,    xr10
    xvmadd.w      \_out1,  \_in2,    xr13
    xvmadd.w      \_out0,  \_in3,    xr11
    xvmsub.w      \_out1,  \_in3,    xr12
    xvmadd.w      \_out0,  \_in4,    xr12
    xvmadd.w      \_out1,  \_in4,    xr11
    xvmadd.w      \_out0,  \_in5,    xr13
    xvmsub.w      \_out1,  \_in5,    xr10
    xvmadd.w      \_out0,  \_in6,    xr14
    xvmadd.w      \_out1,  \_in6,    xr9
    xvmadd.w      \_out0,  \_in7,    xr15
    xvmsub.w      \_out1,  \_in7,    xr8
.endm

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: xr8~xr15
 */
.macro LASX_CAL_DCT_8_ELE_2X _rin, _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                             _out0, _out1, _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7
    xvldrepl.w    xr8,     \_rin,    \_si0
    xvldrepl.w    xr9,     \_rin,    \_si1
    xvldrepl.w    xr10,    \_rin,    \_si2
    xvldrepl.w    xr11,    \_rin,    \_si3
    xvldrepl.w    xr12,    \_rin,    \_si4
    xvldrepl.w    xr13,    \_rin,    \_si5
    xvldrepl.w    xr14,    \_rin,    \_si6
    xvldrepl.w    xr15,    \_rin,    \_si7
    xvmul.w       \_out0,  \_in0,    xr8
    xvmul.w       \_out1,  \_in7,    xr8
    xvmadd.w      \_out0,  \_in1,    xr9
    xvmsub.w      \_out1,  \_in6,    xr9
    xvmadd.w      \_out0,  \_in2,    xr10
    xvmadd.w      \_out1,  \_in5,    xr10
    xvmadd.w      \_out0,  \_in3,    xr11
    xvmsub.w      \_out1,  \_in4,    xr11
    xvmadd.w      \_out0,  \_in4,    xr12
    xvmadd.w      \_out1,  \_in3,    xr12
    xvmadd.w      \_out0,  \_in5,    xr13
    xvmsub.w      \_out1,  \_in2,    xr13
    xvmadd.w      \_out0,  \_in6,    xr14
    xvmadd.w      \_out1,  \_in1,    xr14
    xvmadd.w      \_out0,  \_in7,    xr15
    xvmsub.w      \_out1,  \_in0,    xr15
.endm

.macro DCT16_8_LINE _shift, _rout
    LASX_TRANSPOSE8x8_H xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7,\
                        xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                        xr8, xr9, xr10, xr11, xr12, xr13, xr14, xr15

    LASX_EXT_W_H xr16, xr0, xr8
    LASX_EXT_W_H xr17, xr1, xr9
    LASX_EXT_W_H xr18, xr2, xr10
    LASX_EXT_W_H xr19, xr3, xr11
    LASX_EXT_W_H xr20, xr4, xr12
    LASX_EXT_W_H xr21, xr5, xr13
    LASX_EXT_W_H xr22, xr6, xr14
    LASX_EXT_W_H xr23, xr7, xr15

    /* O[0...7] */
    xvsub.w       xr16,    xr0,     xr15
    xvsub.w       xr17,    xr1,     xr14
    xvsub.w       xr18,    xr2,     xr13
    xvsub.w       xr19,    xr3,     xr12
    xvsub.w       xr20,    xr4,     xr11
    xvsub.w       xr21,    xr5,     xr10
    xvsub.w       xr22,    xr6,     xr9
    xvsub.w       xr23,    xr7,     xr8

    /* E[0...7] */
    xvadd.w       xr15,    xr0,     xr15
    xvadd.w       xr14,    xr1,     xr14
    xvadd.w       xr13,    xr2,     xr13
    xvadd.w       xr12,    xr3,     xr12
    xvadd.w       xr11,    xr4,     xr11
    xvadd.w       xr10,    xr5,     xr10
    xvadd.w       xr9,     xr6,     xr9
    xvadd.w       xr8,     xr7,     xr8

    /* EE[0...3] */
    xvadd.w       xr0,     xr15,    xr8
    xvadd.w       xr1,     xr14,    xr9
    xvadd.w       xr2,     xr13,    xr10
    xvadd.w       xr3,     xr12,    xr11

    /* EO[0...3] */
    xvsub.w       xr4,     xr15,    xr8
    xvsub.w       xr5,     xr14,    xr9
    xvsub.w       xr6,     xr13,    xr10
    xvsub.w       xr7,     xr12,    xr11

    xvadd.w       xr8,     xr0,     xr3  // EEE[0]
    xvadd.w       xr9,     xr1,     xr2  // EEE[1]
    xvsub.w       xr10,    xr0,     xr3  // EEO[0]
    xvsub.w       xr11,    xr1,     xr2  // EEO[1]

    /* CAL0-8-4-12*/
    xvldrepl.w    xr12,    t1,      0
    xvmul.w       xr0,     xr8,     xr12
    xvmul.w       xr2,     xr8,     xr12
    xvmadd.w      xr0,     xr9,     xr12  //dst[0]
    xvmsub.w      xr2,     xr9,     xr12  //dst[8]

    xvldrepl.w    xr12,    t1,      64 * 4
    xvldrepl.w    xr13,    t1,      64 * 4 + 4
    xvmul.w       xr1,     xr10,    xr12
    xvmul.w       xr3,     xr10,    xr13
    xvmadd.w      xr1,     xr11,    xr13  //dst[4]
    xvmsub.w      xr3,     xr11,    xr12  //dst[12]

    /* CAL2-6-10-14*/
    LASX_CAL_DCT_4_ELE_2 t1, xr4, xr5, xr6, xr7, xr12, xr15, \
                         64 * 2, 64 * 2 + 4, 64 * 2 + 8, 64 * 2 + 12
    LASX_CAL_DCT_4_ELE_2X t1, xr4, xr5, xr6, xr7, xr13, xr14, \
                          64 * 6, 64 * 6 + 4, 64 * 6 + 8, 64 * 6 + 12

    xvssrarni.h.w   xr12,   xr0,    \_shift
    xvssrarni.h.w   xr13,   xr1,    \_shift
    xvssrarni.h.w   xr14,   xr2,    \_shift
    xvssrarni.h.w   xr15,   xr3,    \_shift

    xvstelm.d       xr12,   \_rout, 0,            0
    xvstelm.d       xr12,   \_rout, 8,            2  // k = 0
    xvstelm.d       xr12,   \_rout, 32 * 2,       1
    xvstelm.d       xr12,   \_rout, 32 * 2 + 8,   3  // k = 2
    xvstelm.d       xr13,   \_rout, 32 * 4,       0
    xvstelm.d       xr13,   \_rout, 32 * 4 + 8,   2  // k = 4
    xvstelm.d       xr13,   \_rout, 32 * 6,       1
    xvstelm.d       xr13,   \_rout, 32 * 6 + 8,   3  // k = 6
    xvstelm.d       xr14,   \_rout, 32 * 8,       0
    xvstelm.d       xr14,   \_rout, 32 * 8 + 8,   2  // k = 8
    xvstelm.d       xr14,   \_rout, 32 * 10,      1
    xvstelm.d       xr14,   \_rout, 32 * 10 + 8,  3  // k = 10
    xvstelm.d       xr15,   \_rout, 32 * 12,      0
    xvstelm.d       xr15,   \_rout, 32 * 12 + 8,  2  // k = 12
    xvstelm.d       xr15,   \_rout, 32 * 14,      1
    xvstelm.d       xr15,   \_rout, 32 * 14 + 8,  3  // k = 14

    /* CAL1-3-5-7...*/
    LASX_CAL_DCT_8_ELE_2 t1, xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                         xr0, xr7, 64 * 1, 64 * 1 + 4, 64 * 1 + 8, 64 * 1 + 12, \
                         64 * 1 + 16, 64 * 1 + 20, 64 * 1 + 24, 64 * 1 + 28
    LASX_CAL_DCT_8_ELE_2X t1, xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                          xr1, xr6, 64 * 3, 64 * 3 + 4, 64 * 3 + 8, 64 * 3 + 12, \
                          64 * 3 + 16, 64 * 3 + 20, 64 * 3 + 24, 64 * 3 + 28
    LASX_CAL_DCT_8_ELE_2 t1, xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                         xr2, xr5, 64 * 5, 64 * 5 + 4, 64 * 5 + 8, 64 * 5 + 12, \
                         64 * 5 + 16, 64 * 5 + 20, 64 * 5 + 24, 64 * 5 + 28
    LASX_CAL_DCT_8_ELE_2X t1, xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                          xr3, xr4, 64 * 7, 64 * 7 + 4, 64 * 7 + 8, 64 * 7 + 12, \
                          64 * 7 + 16, 64 * 7 + 20, 64 * 7 + 24, 64 * 7 + 28

    xvssrarni.h.w   xr1,    xr0,    \_shift
    xvssrarni.h.w   xr3,    xr2,    \_shift
    xvssrarni.h.w   xr5,    xr4,    \_shift
    xvssrarni.h.w   xr7,    xr6,    \_shift

    xvstelm.d       xr1,    \_rout, 32 * 1,       0
    xvstelm.d       xr1,    \_rout, 32 * 1 + 8,   2  // k = 1
    xvstelm.d       xr1,    \_rout, 32 * 3,       1
    xvstelm.d       xr1,    \_rout, 32 * 3 + 8,   3  // k = 3
    xvstelm.d       xr3,    \_rout, 32 * 5,       0
    xvstelm.d       xr3,    \_rout, 32 * 5 + 8,   2  // k = 5
    xvstelm.d       xr3,    \_rout, 32 * 7,       1
    xvstelm.d       xr3,    \_rout, 32 * 7 + 8,   3  // k = 7
    xvstelm.d       xr5,    \_rout, 32 * 9,       0
    xvstelm.d       xr5,    \_rout, 32 * 9 + 8,   2  // k = 9
    xvstelm.d       xr5,    \_rout, 32 * 11,      1
    xvstelm.d       xr5,    \_rout, 32 * 11 + 8,  3  // k = 11
    xvstelm.d       xr7,    \_rout, 32 * 13,      0
    xvstelm.d       xr7,    \_rout, 32 * 13 + 8,  2  // k = 13
    xvstelm.d       xr7,    \_rout, 32 * 15,      1
    xvstelm.d       xr7,    \_rout, 32 * 15 + 8,  3  // k = 15
.endm

/* void x265_dct16_lasx(const int16_t* src, int16_t* dst, intptr_t srcStride) */
function x265_dct16_lasx
    addi.d        sp,      sp,      -512 //-(16*16*2) si12 Immediate overflow
    la.local      t1,      table_dct16
    slli.d        a3,      a2,      1  //stride
    slli.d        a4,      a2,      2  //stride2
    slli.d        a6,      a2,      3  //stride4
    slli.d        t6,      a2,      4  //stride8
    add.d         a5,      a4,      a3 //stride3
    add.d         a7,      a6,      a3 //stride5
    add.d         t7,      a6,      a4 //stride6
    add.d         t8,      a6,      a5 //stride7

    /*
     * The first butterfly operation.
     */
    xvld          xr0,     a0,      0    //line0
    xvldx         xr1,     a0,      a3   //line1
    xvldx         xr2,     a0,      a4   //line2
    xvldx         xr3,     a0,      a5   //line3
    xvldx         xr4,     a0,      a6   //line4
    xvldx         xr5,     a0,      a7   //line5
    xvldx         xr6,     a0,      t7   //line6
    xvldx         xr7,     a0,      t8   //line7
    DCT16_8_LINE 3, sp
    addi.d        t2,      sp,      16

    add.d         a0,      a0,      t6
    xvld          xr0,     a0,      0    //line8
    xvldx         xr1,     a0,      a3   //line9
    xvldx         xr2,     a0,      a4   //line10
    xvldx         xr3,     a0,      a5   //line11
    xvldx         xr4,     a0,      a6   //line12
    xvldx         xr5,     a0,      a7   //line13
    xvldx         xr6,     a0,      t7   //line14
    xvldx         xr7,     a0,      t8   //line15
    DCT16_8_LINE 3, t2

    /*
     * The second butterfly operation.
     */
    xvld          xr0,     sp,      0    //line0
    xvld          xr1,     sp,      32   //line1
    xvld          xr2,     sp,      64   //line2
    xvld          xr3,     sp,      96   //line3
    xvld          xr4,     sp,      128  //line4
    xvld          xr5,     sp,      160  //line5
    xvld          xr6,     sp,      192  //line6
    xvld          xr7,     sp,      224  //line7
    DCT16_8_LINE 10, a1

    addi.d        t2,      a1,      16
    xvld          xr0,     sp,      256  //line8
    xvld          xr1,     sp,      288  //line9
    xvld          xr2,     sp,      320  //line10
    xvld          xr3,     sp,      352  //line11
    xvld          xr4,     sp,      384  //line12
    xvld          xr5,     sp,      416  //line13
    xvld          xr6,     sp,      448  //line14
    xvld          xr7,     sp,      480  //line15
    DCT16_8_LINE 10, t2

    addi.d        sp,      sp,   512
endfunc

/*
 *  _out0, _out1: E[0...15]
 *  _out2, _out3: O[0...15]
 *  temp reg: xr28, xr29, xr30
 */
.macro LASX_LOAD_DCT32 _out0, _out1, _out2, _out3, _in
    xvld          xr28,  \_in,    0    //src[0...15]
    xvld          xr29,  \_in,    32   //src[16...31]

    xvshuf.b      xr29,   xr29,   xr29, xr31
    xvpermi.q     xr29,   xr29,   0x1

    xvaddwev.w.h  \_out2,  xr28,    xr29
    xvaddwod.w.h  \_out3,  xr28,    xr29
    xvilvl.w      \_out0,  \_out3,  \_out2
    xvilvh.w      \_out1,  \_out3,  \_out2
    xmov          xr30,    \_out0
    xvpermi.q     \_out0,  \_out1,  0x2   //E[0...7]
    xvpermi.q     \_out1,  xr30,    0x31  //E[8...15]1

    xvsubwev.w.h  xr30,    xr28,    xr29
    xvsubwod.w.h  xr28,    xr28,    xr29
    xvilvl.w      \_out2,  xr28,    xr30
    xvilvh.w      \_out3,  xr28,    xr30
    xmov          xr30,    \_out2
    xvpermi.q     \_out2,  \_out3,  0x2   //O[0...7]
    xvpermi.q     \_out3,  xr30,    0x31  //O[8...15]1
.endm

/*
 * Description : Multiplication and addition calculation of 16 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * in reg: xr8 ~ xr15, xr0, xr2, xr4, xr6, xr20, xr21, xr22, xr23
 * temp reg: xr16 ~ xr19
 */
.macro LASX_CAL_DCT_16_ELE_2 _rin, _out0,  _out1, \
                             _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7, \
                             _si8, _si9, _si10, _si11, _si12, _si13, _si14, _si15
    xvldrepl.w     xr16,    \_rin,    \_si0
    xvldrepl.w     xr17,    \_rin,    \_si1
    xvldrepl.w     xr18,    \_rin,    \_si2
    xvldrepl.w     xr19,    \_rin,    \_si3
    xvmul.w        \_out0,  xr8,      xr16
    xvmul.w        \_out1,  xr20,     xr19
    xvmadd.w       \_out0,  xr9,      xr17
    xvmsub.w       \_out1,  xr21,     xr18
    xvmadd.w       \_out0,  xr10,     xr18
    xvmadd.w       \_out1,  xr22,     xr17
    xvmadd.w       \_out0,  xr11,     xr19
    xvmsub.w       \_out1,  xr23,     xr16

    xvldrepl.w     xr16,    \_rin,    \_si4
    xvldrepl.w     xr17,    \_rin,    \_si5
    xvldrepl.w     xr18,    \_rin,    \_si6
    xvldrepl.w     xr19,    \_rin,    \_si7
    xvmadd.w       \_out0,  xr12,     xr16
    xvmadd.w       \_out1,  xr0,      xr19
    xvmadd.w       \_out0,  xr13,     xr17
    xvmsub.w       \_out1,  xr2,      xr18
    xvmadd.w       \_out0,  xr14,     xr18
    xvmadd.w       \_out1,  xr4,      xr17
    xvmadd.w       \_out0,  xr15,     xr19
    xvmsub.w       \_out1,  xr6,      xr16

    xvldrepl.w     xr16,    \_rin,    \_si8
    xvldrepl.w     xr17,    \_rin,    \_si9
    xvldrepl.w     xr18,    \_rin,    \_si10
    xvldrepl.w     xr19,    \_rin,    \_si11
    xvmadd.w       \_out0,  xr0,      xr16
    xvmadd.w       \_out1,  xr12,     xr19
    xvmadd.w       \_out0,  xr2,      xr17
    xvmsub.w       \_out1,  xr13,     xr18
    xvmadd.w       \_out0,  xr4,      xr18
    xvmadd.w       \_out1,  xr14,     xr17
    xvmadd.w       \_out0,  xr6,      xr19
    xvmsub.w       \_out1,  xr15,     xr16

    xvldrepl.w     xr16,    \_rin,    \_si12
    xvldrepl.w     xr17,    \_rin,    \_si13
    xvldrepl.w     xr18,    \_rin,    \_si14
    xvldrepl.w     xr19,    \_rin,    \_si15
    xvmadd.w       \_out0,  xr20,     xr16
    xvmadd.w       \_out1,  xr8,      xr19
    xvmadd.w       \_out0,  xr21,     xr17
    xvmsub.w       \_out1,  xr9,      xr18
    xvmadd.w       \_out0,  xr22,     xr18
    xvmadd.w       \_out1,  xr10,     xr17
    xvmadd.w       \_out0,  xr23,     xr19
    xvmsub.w       \_out1,  xr11,     xr16
.endm

/*
 * Description : Multiplication and addition calculation of 16 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * in reg: xr8 ~ xr15, xr0, xr2, xr4, xr6, xr20, xr21, xr22, xr23
 * temp reg: xr16 ~ xr19
 */
.macro LASX_CAL_DCT_16_ELE_2X _rin, _out0,  _out1, \
                              _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7, \
                              _si8, _si9, _si10, _si11, _si12, _si13, _si14, _si15
    xvldrepl.w     xr16,    \_rin,    \_si0
    xvldrepl.w     xr17,    \_rin,    \_si1
    xvldrepl.w     xr18,    \_rin,    \_si2
    xvldrepl.w     xr19,    \_rin,    \_si3
    xvmul.w        \_out0,  xr8,      xr16
    xvmul.w        \_out1,  xr23,     xr16
    xvmadd.w       \_out0,  xr9,      xr17
    xvmsub.w       \_out1,  xr22,     xr17
    xvmadd.w       \_out0,  xr10,     xr18
    xvmadd.w       \_out1,  xr21,     xr18
    xvmadd.w       \_out0,  xr11,     xr19
    xvmsub.w       \_out1,  xr20,     xr19

    xvldrepl.w     xr16,    \_rin,    \_si4
    xvldrepl.w     xr17,    \_rin,    \_si5
    xvldrepl.w     xr18,    \_rin,    \_si6
    xvldrepl.w     xr19,    \_rin,    \_si7
    xvmadd.w       \_out0,  xr12,     xr16
    xvmadd.w       \_out1,  xr6,      xr16
    xvmadd.w       \_out0,  xr13,     xr17
    xvmsub.w       \_out1,  xr4,      xr17
    xvmadd.w       \_out0,  xr14,     xr18
    xvmadd.w       \_out1,  xr2,      xr18
    xvmadd.w       \_out0,  xr15,     xr19
    xvmsub.w       \_out1,  xr0,      xr19

    xvldrepl.w     xr16,    \_rin,    \_si8
    xvldrepl.w     xr17,    \_rin,    \_si9
    xvldrepl.w     xr18,    \_rin,    \_si10
    xvldrepl.w     xr19,    \_rin,    \_si11
    xvmadd.w       \_out0,  xr0,      xr16
    xvmadd.w       \_out1,  xr15,     xr16
    xvmadd.w       \_out0,  xr2,      xr17
    xvmsub.w       \_out1,  xr14,     xr17
    xvmadd.w       \_out0,  xr4,      xr18
    xvmadd.w       \_out1,  xr13,     xr18
    xvmadd.w       \_out0,  xr6,      xr19
    xvmsub.w       \_out1,  xr12,     xr19

    xvldrepl.w     xr16,    \_rin,    \_si12
    xvldrepl.w     xr17,    \_rin,    \_si13
    xvldrepl.w     xr18,    \_rin,    \_si14
    xvldrepl.w     xr19,    \_rin,    \_si15
    xvmadd.w       \_out0,  xr20,     xr16
    xvmadd.w       \_out1,  xr11,     xr16
    xvmadd.w       \_out0,  xr21,     xr17
    xvmsub.w       \_out1,  xr10,     xr17
    xvmadd.w       \_out0,  xr22,     xr18
    xvmadd.w       \_out1,  xr9,      xr18
    xvmadd.w       \_out0,  xr23,     xr19
    xvmsub.w       \_out1,  xr8,      xr19
.endm

.macro LASX_CLA_DCT32_O _shift
    LASX_TRANSPOSE8x8_W xr0, xr2, xr4, xr6, xr24, xr26, xr16, xr18, \
                        xr8, xr9, xr10, xr11, xr12, xr13, xr14, xr15, \
                        xr28, xr29, xr30, xr31
    LASX_TRANSPOSE8x8_W xr1, xr3, xr5, xr7, xr25, xr27, xr17, xr19, \
                        xr0, xr2, xr4, xr6, xr20, xr21, xr22, xr23,\
                        xr28, xr29, xr30, xr31

    addi.d        t3,      t2,      64 * 14
    addi.d        t6,      t3,      64 * 14
    LASX_CAL_DCT_16_ELE_2 t1, xr25, xr28, \
                          128 * 1, 128 * 1 + 4, 128 * 1 + 8, 128 * 1 + 12, \
                          128 * 1 + 16, 128 * 1 + 20, 128 * 1 + 24, 128 * 1 + 28, \
                          128 * 1 + 32, 128 * 1 + 36, 128 * 1 + 40, 128 * 1 + 44, \
                          128 * 1 + 48, 128 * 1 + 52, 128 * 1 + 56, 128 * 1 + 60
    LASX_CAL_DCT_16_ELE_2X t1, xr26, xr27, \
                           128 * 3, 128 * 3 + 4, 128 * 3 + 8, 128 * 3 + 12, \
                           128 * 3 + 16, 128 * 3 + 20, 128 * 3 + 24, 128 * 3 + 28, \
                           128 * 3 + 32, 128 * 3 + 36, 128 * 3 + 40, 128 * 3 + 44, \
                           128 * 3 + 48, 128 * 3 + 52, 128 * 3 + 56, 128 * 3 + 60
    xvssrarni.h.w  xr26,    xr25,    \_shift
    xvssrarni.h.w  xr28,    xr27,    \_shift

    LASX_CAL_DCT_16_ELE_2 t1, xr25, xr3, \
                          128 * 5, 128 * 5 + 4, 128 * 5 + 8, 128 * 5 + 12, \
                          128 * 5 + 16, 128 * 5 + 20, 128 * 5 + 24, 128 * 5 + 28, \
                          128 * 5 + 32, 128 * 5 + 36, 128 * 5 + 40, 128 * 5 + 44, \
                          128 * 5 + 48, 128 * 5 + 52, 128 * 5 + 56, 128 * 5 + 60
    LASX_CAL_DCT_16_ELE_2X t1, xr1, xr27, \
                           128 * 7, 128 * 7 + 4, 128 * 7 + 8, 128 * 7 + 12, \
                           128 * 7 + 16, 128 * 7 + 20, 128 * 7 + 24, 128 * 7 + 28, \
                           128 * 7 + 32, 128 * 7 + 36, 128 * 7 + 40, 128 * 7 + 44, \
                           128 * 7 + 48, 128 * 7 + 52, 128 * 7 + 56, 128 * 7 + 60
    xvssrarni.h.w  xr1,    xr25,     \_shift
    xvssrarni.h.w  xr3,    xr27,     \_shift

    LASX_CAL_DCT_16_ELE_2 t1, xr25, xr7, \
                          128 * 9, 128 * 9 + 4, 128 * 9 + 8, 128 * 9 + 12, \
                          128 * 9 + 16, 128 * 9 + 20, 128 * 9 + 24, 128 * 9 + 28, \
                          128 * 9 + 32, 128 * 9 + 36, 128 * 9 + 40, 128 * 9 + 44, \
                          128 * 9 + 48, 128 * 9 + 52, 128 * 9 + 56, 128 * 9 + 60
    LASX_CAL_DCT_16_ELE_2X t1, xr5, xr27, \
                           128 * 11, 128 * 11 + 4, 128 * 11 + 8, 128 * 11 + 12, \
                           128 * 11 + 16, 128 * 11 + 20, 128 * 11 + 24, 128 * 11 + 28, \
                           128 * 11 + 32, 128 * 11 + 36, 128 * 11 + 40, 128 * 11 + 44, \
                           128 * 11 + 48, 128 * 11 + 52, 128 * 11 + 56, 128 * 11 + 60
    xvssrarni.h.w  xr5,     xr25,    \_shift
    xvssrarni.h.w  xr7,     xr27,    \_shift

    LASX_CAL_DCT_16_ELE_2 t1, xr25, xr30, \
                          128 * 13, 128 * 13 + 4, 128 * 13 + 8, 128 * 13 + 12, \
                          128 * 13 + 16, 128 * 13 + 20, 128 * 13 + 24, 128 * 13 + 28, \
                          128 * 13 + 32, 128 * 13 + 36, 128 * 13 + 40, 128 * 13 + 44, \
                          128 * 13 + 48, 128 * 13 + 52, 128 * 13 + 56, 128 * 13 + 60
    LASX_CAL_DCT_16_ELE_2X t1, xr29, xr27, \
                           128 * 15, 128 * 15 + 4, 128 * 15 + 8, 128 * 15 + 12, \
                           128 * 15 + 16, 128 * 15 + 20, 128 * 15 + 24, 128 * 15 + 28, \
                           128 * 15 + 32, 128 * 15 + 36, 128 * 15 + 40, 128 * 15 + 44, \
                           128 * 15 + 48, 128 * 15 + 52, 128 * 15 + 56, 128 * 15 + 60
    xvssrarni.h.w  xr29,    xr25,    \_shift
    xvssrarni.h.w  xr30,    xr27,    \_shift

    xvstelm.d      xr26,    t2,      64 * 1,       0
    xvstelm.d      xr26,    t2,      64 * 1 + 8,   2  // k = 1
    xvstelm.d      xr26,    t2,      64 * 3,       1
    xvstelm.d      xr26,    t2,      64 * 3 + 8,   3  // k = 3
    xvstelm.d      xr1,     t2,      64 * 5,       0
    xvstelm.d      xr1,     t2,      64 * 5 + 8,   2  // k = 5
    xvstelm.d      xr1,     t2,      64 * 7,       1
    xvstelm.d      xr1,     t2,      64 * 7 + 8,   3  // k = 7
    xvstelm.d      xr5,     t2,      64 * 9,       0
    xvstelm.d      xr5,     t2,      64 * 9 + 8,   2  // k = 9
    xvstelm.d      xr5,     t2,      64 * 11,      1
    xvstelm.d      xr5,     t2,      64 * 11 + 8,  3  // k = 11
    xvstelm.d      xr29,    t2,      64 * 13,      0
    xvstelm.d      xr29,    t2,      64 * 13 + 8,  2  // k = 13
    xvstelm.d      xr29,    t3,      64 * 1,       1
    xvstelm.d      xr29,    t3,      64 * 1 + 8,   3  // k = 15
    xvstelm.d      xr30,    t3,      64 * 3,       0
    xvstelm.d      xr30,    t3,      64 * 3 + 8,   2  // k = 17
    xvstelm.d      xr30,    t3,      64 * 5,       1
    xvstelm.d      xr30,    t3,      64 * 5 + 8,   3  // k = 19
    xvstelm.d      xr7,     t3,      64 * 7,       0
    xvstelm.d      xr7,     t3,      64 * 7 + 8,   2  // k = 21
    xvstelm.d      xr7,     t3,      64 * 9,       1
    xvstelm.d      xr7,     t3,      64 * 9 + 8,   3  // k = 23
    xvstelm.d      xr3,     t3,      64 * 11,      0
    xvstelm.d      xr3,     t3,      64 * 11 + 8,  2  // k = 25
    xvstelm.d      xr3,     t3,      64 * 13,      1
    xvstelm.d      xr3,     t3,      64 * 13 + 8,  3  // k = 27
    xvstelm.d      xr28,    t6,      64 * 1,       0
    xvstelm.d      xr28,    t6,      64 * 1 + 8,   2  // k = 29
    xvstelm.d      xr28,    t6,      64 * 3,       1
    xvstelm.d      xr28,    t6,      64 * 3 + 8,   3  // k = 31
.endm

.macro LASX_CLA_DCT32_E _shift
    LASX_TRANSPOSE8x8_W xr8, xr9, xr10, xr11, xr12, xr13, xr14, xr15, \
                        xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7,\
                        xr28, xr29, xr30, xr31
    LASX_TRANSPOSE8x8_W xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                        xr8, xr9, xr10, xr11, xr12, xr13, xr14, xr15, \
                        xr28, xr29, xr30, xr31

    /* EO[0...7] */
    xvsub.w       xr16,    xr0,     xr15
    xvsub.w       xr17,    xr1,     xr14
    xvsub.w       xr18,    xr2,     xr13
    xvsub.w       xr19,    xr3,     xr12
    xvsub.w       xr20,    xr4,     xr11
    xvsub.w       xr21,    xr5,     xr10
    xvsub.w       xr22,    xr6,     xr9
    xvsub.w       xr23,    xr7,     xr8

    /* EE[0...7] */
    xvadd.w       xr15,    xr0,     xr15
    xvadd.w       xr14,    xr1,     xr14
    xvadd.w       xr13,    xr2,     xr13
    xvadd.w       xr12,    xr3,     xr12
    xvadd.w       xr11,    xr4,     xr11
    xvadd.w       xr10,    xr5,     xr10
    xvadd.w       xr9,     xr6,     xr9
    xvadd.w       xr8,     xr7,     xr8

    /* EEE[0...3] */
    xvadd.w       xr0,     xr15,    xr8
    xvadd.w       xr1,     xr14,    xr9
    xvadd.w       xr2,     xr13,    xr10
    xvadd.w       xr3,     xr12,    xr11

    /* EEO[0...3] */
    xvsub.w       xr4,     xr15,    xr8
    xvsub.w       xr5,     xr14,    xr9
    xvsub.w       xr6,     xr13,    xr10
    xvsub.w       xr7,     xr12,    xr11

    xvadd.w       xr8,     xr0,     xr3  // EEEE[0]
    xvadd.w       xr9,     xr1,     xr2  // EEEE[1]
    xvsub.w       xr10,    xr0,     xr3  // EEEO[0]
    xvsub.w       xr11,    xr1,     xr2  // EEEO[1]

    addi.d        t3,      t2,      64 * 16

    /* CAL0-8-16-24*/
    xvldrepl.w    xr12,    t1,      0
    xvmul.w       xr0,     xr8,     xr12
    xvmul.w       xr2,     xr8,     xr12
    xvmadd.w      xr0,     xr9,     xr12  //dst[0]
    xvmsub.w      xr2,     xr9,     xr12  //dst[16]

    xvldrepl.w    xr13,    t1,      128 * 8
    xvldrepl.w    xr14,    t1,      128 * 8 + 4
    xvmul.w       xr1,     xr10,    xr13
    xvmul.w       xr3,     xr10,    xr14
    xvmadd.w      xr1,     xr11,    xr14  //dst[8]
    xvmsub.w      xr3,     xr11,    xr13  //dst[24]

    /* CAL2-6-10-14*/
    LASX_CAL_DCT_4_ELE_2 t1, xr4, xr5, xr6, xr7, xr12, xr15, \
                         128 * 4, 128 * 4 + 4, 128 * 4 + 8, 128 * 4 + 12
    LASX_CAL_DCT_4_ELE_2X t1, xr4, xr5, xr6, xr7, xr13, xr14, \
                          128 * 12, 128 * 12 + 4, 128 * 12 + 8, 128 * 12 + 12

    xvssrarni.h.w   xr12,   xr0,    \_shift
    xvssrarni.h.w   xr13,   xr1,    \_shift
    xvssrarni.h.w   xr14,   xr2,    \_shift
    xvssrarni.h.w   xr15,   xr3,    \_shift

    xvstelm.d       xr12,   t2,     0,            0
    xvstelm.d       xr12,   t2,     8,            2  // k = 0
    xvstelm.d       xr12,   t2,     64 * 4,       1
    xvstelm.d       xr12,   t2,     64 * 4+ 8,    3  // k = 4
    xvstelm.d       xr13,   t2,     64 * 8,       0
    xvstelm.d       xr13,   t2,     64 * 8 + 8,   2  // k = 8
    xvstelm.d       xr13,   t2,     64 * 12,      1
    xvstelm.d       xr13,   t2,     64 * 12 + 8,  3  // k = 12
    xvstelm.d       xr14,   t3,     0,            0
    xvstelm.d       xr14,   t3,     8,            2  // k = 16
    xvstelm.d       xr14,   t3,     64 * 4,       1
    xvstelm.d       xr14,   t3,     64 * 4 + 8,   3  // k = 20
    xvstelm.d       xr15,   t3,     64 * 8,       0
    xvstelm.d       xr15,   t3,     64 * 8 + 8,   2  // k = 24
    xvstelm.d       xr15,   t3,     64 * 12,      1
    xvstelm.d       xr15,   t3,     64 * 12 + 8,  3  // k = 28

    /* CAL2-6-10-14...*/
    LASX_CAL_DCT_8_ELE_2 t1, xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                         xr0, xr7, 128 * 2, 128 * 2 + 4, 128 * 2 + 8, 128 * 2 + 12, \
                         128 * 2 + 16, 128 * 2 + 20, 128 * 2 + 24, 128 * 2 + 28
    LASX_CAL_DCT_8_ELE_2X t1, xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                          xr1, xr6, 128 * 6, 128 * 6 + 4, 128 * 6 + 8, 128 * 6 + 12, \
                          128 * 6 + 16, 128 * 6 + 20, 128 * 6 + 24, 128 * 6 + 28
    LASX_CAL_DCT_8_ELE_2 t1, xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                         xr2, xr5, 128 * 10, 128 * 10 + 4, 128 * 10 + 8, 128 * 10 + 12, \
                         128 * 10 + 16, 128 * 10 + 20, 128 * 10 + 24, 128 * 10 + 28
    LASX_CAL_DCT_8_ELE_2X t1, xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                          xr3, xr4, 128 * 14, 128 * 14 + 4, 128 * 14 + 8, 128 * 14 + 12, \
                          128 * 14 + 16, 128 * 14 + 20, 128 * 14 + 24, 128 * 14 + 28

    xvssrarni.h.w   xr1,    xr0,    \_shift
    xvssrarni.h.w   xr3,    xr2,    \_shift
    xvssrarni.h.w   xr5,    xr4,    \_shift
    xvssrarni.h.w   xr7,    xr6,    \_shift

    xvstelm.d       xr1,    t2,     64 * 2,       0
    xvstelm.d       xr1,    t2,     64 * 2 + 8,   2  // k = 2
    xvstelm.d       xr1,    t2,     64 * 6,       1
    xvstelm.d       xr1,    t2,     64 * 6 + 8,   3  // k = 6
    xvstelm.d       xr3,    t2,     64 * 10,      0
    xvstelm.d       xr3,    t2,     64 * 10 + 8,  2  // k = 10
    xvstelm.d       xr3,    t2,     64 * 14,      1
    xvstelm.d       xr3,    t2,     64 * 14 + 8,  3  // k = 14
    xvstelm.d       xr5,    t3,     64 * 2,       0
    xvstelm.d       xr5,    t3,     64 * 2 + 8,   2  // k = 18
    xvstelm.d       xr5,    t3,     64 * 6,       1
    xvstelm.d       xr5,    t3,     64 * 6 + 8,   3  // k = 22
    xvstelm.d       xr7,    t3,     64 * 10,      0
    xvstelm.d       xr7,    t3,     64 * 10 + 8,  2  // k = 26
    xvstelm.d       xr7,    t3,     64 * 14,      1
    xvstelm.d       xr7,    t3,     64 * 14 + 8,  3  // k = 30
.endm

.macro DCT32_8_LINE_1
    xvld          xr31,    t0,      0

    LASX_LOAD_DCT32   xr8, xr16, xr0, xr1, a0
    add.d         a0,      a0,      a2
    LASX_LOAD_DCT32   xr9, xr17, xr2, xr3, a0
    add.d         a0,      a0,      a2
    LASX_LOAD_DCT32   xr10, xr18, xr4, xr5, a0
    add.d         a0,      a0,      a2
    LASX_LOAD_DCT32   xr11, xr19, xr6, xr7, a0
    add.d         a0,      a0,      a2
    LASX_LOAD_DCT32   xr12, xr20, xr24, xr25, a0
    add.d         a0,      a0,      a2
    LASX_LOAD_DCT32   xr13, xr21, xr26, xr27, a0
    add.d         a0,      a0,      a2

    xvst          xr0,     t4,      0
    xvst          xr1,     t4,      32
    xvst          xr2,     t4,      32 * 2
    xvst          xr3,     t4,      32 * 3
    xvst          xr4,     t4,      32 * 4
    xvst          xr5,     t4,      32 * 5
    xvst          xr6,     t4,      32 * 6
    xvst          xr7,     t4,      32 * 7

    LASX_LOAD_DCT32   xr14, xr22, xr0, xr1, a0
    add.d         a0,      a0,      a2
    LASX_LOAD_DCT32   xr15, xr23, xr2, xr3, a0
    add.d         a0,      a0,      a2
    xvst          xr0,     t4,      32 * 8
    xvst          xr1,     t4,      32 * 9
    xvst          xr2,     t4,      32 * 10
    xvst          xr3,     t4,      32 * 11

    LASX_CLA_DCT32_E 4

    xvld          xr0,     t4,      0
    xvld          xr1,     t4,      32
    xvld          xr2,     t4,      32 * 2
    xvld          xr3,     t4,      32 * 3
    xvld          xr4,     t4,      32 * 4
    xvld          xr5,     t4,      32 * 5
    xvld          xr6,     t4,      32 * 6
    xvld          xr7,     t4,      32 * 7
    xvld          xr16,    t4,      32 * 8
    xvld          xr17,    t4,      32 * 9
    xvld          xr18,    t4,      32 * 10
    xvld          xr19,    t4,      32 * 11
    LASX_CLA_DCT32_O 4

    addi.d        t2,      t2,      16
.endm

.macro DCT32_8_LINE_2
    xvld          xr31,    t0,      0

    LASX_LOAD_DCT32   xr8, xr16, xr0, xr1, a3
    addi.d        a3,      a3,      64
    LASX_LOAD_DCT32   xr9, xr17, xr2, xr3, a3
    addi.d        a3,      a3,      64
    LASX_LOAD_DCT32   xr10, xr18, xr4, xr5, a3
    addi.d        a3,      a3,      64
    LASX_LOAD_DCT32   xr11, xr19, xr6, xr7, a3
    addi.d        a3,      a3,      64
    LASX_LOAD_DCT32   xr12, xr20, xr24, xr25, a3
    addi.d        a3,      a3,      64
    LASX_LOAD_DCT32   xr13, xr21, xr26, xr27, a3
    addi.d        a3,      a3,      64

    xvst          xr0,     t4,      0
    xvst          xr1,     t4,      32
    xvst          xr2,     t4,      32 * 2
    xvst          xr3,     t4,      32 * 3
    xvst          xr4,     t4,      32 * 4
    xvst          xr5,     t4,      32 * 5
    xvst          xr6,     t4,      32 * 6
    xvst          xr7,     t4,      32 * 7

    LASX_LOAD_DCT32   xr14, xr22, xr0, xr1, a3
    addi.d        a3,      a3,      64
    LASX_LOAD_DCT32   xr15, xr23, xr2, xr3, a3
    addi.d        a3,      a3,      64
    xvst          xr0,     t4,      32 * 8
    xvst          xr1,     t4,      32 * 9
    xvst          xr2,     t4,      32 * 10
    xvst          xr3,     t4,      32 * 11

    LASX_CLA_DCT32_E 11

    xvld          xr0,     t4,      0
    xvld          xr1,     t4,      32
    xvld          xr2,     t4,      32 * 2
    xvld          xr3,     t4,      32 * 3
    xvld          xr4,     t4,      32 * 4
    xvld          xr5,     t4,      32 * 5
    xvld          xr6,     t4,      32 * 6
    xvld          xr7,     t4,      32 * 7
    xvld          xr16,    t4,      32 * 8
    xvld          xr17,    t4,      32 * 9
    xvld          xr18,    t4,      32 * 10
    xvld          xr19,    t4,      32 * 11
    LASX_CLA_DCT32_O 11

    addi.d        t2,      t2,      16
.endm

/* void x265_dct32_lasx(const int16_t* src, int16_t* dst, intptr_t srcStride) */
function x265_dct32_lasx
    addi.d        sp,      sp,      -1248 //-(64 + 12*32 + 32*32*2) si12 Immediate overflow
    addi.d        sp,      sp,      -1248
    fst.d         f24,     sp,      0
    fst.d         f25,     sp,      8
    fst.d         f26,     sp,      16
    fst.d         f27,     sp,      24
    fst.d         f28,     sp,      32
    fst.d         f29,     sp,      40
    fst.d         f30,     sp,      48
    fst.d         f31,     sp,      56
    la.local      t0,      shuf_1
    la.local      t1,      table_dct32
    slli.d        a2,      a2,      1  //stride

    /*
     * The first butterfly operation.
     */
    addi.d        t2,      sp,      64 + 12 * 32
    addi.d        t4,      sp,      64

   /* line 0 ~ 7  */
    DCT32_8_LINE_1
    /* line 8 ~ 15  */
    DCT32_8_LINE_1
    /* line 16 ~ 23  */
    DCT32_8_LINE_1
    /* line 24 ~ 31  */
    DCT32_8_LINE_1

    /*
     * The second butterfly operation.
     */
    addi.d        t2,      a1,      0
    addi.d        a3,      sp,      64 + 12 * 32

    /* line 0 ~ 7  */
    DCT32_8_LINE_2
    /* line 8 ~ 15  */
    DCT32_8_LINE_2
    /* line 16 ~ 23  */
    DCT32_8_LINE_2
    /* line 24 ~ 31  */
    DCT32_8_LINE_2

    fld.d         f24,   sp,   0
    fld.d         f25,   sp,   8
    fld.d         f26,   sp,   16
    fld.d         f27,   sp,   24
    fld.d         f28,   sp,   32
    fld.d         f29,   sp,   40
    fld.d         f30,   sp,   48
    fld.d         f31,   sp,   56
    addi.d        sp,    sp,   1248
    addi.d        sp,    sp,   1248
endfunc

.macro IDCT4_4_LINE
    vmul.w        vr4,     vr1,     vr9
    vmul.w        vr6,     vr0,     vr8
    vmul.w        vr5,     vr1,     vr10
    vmul.w        vr7,     vr0,     vr8
    vmadd.w       vr4,     vr3,     vr10
    vmadd.w       vr6,     vr2,     vr8
    vadd.w        vr16,    vr6,     vr4
    vsub.w        vr19,    vr6,     vr4

    vmadd.w       vr5,     vr3,     vr12
    vmadd.w       vr7,     vr2,     vr11
    vadd.w        vr17,    vr7,     vr5
    vsub.w        vr18,    vr7,     vr5
    LSX_TRANSPOSE4x4_W_EXTRA vr16, vr17, vr18, vr19, vr0, vr1, vr2, vr3
.endm

/* void x265_idct4_lsx(const int16_t* src, int16_t* dst, intptr_t dstStride) */
function x265_idct4_lsx
    la.local      t1,      table_dct16
    slli.d        a3,      a2,     1  //stride
    vldi          vr8,     0x840               // 64 g_t4[0][0] g_t4[0][1] g_t4[2][0]
    vldi          vr9,     0x853               // 83 g_t4[1][0]
    vldi          vr10,    0x824               // 36 g_t4[1][1] g_t4[3][0]
    vldrepl.w     vr11,    t1,     256 * 2 + 4 // -64 g_t4[2][1]
    vldrepl.w     vr12,    t1,     256 * 3 + 4

    /*
     * The first butterfly operation.
     */
    vld           vr4,     a0,     0    //line01
    vld           vr5,     a0,     16   //line23

    vsllwil.w.h   vr0,     vr4,    0
    vexth.w.h     vr1,     vr4
    vsllwil.w.h   vr2,     vr5,    0
    vexth.w.h     vr3,     vr5

    IDCT4_4_LINE

    vsrari.w      vr0,     vr0,    7
    vsrari.w      vr1,     vr1,    7
    vsrari.w      vr2,     vr2,    7
    vsrari.w      vr3,     vr3,    7

    /*
     * The second butterfly operation.
     */
    IDCT4_4_LINE

    vssrarni.h.w  vr1,     vr0,    12
    vssrarni.h.w  vr3,     vr2,    12

    vstelm.d      vr1,     a1,     0,   0
    add.d         a1,      a1,     a3
    vstelm.d      vr1,     a1,     0,   1
    add.d         a1,      a1,     a3
    vstelm.d      vr3,     a1,     0,   0
    add.d         a1,      a1,     a3
    vstelm.d      vr3,     a1,     0,   1
endfunc

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 4 outputs)
 * temp reg: _temp0 ~ _temp3
 */
.macro LSX_CAL_IDCT_4_ELE_4 _rin, _in0, _in1, _in2, _in3, \
                            _in4, _in5, _in6, _in7, _out0, _out1, _out2, _out3, \
                            _temp0, _temp1, _temp2, _temp3, \
                            _si0, _si1, _si2, _si3
    vldrepl.w     \_temp0, \_rin,    \_si0
    vldrepl.w     \_temp1, \_rin,    \_si1
    vldrepl.w     \_temp2, \_rin,    \_si2
    vldrepl.w     \_temp3, \_rin,    \_si3
    vmul.w        \_out0,  \_in0,    \_temp0
    vmul.w        \_out1,  \_in4,    \_temp0
    vmadd.w       \_out0,  \_in1,    \_temp1
    vmadd.w       \_out1,  \_in5,    \_temp1
    vmadd.w       \_out0,  \_in2,    \_temp2
    vmadd.w       \_out1,  \_in6,    \_temp2
    vmadd.w       \_out0,  \_in3,    \_temp3
    vmadd.w       \_out1,  \_in7,    \_temp3

    vmul.w        \_out2,  \_in0,    \_temp3
    vmul.w        \_out3,  \_in4,    \_temp3
    vmsub.w       \_out2,  \_in1,    \_temp2
    vmsub.w       \_out3,  \_in5,    \_temp2
    vmadd.w       \_out2,  \_in2,    \_temp1
    vmadd.w       \_out3,  \_in6,    \_temp1
    vmsub.w       \_out2,  \_in3,    \_temp0
    vmsub.w       \_out3,  \_in7,    \_temp0
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 4 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: _temp0 ~ _temp3
 */
.macro LSX_CAL_IDCT_4_ELE_4X _rin, _in0, _in1, _in2, _in3, \
                             _in4, _in5, _in6, _in7, _out0, _out1, _out2, _out3, \
                             _temp0, _temp1, _temp2, _temp3, \
                             _si0, _si1, _si2, _si3
    vldrepl.w     \_temp0, \_rin,    \_si0
    vldrepl.w     \_temp1, \_rin,    \_si1
    vldrepl.w     \_temp2, \_rin,    \_si2
    vldrepl.w     \_temp3, \_rin,    \_si3
    vmul.w        \_out0,  \_in0,    \_temp0
    vmul.w        \_out1,  \_in4,    \_temp0
    vmadd.w       \_out0,  \_in1,    \_temp1
    vmadd.w       \_out1,  \_in5,    \_temp1
    vmadd.w       \_out0,  \_in2,    \_temp2
    vmadd.w       \_out1,  \_in6,    \_temp2
    vmadd.w       \_out0,  \_in3,    \_temp3
    vmadd.w       \_out1,  \_in7,    \_temp3

    vmul.w        \_out2,  \_in3,    \_temp0
    vmul.w        \_out3,  \_in7,    \_temp0
    vmsub.w       \_out2,  \_in2,    \_temp1
    vmsub.w       \_out3,  \_in6,    \_temp1
    vmadd.w       \_out2,  \_in1,    \_temp2
    vmadd.w       \_out3,  \_in5,    \_temp2
    vmsub.w       \_out2,  \_in0,    \_temp3
    vmsub.w       \_out3,  \_in4,    \_temp3
.endm

.macro IDCT8_8_LINE
    /* O[0...3] */
    vldrepl.w     vr24,    t1,      128 * 1
    vldrepl.w     vr25,    t1,      128 * 1 + 4
    vldrepl.w     vr26,    t1,      128 * 1 + 8
    vldrepl.w     vr27,    t1,      128 * 1 + 12
    vldrepl.w     vr29,    t1,      128 * 3 + 4
    vldrepl.w     vr30,    t1,      128 * 3 + 8
    vldrepl.w     vr31,    t1,      128 * 3 + 12

    vmul.w        vr16,    vr1,     vr24
    vmul.w        vr17,    vr9,     vr24
    vmul.w        vr18,    vr1,     vr25
    vmul.w        vr19,    vr9,     vr25
    vmul.w        vr20,    vr1,     vr26
    vmul.w        vr21,    vr9,     vr26
    vmul.w        vr22,    vr1,     vr27
    vmul.w        vr23,    vr9,     vr27

    vmadd.w       vr16,    vr3,     vr25
    vmadd.w       vr17,    vr11,    vr25
    vmadd.w       vr18,    vr3,     vr29
    vmadd.w       vr19,    vr11,    vr29
    vmadd.w       vr20,    vr3,     vr30
    vmadd.w       vr21,    vr11,    vr30
    vmadd.w       vr22,    vr3,     vr31
    vmadd.w       vr23,    vr11,    vr31

    vmadd.w       vr16,    vr5,     vr26
    vmadd.w       vr17,    vr13,    vr26
    vmadd.w       vr18,    vr5,     vr30
    vmadd.w       vr19,    vr13,    vr30
    vmadd.w       vr20,    vr5,     vr27
    vmadd.w       vr21,    vr13,    vr27
    vmadd.w       vr22,    vr5,     vr25
    vmadd.w       vr23,    vr13,    vr25

    vmadd.w       vr16,    vr7,     vr27
    vmadd.w       vr17,    vr15,    vr27
    vmadd.w       vr18,    vr7,     vr31
    vmadd.w       vr19,    vr15,    vr31
    vmadd.w       vr20,    vr7,     vr25
    vmadd.w       vr21,    vr15,    vr25
    vmadd.w       vr22,    vr7,     vr30
    vmadd.w       vr23,    vr15,    vr30

    /* EE */
    vldrepl.w     vr24,   t1,      0
    vldrepl.w     vr25,   t1,      128 * 2
    vldrepl.w     vr26,   t1,      128 * 2 + 4
    vldrepl.w     vr27,   t1,      128 * 4 + 4
    vldrepl.w     vr29,   t1,      128 * 6 + 4
    vmul.w        vr1,     vr0,    vr24
    vmul.w        vr3,     vr8,    vr24
    vmul.w        vr5,     vr0,    vr24
    vmul.w        vr7,     vr8,    vr24
    vmadd.w       vr1,     vr4,    vr24
    vmadd.w       vr3,     vr12,   vr24  // EE[0]
    vmadd.w       vr5,     vr4,    vr27
    vmadd.w       vr7,     vr12,   vr27  // EE[1]

    /* EO */
    vmul.w        vr9,     vr2,    vr25
    vmadd.w       vr9,     vr6,    vr26
    vmul.w        vr11,    vr10,   vr25
    vmadd.w       vr11,    vr14,   vr26  // EO[0]
    vmul.w        vr13,    vr2,    vr26
    vmadd.w       vr13,    vr6,    vr29
    vmul.w        vr15,    vr10,   vr26
    vmadd.w       vr15,    vr14,   vr29  // EO[1]

    /* E */
    vadd.w        vr0,     vr1,     vr9
    vadd.w        vr2,     vr3,     vr11  //E[0]
    vsub.w        vr4,     vr1,     vr9
    vsub.w        vr6,     vr3,     vr11  //E[3]
    vadd.w        vr8,     vr5,     vr13
    vadd.w        vr10,    vr7,     vr15  //E[1]
    vsub.w        vr12,    vr5,     vr13
    vsub.w        vr14,    vr7,     vr15  //E[2]

    /* dst */
    vadd.w        vr9,     vr0,     vr16
    vadd.w        vr25,    vr2,     vr17  //dst[0]
    vsub.w        vr26,    vr0,     vr16
    vsub.w        vr27,    vr2,     vr17  //dst[7]
    vadd.w        vr11,    vr8,     vr18
    vadd.w        vr16,    vr10,    vr19  //dst[1]
    vsub.w        vr24,    vr8,     vr18
    vsub.w        vr17,    vr10,    vr19  //dst[6]
    vadd.w        vr8,     vr12,    vr20
    vadd.w        vr18,    vr14,    vr21  //dst[2]
    vsub.w        vr20,    vr12,    vr20
    vsub.w        vr19,    vr14,    vr21  //dst[5]
    vadd.w        vr10,    vr4,     vr22
    vadd.w        vr21,    vr6,     vr23  //dst[3]
    vsub.w        vr22,    vr4,     vr22
    vsub.w        vr23,    vr6,     vr23  //dst[4]
.endm

/* void x265_idct8_lsx(const int16_t* src, int16_t* dst, intptr_t dstStride) */
function x265_idct8_lsx
    addi.d        sp,      sp,      -56
    fst.d         f24,     sp,      0
    fst.d         f25,     sp,      8
    fst.d         f26,     sp,      16
    fst.d         f27,     sp,      24
    fst.d         f29,     sp,      32
    fst.d         f30,     sp,      40
    fst.d         f31,     sp,      48
    la.local      t1,      table_dct16
    slli.d        a3,      a2,      1  //stride

    /*
     * The first butterfly operation.
     */
    vld           vr8,     a0,     0    //line0
    vld           vr9,     a0,     16   //line1
    vld           vr10,    a0,     32   //line2
    vld           vr11,    a0,     48   //line3
    vld           vr12,    a0,     64   //line4
    vld           vr13,    a0,     80   //line5
    vld           vr14,    a0,     96   //line6
    vld           vr15,    a0,     112  //line7
    vsllwil.w.h   vr0,     vr8,    0
    vsllwil.w.h   vr1,     vr9,    0
    vsllwil.w.h   vr2,     vr10,   0
    vsllwil.w.h   vr3,     vr11,   0
    vsllwil.w.h   vr4,     vr12,   0
    vsllwil.w.h   vr5,     vr13,   0
    vsllwil.w.h   vr6,     vr14,   0
    vsllwil.w.h   vr7,     vr15,   0
    vexth.w.h     vr8,     vr8
    vexth.w.h     vr9,     vr9
    vexth.w.h     vr10,    vr10
    vexth.w.h     vr11,    vr11
    vexth.w.h     vr12,    vr12
    vexth.w.h     vr13,    vr13
    vexth.w.h     vr14,    vr14
    vexth.w.h     vr15,    vr15

    IDCT8_8_LINE

    vsrari.w      vr9,     vr9,    7
    vsrari.w      vr25,    vr25,   7
    vsrari.w      vr26,    vr26,   7
    vsrari.w      vr27,    vr27,   7
    vsrari.w      vr11,    vr11,   7
    vsrari.w      vr16,    vr16,   7
    vsrari.w      vr24,    vr24,   7
    vsrari.w      vr17,    vr17,   7
    vsrari.w      vr8,     vr8,    7
    vsrari.w      vr18,    vr18,   7
    vsrari.w      vr20,    vr20,   7
    vsrari.w      vr19,    vr19,   7
    vsrari.w      vr10,    vr10,   7
    vsrari.w      vr21,    vr21,   7
    vsrari.w      vr22,    vr22,   7
    vsrari.w      vr23,    vr23,   7
    LSX_TRANSPOSE4x4_W_EXTRA vr9, vr11, vr8, vr10, vr0, vr1, vr2, vr3
    LSX_TRANSPOSE4x4_W_EXTRA vr22, vr20, vr24, vr26, vr8, vr9, vr10, vr11
    LSX_TRANSPOSE4x4_W_EXTRA vr25, vr16, vr18, vr21, vr4, vr5, vr6, vr7
    LSX_TRANSPOSE4x4_W_EXTRA vr23, vr19, vr17, vr27, vr12, vr13, vr14, vr15

    /*
     * The second butterfly operation.
     */
    IDCT8_8_LINE

    vssrarni.h.w  vr25,    vr9,    12
    vssrarni.h.w  vr27,    vr26,   12
    vssrarni.h.w  vr16,    vr11,   12
    vssrarni.h.w  vr17,    vr24,   12
    vssrarni.h.w  vr18,    vr8,    12
    vssrarni.h.w  vr19,    vr20,   12
    vssrarni.h.w  vr21,    vr10,   12
    vssrarni.h.w  vr23,    vr22,   12

    LSX_TRANSPOSE8x8_H vr25, vr16, vr18, vr21, vr23, vr19, vr17, vr27, \
                       vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                       vr9, vr26, vr11, vr24, vr8, vr20, vr10, vr22

    vst           vr0,     a1,     0
    vstx          vr1,     a1,     a3
    alsl.d        a1,      a3,     a1,  1
    vst           vr2,     a1,     0
    vstx          vr3,     a1,     a3
    alsl.d        a1,      a3,     a1,  1
    vst           vr4,     a1,     0
    vstx          vr5,     a1,     a3
    alsl.d        a1,      a3,     a1,  1
    vst           vr6,     a1,     0
    vstx          vr7,     a1,     a3
    alsl.d        a1,      a3,     a1,  1

    fld.d         f24,   sp,   0
    fld.d         f25,   sp,   8
    fld.d         f26,   sp,   16
    fld.d         f27,   sp,   24
    fld.d         f29,   sp,   32
    fld.d         f30,   sp,   40
    fld.d         f31,   sp,   48
    addi.d        sp,    sp,   56
endfunc

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 4 outputs)
 * temp reg: _tmp0 ~ _tmp7
 */
.macro LSX_CAL_IDCT_8_ELE_4 _rin, _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                            _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15, \
                            _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7, \
                            _out0, _out1, _out2, _out3, \
                            _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7
    vldrepl.w     \_tmp0,  \_rin,    \_si0
    vldrepl.w     \_tmp1,  \_rin,    \_si1
    vldrepl.w     \_tmp2,  \_rin,    \_si2
    vldrepl.w     \_tmp3,  \_rin,    \_si3
    vldrepl.w     \_tmp4,  \_rin,    \_si4
    vldrepl.w     \_tmp5,  \_rin,    \_si5
    vldrepl.w     \_tmp6,  \_rin,    \_si6
    vldrepl.w     \_tmp7,  \_rin,    \_si7
    vmul.w        \_out0,  \_in0,    \_tmp0
    vmul.w        \_out1,  \_in8,    \_tmp0
    vmul.w        \_out2,  \_in0,    \_tmp7
    vmul.w        \_out3,  \_in8,    \_tmp7
    vmadd.w       \_out0,  \_in1,    \_tmp1
    vmadd.w       \_out1,  \_in9,    \_tmp1
    vmsub.w       \_out2,  \_in1,    \_tmp6
    vmsub.w       \_out3,  \_in9,    \_tmp6
    vmadd.w       \_out0,  \_in2,    \_tmp2
    vmadd.w       \_out1,  \_in10,   \_tmp2
    vmadd.w       \_out2,  \_in2,    \_tmp5
    vmadd.w       \_out3,  \_in10,   \_tmp5
    vmadd.w       \_out0,  \_in3,    \_tmp3
    vmadd.w       \_out1,  \_in11,   \_tmp3
    vmsub.w       \_out2,  \_in3,    \_tmp4
    vmsub.w       \_out3,  \_in11,   \_tmp4
    vmadd.w       \_out0,  \_in4,    \_tmp4
    vmadd.w       \_out1,  \_in12,   \_tmp4
    vmadd.w       \_out2,  \_in4,    \_tmp3
    vmadd.w       \_out3,  \_in12,   \_tmp3
    vmadd.w       \_out0,  \_in5,    \_tmp5
    vmadd.w       \_out1,  \_in13,   \_tmp5
    vmsub.w       \_out2,  \_in5,    \_tmp2
    vmsub.w       \_out3,  \_in13,   \_tmp2
    vmadd.w       \_out0,  \_in6,    \_tmp6
    vmadd.w       \_out1,  \_in14,   \_tmp6
    vmadd.w       \_out2,  \_in6,    \_tmp1
    vmadd.w       \_out3,  \_in14,   \_tmp1
    vmadd.w       \_out0,  \_in7,    \_tmp7
    vmadd.w       \_out1,  \_in15,   \_tmp7
    vmsub.w       \_out2,  \_in7,    \_tmp0
    vmsub.w       \_out3,  \_in15,   \_tmp0
.endm

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 4 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: _tmp0 ~ _tmp7
 */
.macro LSX_CAL_IDCT_8_ELE_4X _rin, _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                             _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15, \
                             _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7, \
                             _out0, _out1, _out2, _out3, \
                             _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7
    vldrepl.w     \_tmp0,  \_rin,    \_si0
    vldrepl.w     \_tmp1,  \_rin,    \_si1
    vldrepl.w     \_tmp2,  \_rin,    \_si2
    vldrepl.w     \_tmp3,  \_rin,    \_si3
    vldrepl.w     \_tmp4,  \_rin,    \_si4
    vldrepl.w     \_tmp5,  \_rin,    \_si5
    vldrepl.w     \_tmp6,  \_rin,    \_si6
    vldrepl.w     \_tmp7,  \_rin,    \_si7
    vmul.w        \_out0,  \_in0,    \_tmp0
    vmul.w        \_out1,  \_in8,    \_tmp0
    vmadd.w       \_out0,  \_in1,    \_tmp1
    vmadd.w       \_out1,  \_in9,    \_tmp1
    vmadd.w       \_out0,  \_in2,    \_tmp2
    vmadd.w       \_out1,  \_in10,   \_tmp2
    vmadd.w       \_out0,  \_in3,    \_tmp3
    vmadd.w       \_out1,  \_in11,   \_tmp3
    vmadd.w       \_out0,  \_in4,    \_tmp4
    vmadd.w       \_out1,  \_in12,   \_tmp4
    vmadd.w       \_out0,  \_in5,    \_tmp5
    vmadd.w       \_out1,  \_in13,   \_tmp5
    vmadd.w       \_out0,  \_in6,    \_tmp6
    vmadd.w       \_out1,  \_in14,   \_tmp6
    vmadd.w       \_out0,  \_in7,    \_tmp7
    vmadd.w       \_out1,  \_in15,   \_tmp7

    vmul.w        \_out2,  \_in7,    \_tmp0
    vmul.w        \_out3,  \_in15,   \_tmp0
    vmsub.w       \_out2,  \_in6,    \_tmp1
    vmsub.w       \_out3,  \_in14,   \_tmp1
    vmadd.w       \_out2,  \_in5,    \_tmp2
    vmadd.w       \_out3,  \_in13,   \_tmp2
    vmsub.w       \_out2,  \_in4,    \_tmp3
    vmsub.w       \_out3,  \_in12,   \_tmp3
    vmadd.w       \_out2,  \_in3,    \_tmp4
    vmadd.w       \_out3,  \_in11,   \_tmp4
    vmsub.w       \_out2,  \_in2,    \_tmp5
    vmsub.w       \_out3,  \_in10,   \_tmp5
    vmadd.w       \_out2,  \_in1,    \_tmp6
    vmadd.w       \_out3,  \_in9,    \_tmp6
    vmsub.w       \_out2,  \_in0,    \_tmp7
    vmsub.w       \_out3,  \_in8,    \_tmp7
.endm

.macro CLA_IDCT16_O
    LSX_CAL_IDCT_8_ELE_4 t1, vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                         vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                         vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                         vr24, vr25, vr26, vr27, \
                         64 * 1, 64 * 3, 64 * 5, 64 * 7, \
                         64 * 9, 64 * 11, 64 * 13, 64 * 15
    LSX_CAL_IDCT_8_ELE_4X t1, vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                          vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                          vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                          vr28, vr29, vr30, vr31, \
                          64 * 1 + 4, 64 * 3 + 4, 64 * 5 + 4, 64 * 7 + 4, \
                          64 * 9 + 4, 64 * 11 + 4, 64 * 13 + 4, 64 * 15 + 4

    vst           vr24,     t4,      0
    vst           vr25,     t4,      16
    vst           vr28,     t4,      16 * 2
    vst           vr29,     t4,      16 * 3
    vst           vr30,     t4,      16 * 12
    vst           vr31,     t4,      16 * 13
    vst           vr26,     t4,      16 * 14
    vst           vr27,     t4,      16 * 15

    LSX_CAL_IDCT_8_ELE_4 t1, vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                         vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                         vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                         vr24, vr25, vr26, vr27, \
                         64 * 1 + 8, 64 * 3 + 8, 64 * 5 + 8, 64 * 7 + 8, \
                         64 * 9 + 8, 64 * 11 + 8, 64 * 13 + 8, 64 * 15 + 8
    LSX_CAL_IDCT_8_ELE_4X t1, vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                          vr8, vr9, vr10, vr11, vr12, vr13, vr14, vr15, \
                          vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, \
                          vr28, vr29, vr30, vr31, \
                          64 * 1 + 12, 64 * 3 + 12, 64 * 5 + 12, 64 * 7 + 12, \
                          64 * 9 + 12, 64 * 11 + 12, 64 * 13 + 12, 64 * 15 + 12

    vst           vr24,     t4,      16 * 4
    vst           vr25,     t4,      16 * 5
    vst           vr28,     t4,      16 * 6
    vst           vr29,     t4,      16 * 7
    vst           vr30,     t4,      16 * 8
    vst           vr31,     t4,      16 * 9
    vst           vr26,     t4,      16 * 10
    vst           vr27,     t4,      16 * 11
.endm

.macro CLA_IDCT16_E
    /* EO[0...3] */
    LSX_CAL_IDCT_4_ELE_4 t1, vr1, vr3, vr5, vr7, vr9, vr11, vr13, vr15, \
                         vr16, vr17, vr22, vr23, vr24, vr25, vr26, vr27, \
                         64 * 2, 64 * 6, 64 * 10, 64 * 14
    LSX_CAL_IDCT_4_ELE_4X t1, vr1, vr3, vr5, vr7, vr9, vr11, vr13, vr15, \
                          vr18, vr19, vr20, vr21, vr24, vr25, vr26, vr27, \
                          64 * 2 + 4, 64 * 6 + 4, 64 * 10 + 4, 64 * 14 + 4

    /* EEE */
    vldrepl.w     vr24,    t1,     0
    vldrepl.w     vr25,    t1,     4
    vldrepl.w     vr26,    t1,     64 * 8
    vldrepl.w     vr27,    t1,     64 * 8 + 4
    vmul.w        vr1,     vr0,    vr24
    vmadd.w       vr1,     vr4,    vr26
    vmul.w        vr3,     vr8,    vr24
    vmadd.w       vr3,     vr12,   vr26  // EEE[0]
    vmul.w        vr5,     vr0,    vr25
    vmadd.w       vr5,     vr4,    vr27
    vmul.w        vr7,     vr8,    vr25
    vmadd.w       vr7,     vr12,   vr27  // EEE[1]

    /* EEO */
    vldrepl.w     vr24,    t1,     64 * 4
    vldrepl.w     vr25,    t1,     64 * 4 + 4
    vldrepl.w     vr26,    t1,     64 * 12
    vldrepl.w     vr27,    t1,     64 * 12 + 4
    vmul.w        vr9,     vr2,    vr24
    vmadd.w       vr9,     vr6,    vr26
    vmul.w        vr11,    vr10,   vr24
    vmadd.w       vr11,    vr14,   vr26  // EEO[0]
    vmul.w        vr13,    vr2,    vr25
    vmadd.w       vr13,    vr6,    vr27
    vmul.w        vr15,    vr10,   vr25
    vmadd.w       vr15,    vr14,   vr27  // EEO[1]

    /* EE */
    vadd.w        vr0,     vr1,     vr9
    vadd.w        vr2,     vr3,     vr11  //EE[0]
    vsub.w        vr4,     vr1,     vr9
    vsub.w        vr6,     vr3,     vr11  //EE[3]
    vadd.w        vr8,     vr5,     vr13
    vadd.w        vr10,    vr7,     vr15  //EE[1]
    vsub.w        vr12,    vr5,     vr13
    vsub.w        vr14,    vr7,     vr15  //EE[2]

    /* E */
    vadd.w        vr24,    vr0,     vr16
    vadd.w        vr25,    vr2,     vr17  //E[0]
    vsub.w        vr26,    vr0,     vr16
    vsub.w        vr27,    vr2,     vr17  //E[7]
    vadd.w        vr28,    vr8,     vr18
    vadd.w        vr29,    vr10,    vr19  //E[1]
    vsub.w        vr30,    vr8,     vr18
    vsub.w        vr31,    vr10,    vr19  //E[6]
    vadd.w        vr16,    vr12,    vr20
    vadd.w        vr17,    vr14,    vr21  //E[2]
    vsub.w        vr18,    vr12,    vr20
    vsub.w        vr19,    vr14,    vr21  //E[5]
    vadd.w        vr20,    vr4,     vr22
    vadd.w        vr21,    vr6,     vr23  //E[3]
    vsub.w        vr22,    vr4,     vr22
    vsub.w        vr23,    vr6,     vr23  //E[4]
.endm

.macro LSX_IDCT16_8_ROW _rin
    vld           vr8,     \_rin,  32   //line1
    vld           vr9,     \_rin,  96   //line3
    vld           vr10,    \_rin,  160  //line5
    vld           vr11,    \_rin,  224  //line7
    vld           vr12,    \_rin,  288  //line9
    vld           vr13,    \_rin,  352  //line11
    vld           vr14,    \_rin,  416  //line13
    vld           vr15,    \_rin,  480  //line15
    vsllwil.w.h   vr0,     vr8,    0
    vsllwil.w.h   vr1,     vr9,    0
    vsllwil.w.h   vr2,     vr10,   0
    vsllwil.w.h   vr3,     vr11,   0
    vsllwil.w.h   vr4,     vr12,   0
    vsllwil.w.h   vr5,     vr13,   0
    vsllwil.w.h   vr6,     vr14,   0
    vsllwil.w.h   vr7,     vr15,   0
    vexth.w.h     vr8,     vr8
    vexth.w.h     vr9,     vr9
    vexth.w.h     vr10,    vr10
    vexth.w.h     vr11,    vr11
    vexth.w.h     vr12,    vr12
    vexth.w.h     vr13,    vr13
    vexth.w.h     vr14,    vr14
    vexth.w.h     vr15,    vr15

    CLA_IDCT16_O

    vld           vr8,     \_rin,  0    //line0
    vld           vr9,     \_rin,  64   //line2
    vld           vr10,    \_rin,  128  //line4
    vld           vr11,    \_rin,  192  //line6
    vld           vr12,    \_rin,  256  //line8
    vld           vr13,    \_rin,  320  //line10
    vld           vr14,    \_rin,  384  //line12
    vld           vr15,    \_rin,  448  //line14
    vsllwil.w.h   vr0,     vr8,    0
    vsllwil.w.h   vr1,     vr9,    0
    vsllwil.w.h   vr2,     vr10,   0
    vsllwil.w.h   vr3,     vr11,   0
    vsllwil.w.h   vr4,     vr12,   0
    vsllwil.w.h   vr5,     vr13,   0
    vsllwil.w.h   vr6,     vr14,   0
    vsllwil.w.h   vr7,     vr15,   0
    vexth.w.h     vr8,     vr8
    vexth.w.h     vr9,     vr9
    vexth.w.h     vr10,    vr10
    vexth.w.h     vr11,    vr11
    vexth.w.h     vr12,    vr12
    vexth.w.h     vr13,    vr13
    vexth.w.h     vr14,    vr14
    vexth.w.h     vr15,    vr15

    CLA_IDCT16_E
.endm

.macro LSX_ST_IDCT16_1 _shift
    /* dst[0...3] dst[12...15] */
    vld           vr4,     t4,     0
    vld           vr5,     t4,     16 * 2
    vld           vr6,     t4,     16 * 4
    vld           vr7,     t4,     16 * 6
    vadd.w        vr8,     vr24,   vr4
    vadd.w        vr9,     vr28,   vr5
    vadd.w        vr10,    vr16,   vr6
    vadd.w        vr11,    vr20,   vr7
    LSX_TRANSPOSE4x4_W_EXTRA vr8, vr9, vr10, vr11, vr0, vr1, vr2, vr3
    vsub.w        vr8,     vr24,   vr4  //dst[15]
    vsub.w        vr9,     vr28,   vr5  //dst[14]
    vsub.w        vr10,    vr16,   vr6  //dst[13]
    vsub.w        vr11,    vr20,   vr7  //dst[12]
    LSX_TRANSPOSE4x4_W_EXTRA vr11, vr10, vr9, vr8, vr12, vr13, vr14, vr15

    /* dst[4...11] */
    vld           vr24,    t4,     16 * 8
    vld           vr28,    t4,     16 * 10
    vld           vr16,    t4,     16 * 12
    vld           vr20,    t4,     16 * 14
    vadd.w        vr8,     vr22,   vr24  //dst[4]
    vadd.w        vr9,     vr18,   vr28  //dst[5]
    vadd.w        vr10,    vr30,   vr16  //dst[6]
    vadd.w        vr11,    vr26,   vr20  //dst[7]
    LSX_TRANSPOSE4x4_W_EXTRA vr8, vr9, vr10, vr11, vr4, vr5, vr6, vr7
    vsub.w        vr8,     vr22,   vr24  //dst[11]
    vsub.w        vr9,     vr18,   vr28  //dst[10]
    vsub.w        vr10,    vr30,   vr16  //dst[9]
    vsub.w        vr11,    vr26,   vr20  //dst[8]
    LSX_TRANSPOSE4x4_W_EXTRA vr11, vr10, vr9, vr8, vr24, vr28, vr16, vr20

    vssrarni.h.w  vr4,     vr0,    \_shift
    vssrarni.h.w  vr5,     vr1,    \_shift
    vssrarni.h.w  vr6,     vr2,    \_shift
    vssrarni.h.w  vr7,     vr3,    \_shift
    vssrarni.h.w  vr12,    vr24,   \_shift
    vssrarni.h.w  vr13,    vr28,   \_shift
    vssrarni.h.w  vr14,    vr16,   \_shift
    vssrarni.h.w  vr15,    vr20,   \_shift
.endm

.macro LSX_ST_IDCT16_2 _shift
    /* dst[0...3] dst[12...15] */
    vld           vr22,    t4,     16
    vld           vr18,    t4,     16 * 3
    vld           vr30,    t4,     16 * 5
    vld           vr26,    t4,     16 * 7
    vadd.w        vr24,    vr25,   vr22
    vadd.w        vr28,    vr29,   vr18
    vadd.w        vr16,    vr17,   vr30
    vadd.w        vr20,    vr21,   vr26
    LSX_TRANSPOSE4x4_W_EXTRA vr24, vr28, vr16, vr20, vr0, vr1, vr2, vr3
    vsub.w        vr24,    vr25,   vr22  //dst[15]
    vsub.w        vr28,    vr29,   vr18  //dst[14]
    vsub.w        vr16,    vr17,   vr30  //dst[13]
    vsub.w        vr20,    vr21,   vr26  //dst[12]
    LSX_TRANSPOSE4x4_W_EXTRA vr20, vr16, vr28, vr24, vr12, vr13, vr14, vr15

    /* dst[4...11] */
    vld           vr22,    t4,     16 * 9
    vld           vr18,    t4,     16 * 11
    vld           vr30,    t4,     16 * 13
    vld           vr26,    t4,     16 * 15
    vadd.w        vr24,    vr23,   vr22
    vadd.w        vr28,    vr19,   vr18
    vadd.w        vr16,    vr31,   vr30
    vadd.w        vr20,    vr27,   vr26
    LSX_TRANSPOSE4x4_W_EXTRA vr24, vr28, vr16, vr20, vr4, vr5, vr6, vr7
    vsub.w        vr24,    vr23,   vr22 //dst[11]
    vsub.w        vr28,    vr19,   vr18 //dst[10]
    vsub.w        vr16,    vr31,   vr30 //dst[9]
    vsub.w        vr20,    vr27,   vr26 //dst[8]
    LSX_TRANSPOSE4x4_W_EXTRA vr20, vr16, vr28, vr24, vr22, vr18, vr30, vr26

    vssrarni.h.w  vr4,     vr0,    \_shift
    vssrarni.h.w  vr5,     vr1,    \_shift
    vssrarni.h.w  vr6,     vr2,    \_shift
    vssrarni.h.w  vr7,     vr3,    \_shift
    vssrarni.h.w  vr12,    vr22,   \_shift
    vssrarni.h.w  vr13,    vr18,   \_shift
    vssrarni.h.w  vr14,    vr30,   \_shift
    vssrarni.h.w  vr15,    vr26,   \_shift
.endm

/* void x265_idct16_lsx(const int16_t* src, int16_t* dst, intptr_t dstStride) */
function x265_idct16_lsx
    addi.d        sp,      sp,      -832 //-(64 + 16*16 + 16 *16*2) si12 Immediate overflow
    fst.d         f24,     sp,      0
    fst.d         f25,     sp,      8
    fst.d         f26,     sp,      16
    fst.d         f27,     sp,      24
    fst.d         f28,     sp,      32
    fst.d         f29,     sp,      40
    fst.d         f30,     sp,      48
    fst.d         f31,     sp,      56
    la.local      t1,      table_dct16
    slli.d        a3,      a2,      1  //stride

    /*
     * The first butterfly operation.
     */
    addi.d        t4,      sp,      64
    addi.d        t2,      t4,      256

    LSX_IDCT16_8_ROW a0
    LSX_ST_IDCT16_1  7
    vst           vr4,     t2,     0
    vst           vr12,    t2,     16
    vst           vr5,     t2,     32
    vst           vr13,    t2,     48
    vst           vr6,     t2,     64
    vst           vr14,    t2,     80
    vst           vr7,     t2,     96
    vst           vr15,    t2,     112
    LSX_ST_IDCT16_2  7
    vst           vr4,     t2,     128
    vst           vr12,    t2,     144
    vst           vr5,     t2,     160
    vst           vr13,    t2,     176
    vst           vr6,     t2,     192
    vst           vr14,    t2,     208
    vst           vr7,     t2,     224
    vst           vr15,    t2,     240

    addi.d        a0,      a0,     16
    LSX_IDCT16_8_ROW a0
    LSX_ST_IDCT16_1  7
    vst           vr4,     t2,     256
    vst           vr12,    t2,     272
    vst           vr5,     t2,     288
    vst           vr13,    t2,     304
    vst           vr6,     t2,     320
    vst           vr14,    t2,     336
    vst           vr7,     t2,     352
    vst           vr15,    t2,     368
    LSX_ST_IDCT16_2  7
    vst           vr4,     t2,     384
    vst           vr12,    t2,     400
    vst           vr5,     t2,     416
    vst           vr13,    t2,     432
    vst           vr6,     t2,     448
    vst           vr14,    t2,     464
    vst           vr7,     t2,     480
    vst           vr15,    t2,     496

    /*
     * The second butterfly operation.
     */
    LSX_IDCT16_8_ROW t2
    LSX_ST_IDCT16_1  12
    vst           vr4,     a1,     0
    vst           vr12,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr5,     a1,     0
    vst           vr13,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr6,     a1,     0
    vst           vr14,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr7,     a1,     0
    vst           vr15,    a1,     16
    add.d         a1,      a1,     a3
    LSX_ST_IDCT16_2  12
    vst           vr4,     a1,     0
    vst           vr12,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr5,     a1,     0
    vst           vr13,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr6,     a1,     0
    vst           vr14,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr7,     a1,     0
    vst           vr15,    a1,     16
    add.d         a1,      a1,     a3

    addi.d        t2,      t2,     16
    LSX_IDCT16_8_ROW t2
    LSX_ST_IDCT16_1  12
    vst           vr4,     a1,     0
    vst           vr12,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr5,     a1,     0
    vst           vr13,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr6,     a1,     0
    vst           vr14,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr7,     a1,     0
    vst           vr15,    a1,     16
    add.d         a1,      a1,     a3
    LSX_ST_IDCT16_2  12
    vst           vr4,     a1,     0
    vst           vr12,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr5,     a1,     0
    vst           vr13,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr6,     a1,     0
    vst           vr14,    a1,     16
    add.d         a1,      a1,     a3
    vst           vr7,     a1,     0
    vst           vr15,    a1,     16

    fld.d         f24,   sp,   0
    fld.d         f25,   sp,   8
    fld.d         f26,   sp,   16
    fld.d         f27,   sp,   24
    fld.d         f28,   sp,   32
    fld.d         f29,   sp,   40
    fld.d         f30,   sp,   48
    fld.d         f31,   sp,   56
    addi.d        sp,    sp,   832
endfunc

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * temp reg: _tmp0 ~ _tmp7
 */
.macro LSX_CAL_IDCT_8_ELE_2 _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                            _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7, \
                            _out0, _out1, _si0, _si1, _si2, _si3, \
                            _si4, _si5, _si6, _si7
    vldrepl.w     \_tmp0,  t1,       \_si0
    vldrepl.w     \_tmp1,  t1,       \_si1
    vldrepl.w     \_tmp2,  t1,       \_si2
    vldrepl.w     \_tmp3,  t1,       \_si3
    vldrepl.w     \_tmp4,  t5,       \_si4
    vldrepl.w     \_tmp5,  t5,       \_si5
    vldrepl.w     \_tmp6,  t5,       \_si6
    vldrepl.w     \_tmp7,  t6,       \_si7

    vmul.w        \_out0,  \_in0,    \_tmp0
    vmul.w        \_out1,  \_in0,    \_tmp7
    vmadd.w       \_out0,  \_in1,    \_tmp1
    vmsub.w       \_out1,  \_in1,    \_tmp6
    vmadd.w       \_out0,  \_in2,    \_tmp2
    vmadd.w       \_out1,  \_in2,    \_tmp5
    vmadd.w       \_out0,  \_in3,    \_tmp3
    vmsub.w       \_out1,  \_in3,    \_tmp4
    vmadd.w       \_out0,  \_in4,    \_tmp4
    vmadd.w       \_out1,  \_in4,    \_tmp3
    vmadd.w       \_out0,  \_in5,    \_tmp5
    vmsub.w       \_out1,  \_in5,    \_tmp2
    vmadd.w       \_out0,  \_in6,    \_tmp6
    vmadd.w       \_out1,  \_in6,    \_tmp1
    vmadd.w       \_out0,  \_in7,    \_tmp7
    vmsub.w       \_out1,  \_in7,    \_tmp0
.endm

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: _tmp0 ~ _tmp7
 */
.macro LSX_CAL_IDCT_8_ELE_2X _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                             _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7, \
                             _out0, _out1, _si0, _si1, _si2, _si3, \
                             _si4, _si5, _si6, _si7
    vldrepl.w     \_tmp0,  t1,       \_si0
    vldrepl.w     \_tmp1,  t1,       \_si1
    vldrepl.w     \_tmp2,  t1,       \_si2
    vldrepl.w     \_tmp3,  t1,       \_si3
    vldrepl.w     \_tmp4,  t5,       \_si4
    vldrepl.w     \_tmp5,  t5,       \_si5
    vldrepl.w     \_tmp6,  t5,       \_si6
    vldrepl.w     \_tmp7,  t6,       \_si7

    vmul.w       \_out0,  \_in0,     \_tmp0
    vmul.w       \_out1,  \_in7,     \_tmp0
    vmadd.w      \_out0,  \_in1,     \_tmp1
    vmsub.w      \_out1,  \_in6,     \_tmp1
    vmadd.w      \_out0,  \_in2,     \_tmp2
    vmadd.w      \_out1,  \_in5,     \_tmp2
    vmadd.w      \_out0,  \_in3,     \_tmp3
    vmsub.w      \_out1,  \_in4,     \_tmp3
    vmadd.w      \_out0,  \_in4,     \_tmp4
    vmadd.w      \_out1,  \_in3,     \_tmp4
    vmadd.w      \_out0,  \_in5,     \_tmp5
    vmsub.w      \_out1,  \_in2,     \_tmp5
    vmadd.w      \_out0,  \_in6,     \_tmp6
    vmadd.w      \_out1,  \_in1,     \_tmp6
    vmadd.w      \_out0,  \_in7,     \_tmp7
    vmsub.w      \_out1,  \_in0,     \_tmp7
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * temp reg: _temp0 ~ _temp3
 */
.macro LSX_CAL_IDCT_4_ELE_2 _in0, _in1, _in2, _in3, \
                            _tmp0, _tmp1, _tmp2, _tmp3, _out0, _out1\
                            _si0, _si1, _si2, _si3
    vldrepl.w    \_tmp0,  t1,        \_si0
    vldrepl.w    \_tmp1,  t1,        \_si1
    vldrepl.w    \_tmp2,  t5,        \_si2
    vldrepl.w    \_tmp3,  t5,        \_si3

    vmul.w       \_out0,  \_in0,     \_tmp0
    vmul.w       \_out1,  \_in0,     \_tmp3
    vmadd.w      \_out0,  \_in1,     \_tmp1
    vmsub.w      \_out1,  \_in1,     \_tmp2
    vmadd.w      \_out0,  \_in2,     \_tmp2
    vmadd.w      \_out1,  \_in2,     \_tmp1
    vmadd.w      \_out0,  \_in3,     \_tmp3
    vmsub.w      \_out1,  \_in3,     \_tmp0
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: _temp0 ~ _temp3
 */
.macro LSX_CAL_IDCT_4_ELE_2X _in0, _in1, _in2, _in3, \
                             _tmp0, _tmp1, _tmp2, _tmp3, _out0, _out1\
                             _si0, _si1, _si2, _si3
    vldrepl.w    \_tmp0,  t1,       \_si0
    vldrepl.w    \_tmp1,  t1,       \_si1
    vldrepl.w    \_tmp2,  t5,       \_si2
    vldrepl.w    \_tmp3,  t5,       \_si3
    vmul.w       \_out0,  \_in0,     \_tmp0
    vmul.w       \_out1,  \_in3,     \_tmp0
    vmadd.w      \_out0,  \_in1,     \_tmp1
    vmsub.w      \_out1,  \_in2,     \_tmp1
    vmadd.w      \_out0,  \_in2,     \_tmp2
    vmadd.w      \_out1,  \_in1,     \_tmp2
    vmadd.w      \_out0,  \_in3,     \_tmp3
    vmsub.w      \_out1,  \_in0,     \_tmp3
.endm

.macro CLA_IDCT32_EO
    LSX_CAL_IDCT_8_ELE_2 vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                         vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, vr8, vr15, \
                         128 * 2, 128 * 6, 128 * 10, 128 * 14, \
                         128 * 3, 128 * 7, 128 * 11, 0
    LSX_CAL_IDCT_8_ELE_2X vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                          vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, vr9, vr14, \
                          128 * 2 + 4, 128 * 6 + 4, 128 * 10 + 4, 128 * 14 + 4, \
                          128 * 3 + 4, 128 * 7 + 4, 128 * 11 + 4, 4
    LSX_CAL_IDCT_8_ELE_2 vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                         vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, vr10, vr13, \
                         128 * 2 + 8, 128 * 6 + 8, 128 * 10 + 8, 128 * 14 + 8, \
                         128 * 3 + 8, 128 * 7 + 8, 128 * 11 + 8, 8
    LSX_CAL_IDCT_8_ELE_2X vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, \
                          vr16, vr17, vr18, vr19, vr20, vr21, vr22, vr23, vr11, vr12, \
                          128 * 2 + 12, 128 * 6 + 12, 128 * 10 + 12, 128 * 14 + 12, \
                          128 * 3 + 12, 128 * 7 + 12, 128 * 11 + 12, 12
.endm

.macro CLA_IDCT32_EE
    /* EEO[0...3] */
    LSX_CAL_IDCT_4_ELE_2 vr1, vr3, vr5, vr7, vr20, vr21, vr22, vr23, vr16, vr19, \
                         128 * 4, 128 * 12, 128 * 5, 128 * 13
    LSX_CAL_IDCT_4_ELE_2X vr1, vr3, vr5, vr7, vr20, vr21, vr22, vr23, vr17, vr18, \
                          128 * 4 + 4, 128 * 12 + 4, 128 * 5 + 4, 128 * 13 + 4

    /* EEEE */
    vldrepl.w     vr1,    t1,     0
    vmul.w        vr20,   vr0,    vr1
    vmadd.w       vr20,   vr4,    vr1  // EEEE[0]
    vmul.w        vr21,   vr0,    vr1
    vmsub.w       vr21,   vr4,    vr1  // EEEE[1]

    /* EEEO */
    vldrepl.w     vr1,    t1,     128 * 8
    vldrepl.w     vr5,    t1,     128 * 8 + 4
    vmul.w        vr22,    vr2,    vr1
    vmadd.w       vr22,    vr6,    vr5  // EEEO[0]
    vmul.w        vr23,    vr2,    vr5
    vmsub.w       vr23,    vr6,    vr1  // EEEO[1]

    /* EEE */
    vadd.w        vr4,     vr20,     vr22 // EEE[0]
    vsub.w        vr7,     vr20,     vr22 // EEE[3]
    vadd.w        vr5,     vr21,     vr23 // EEE[1]
    vsub.w        vr6,     vr21,     vr23 // EEE[2]

    /* EE*/
    vadd.w        vr0,     vr4,      vr16 //EE[0]
    vsub.w        vr23,    vr4,      vr16 //EE[7]
    vadd.w        vr1,     vr5,      vr17 //EE[1]
    vsub.w        vr22,    vr5,      vr17 //EE[6]
    vadd.w        vr2,     vr6,      vr18 //EE[2]
    vsub.w        vr21,    vr6,      vr18 //EE[5]
    vadd.w        vr3,     vr7,      vr19 //EE[3]
    vsub.w        vr20,    vr7,      vr19 //EE[4]
.endm

/*
 * Description : Multiplication and addition calculation of 16 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * in reg: vr0 ~ vr15
 * temp reg: _temp0 ~ _temp3
 */
.macro LSX_CAL_IDCT_16_ELE_2 _out0, _out1, _temp0, _temp1, _temp2, _temp3, \
                             _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7, \
                             _si8, _si9, _si10, _si11, _si12, _si13, _si14, _si15
    vldrepl.w     \_temp0, t1,       \_si0
    vldrepl.w     \_temp1, t1,       \_si1
    vldrepl.w     \_temp2, t1,       \_si2
    vldrepl.w     \_temp3, t1,       \_si3
    vmul.w        \_out0,  vr0,      \_temp0
    vmul.w        \_out1,  vr12,     \_temp3
    vmadd.w       \_out0,  vr1,      \_temp1
    vmsub.w       \_out1,  vr13,     \_temp2
    vmadd.w       \_out0,  vr2,      \_temp2
    vmadd.w       \_out1,  vr14,     \_temp1
    vmadd.w       \_out0,  vr3,      \_temp3
    vmsub.w       \_out1,  vr15,     \_temp0

    vldrepl.w     \_temp0, t1,       \_si4
    vldrepl.w     \_temp1, t1,       \_si5
    vldrepl.w     \_temp2, t1,       \_si6
    vldrepl.w     \_temp3, t5,       \_si7
    vmadd.w       \_out0,  vr4,      \_temp0
    vmadd.w       \_out1,  vr8,      \_temp3
    vmadd.w       \_out0,  vr5,      \_temp1
    vmsub.w       \_out1,  vr9,      \_temp2
    vmadd.w       \_out0,  vr6,      \_temp2
    vmadd.w       \_out1,  vr10,     \_temp1
    vmadd.w       \_out0,  vr7,      \_temp3
    vmsub.w       \_out1,  vr11,     \_temp0

    vldrepl.w     \_temp0, t5,       \_si8
    vldrepl.w     \_temp1, t5,       \_si9
    vldrepl.w     \_temp2, t5,       \_si10
    vldrepl.w     \_temp3, t5,       \_si11
    vmadd.w       \_out0,  vr8,      \_temp0
    vmadd.w       \_out1,  vr4,      \_temp3
    vmadd.w       \_out0,  vr9,      \_temp1
    vmsub.w       \_out1,  vr5,      \_temp2
    vmadd.w       \_out0,  vr10,     \_temp2
    vmadd.w       \_out1,  vr6,      \_temp1
    vmadd.w       \_out0,  vr11,     \_temp3
    vmsub.w       \_out1,  vr7,      \_temp0

    vldrepl.w     \_temp0, t5,       \_si12
    vldrepl.w     \_temp1, t5,       \_si13
    vldrepl.w     \_temp2, t5,       \_si14
    vldrepl.w     \_temp3, t6,       \_si15
    vmadd.w       \_out0,  vr12,     \_temp0
    vmadd.w       \_out1,  vr0,      \_temp3
    vmadd.w       \_out0,  vr13,     \_temp1
    vmsub.w       \_out1,  vr1,      \_temp2
    vmadd.w       \_out0,  vr14,     \_temp2
    vmadd.w       \_out1,  vr2,      \_temp1
    vmadd.w       \_out0,  vr15,     \_temp3
    vmsub.w       \_out1,  vr3,      \_temp0
.endm

/*
 * Description : Multiplication and addition calculation of 16 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * in reg: vr0 ~ vr15
 * temp reg: _temp0 ~ _temp3
 */
.macro LSX_CAL_IDCT_16_ELE_2X _out0, _out1, _temp0, _temp1, _temp2, _temp3, \
                              _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7, \
                              _si8, _si9, _si10, _si11, _si12, _si13, _si14, _si15
    vldrepl.w     \_temp0, t1,       \_si0
    vldrepl.w     \_temp1, t1,       \_si1
    vldrepl.w     \_temp2, t1,       \_si2
    vldrepl.w     \_temp3, t1,       \_si3
    vmul.w        \_out0,  vr0,      \_temp0
    vmul.w        \_out1,  vr15,     \_temp0
    vmadd.w       \_out0,  vr1,      \_temp1
    vmsub.w       \_out1,  vr14,     \_temp1
    vmadd.w       \_out0,  vr2,      \_temp2
    vmadd.w       \_out1,  vr13,     \_temp2
    vmadd.w       \_out0,  vr3,      \_temp3
    vmsub.w       \_out1,  vr12,     \_temp3

    vldrepl.w     \_temp0, t1,       \_si4
    vldrepl.w     \_temp1, t1,       \_si5
    vldrepl.w     \_temp2, t1,       \_si6
    vldrepl.w     \_temp3, t5,       \_si7
    vmadd.w       \_out0,  vr4,      \_temp0
    vmadd.w       \_out1,  vr11,     \_temp0
    vmadd.w       \_out0,  vr5,      \_temp1
    vmsub.w       \_out1,  vr10,     \_temp1
    vmadd.w       \_out0,  vr6,      \_temp2
    vmadd.w       \_out1,  vr9,      \_temp2
    vmadd.w       \_out0,  vr7,      \_temp3
    vmsub.w       \_out1,  vr8,      \_temp3

    vldrepl.w     \_temp0, t5,       \_si8
    vldrepl.w     \_temp1, t5,       \_si9
    vldrepl.w     \_temp2, t5,       \_si10
    vldrepl.w     \_temp3, t5,       \_si11
    vmadd.w       \_out0,  vr8,      \_temp0
    vmadd.w       \_out1,  vr7,      \_temp0
    vmadd.w       \_out0,  vr9,      \_temp1
    vmsub.w       \_out1,  vr6,      \_temp1
    vmadd.w       \_out0,  vr10,     \_temp2
    vmadd.w       \_out1,  vr5,      \_temp2
    vmadd.w       \_out0,  vr11,     \_temp3
    vmsub.w       \_out1,  vr4,      \_temp3

    vldrepl.w     \_temp0, t5,       \_si12
    vldrepl.w     \_temp1, t5,       \_si13
    vldrepl.w     \_temp2, t5,       \_si14
    vldrepl.w     \_temp3, t6,       \_si15
    vmadd.w       \_out0,  vr12,     \_temp0
    vmadd.w       \_out1,  vr3,      \_temp0
    vmadd.w       \_out0,  vr13,     \_temp1
    vmsub.w       \_out1,  vr2,      \_temp1
    vmadd.w       \_out0,  vr14,     \_temp2
    vmadd.w       \_out1,  vr1,      \_temp2
    vmadd.w       \_out0,  vr15,     \_temp3
    vmsub.w       \_out1,  vr0,      \_temp3
.endm

.macro CLA_IDCT32_O
    LSX_CAL_IDCT_16_ELE_2 vr24, vr23, vr16, vr17, vr18, vr19, \
                          128 * 1, 128 * 3, 128 * 5, 128 * 7, \
                          128 * 9, 128 * 11, 128 * 13, 0, \
                          128 * 2, 128 * 4, 128 * 6, 128 * 8, \
                          128 * 10, 128 * 12, 128 * 14, 128 * 1
    LSX_CAL_IDCT_16_ELE_2X vr25, vr22, vr16, vr17, vr18, vr19, \
                           128 * 1 + 4, 128 * 3 + 4, 128 * 5 + 4, 128 * 7 + 4, \
                           128 * 9 + 4, 128 * 11 + 4, 128 * 13 + 4, 4, \
                           128 * 2 + 4, 128 * 4 + 4, 128 * 6 + 4, 128 * 8 + 4, \
                           128 * 10 + 4, 128 * 12 + 4, 128 * 14 + 4, 128 * 1 + 4
    LSX_CAL_IDCT_16_ELE_2 vr26, vr21, vr16, vr17, vr18, vr19, \
                          128 * 1 + 8, 128 * 3 + 8, 128 * 5 + 8, 128 * 7 + 8, \
                          128 * 9 + 8, 128 * 11 + 8, 128 * 13 + 8, 8, \
                          128 * 2 + 8, 128 * 4 + 8, 128 * 6 + 8, 128 * 8 + 8, \
                          128 * 10 + 8, 128 * 12 + 8, 128 * 14 + 8, 128 * 1 + 8
    LSX_CAL_IDCT_16_ELE_2X vr27, vr20, vr16, vr17, vr18, vr19, \
                           128 * 1 + 12, 128 * 3 + 12, 128 * 5 + 12, 128 * 7 + 12, \
                           128 * 9 + 12, 128 * 11 + 12, 128 * 13 + 12, 12, \
                           128 * 2 + 12, 128 * 4 + 12, 128 * 6 + 12, 128 * 8 + 12, \
                           128 * 10 + 12, 128 * 12 + 12, 128 * 14 + 12, 128 * 1 + 12
    vst           vr20,     t4,      16 * 4
    vst           vr21,     t4,      16 * 5
    vst           vr22,     t4,      16 * 6
    vst           vr23,     t4,      16 * 7

    LSX_CAL_IDCT_16_ELE_2 vr28, vr23, vr16, vr17, vr18, vr19, \
                       128 * 1 + 16, 128 * 3 + 16, 128 * 5 + 16, 128 * 7 + 16, \
                       128 * 9 + 16, 128 * 11 + 16, 128 * 13 + 16, 16, \
                       128 * 2 + 16, 128 * 4 + 16, 128 * 6 + 16, 128 * 8 + 16, \
                       128 * 10 + 16, 128 * 12 + 16, 128 * 14 + 16, 128 * 1 + 16
    LSX_CAL_IDCT_16_ELE_2X vr29, vr22, vr16, vr17, vr18, vr19, \
                       128 * 1 + 20, 128 * 3 + 20, 128 * 5 + 20, 128 * 7 + 20, \
                       128 * 9 + 20, 128 * 11 + 20, 128 * 13 + 20, 20, \
                       128 * 2 + 20, 128 * 4 + 20, 128 * 6 + 20, 128 * 8 + 20, \
                       128 * 10 + 20, 128 * 12 + 20, 128 * 14 + 20, 128 * 1 + 20
    LSX_CAL_IDCT_16_ELE_2 vr30, vr21, vr16, vr17, vr18, vr19, \
                       128 * 1 + 24, 128 * 3 + 24, 128 * 5 + 24, 128 * 7 + 24, \
                       128 * 9 + 24, 128 * 11 + 24, 128 * 13 + 24, 24, \
                       128 * 2 + 24, 128 * 4 + 24, 128 * 6 + 24, 128 * 8 + 24, \
                       128 * 10 + 24, 128 * 12 + 24, 128 * 14 + 24, 128 * 1 + 24
    LSX_CAL_IDCT_16_ELE_2X vr31, vr20, vr16, vr17, vr18, vr19, \
                       128 * 1 + 28, 128 * 3 + 28, 128 * 5 + 28, 128 * 7 + 28, \
                       128 * 9 + 28, 128 * 11 + 28, 128 * 13 + 28, 28, \
                       128 * 2 + 28, 128 * 4 + 28, 128 * 6 + 28, 128 * 8 + 28, \
                       128 * 10 + 28, 128 * 12 + 28, 128 * 14 + 28, 128 * 1 + 28
    vst           vr20,     t4,      0
    vst           vr21,     t4,      16
    vst           vr22,     t4,      16 * 2
    vst           vr23,     t4,      16 * 3
.endm

.macro LSX_IDCT32_4_ROW _rin, _shift
    /* O */
    vld           vr0,     \_rin,  64    //line1
    vld           vr1,     \_rin,  192   //line3
    vld           vr2,     \_rin,  320   //line5
    vld           vr3,     \_rin,  448   //line7
    vld           vr4,     \_rin,  576   //line9
    vld           vr5,     \_rin,  704   //line11
    vld           vr6,     \_rin,  832   //line13
    vld           vr7,     \_rin,  960   //line15
    vld           vr8,     \_rin,  1088  //line17
    vld           vr9,     \_rin,  1216  //line19
    vld           vr10,    \_rin,  1344  //line21
    vld           vr11,    \_rin,  1472  //line23
    vld           vr12,    \_rin,  1600  //line25
    vld           vr13,    \_rin,  1728  //line27
    vld           vr14,    \_rin,  1856  //line29
    vld           vr15,    \_rin,  1984  //line31
    .irp i, vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7, vr8, vr9, \
            vr10, vr11, vr12, vr13, vr14, vr15
    vsllwil.w.h   \i,      \i,     0
    .endr

    CLA_IDCT32_O

    vld           vr0,     \_rin,  128   //line2
    vld           vr1,     \_rin,  384   //line6
    vld           vr2,     \_rin,  640   //line10
    vld           vr3,     \_rin,  896   //line14
    vld           vr4,     \_rin,  1152  //line18
    vld           vr5,     \_rin,  1408  //line22
    vld           vr6,     \_rin,  1664  //line26
    vld           vr7,     \_rin,  1920  //line30
    .irp i, vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7
    vsllwil.w.h   \i,      \i,     0
    .endr
    CLA_IDCT32_EO
    vld           vr0,     \_rin,  0     //line0
    vld           vr1,     \_rin,  256   //line4
    vld           vr2,     \_rin,  512   //line8
    vld           vr3,     \_rin,  768   //line12
    vld           vr4,     \_rin,  1024  //line16
    vld           vr5,     \_rin,  1280  //line20
    vld           vr6,     \_rin,  1536  //line24
    vld           vr7,     \_rin,  1792  //line38
    .irp i, vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7
    vsllwil.w.h   \i,      \i,     0
    .endr
    CLA_IDCT32_EE

    /* E */
    vadd.w        vr4,     vr0,      vr8  //E[0]
    vsub.w        vr19,    vr0,      vr8  //E[15]
    vadd.w        vr5,     vr1,      vr9  //E[1]
    vsub.w        vr18,    vr1,      vr9  //E[14]
    vadd.w        vr6,     vr2,      vr10 //E[2]
    vsub.w        vr17,    vr2,      vr10 //E[13]
    vadd.w        vr7,     vr3,      vr11 //E[3]
    vsub.w        vr16,    vr3,      vr11 //E[12]
    vadd.w        vr8,     vr20,     vr12 //E[4]
    vsub.w        vr3,     vr20,     vr12 //E[11]
    vadd.w        vr9,     vr21,     vr13 //E[5]
    vsub.w        vr2,     vr21,     vr13 //E[10]
    vadd.w        vr10,    vr22,     vr14 //E[6]
    vsub.w        vr1,     vr22,     vr14 //E[9]
    vadd.w        vr11,    vr23,     vr15 //E[7]
    vsub.w        vr0,     vr23,     vr15 //E[8]

    /* dst */
    vadd.w        vr12,    vr4,      vr24 //[0]
    vsub.w        vr23,    vr4,      vr24 //[31]
    vadd.w        vr13,    vr5,      vr25 //[1]
    vsub.w        vr22,    vr5,      vr25 //[30]
    vadd.w        vr14,    vr6,      vr26 //[2]
    vsub.w        vr21,    vr6,      vr26 //[29]
    vadd.w        vr15,    vr7,      vr27 //[3]
    vsub.w        vr20,    vr7,      vr27 //[28]

    vadd.w        vr4,     vr8,      vr28 //[4]
    vsub.w        vr27,    vr8,      vr28 //[27]
    vadd.w        vr5,     vr9,      vr29 //[5]
    vsub.w        vr26,    vr9,      vr29 //[26]
    vadd.w        vr6,     vr10,     vr30 //[6]
    vsub.w        vr25,    vr10,     vr30 //[25]
    vadd.w        vr7,     vr11,     vr31 //[7]
    vsub.w        vr24,    vr11,     vr31 //[24]

    LSX_TRANSPOSE4x4_W_EXTRA vr12, vr13, vr14, vr15, vr8, vr9, vr10, vr11
    LSX_TRANSPOSE4x4_W_EXTRA vr4, vr5, vr6, vr7, vr12, vr13, vr14, vr15
    LSX_TRANSPOSE4x4_W_EXTRA vr24, vr25, vr26, vr27, vr4, vr5, vr6, vr7
    LSX_TRANSPOSE4x4_W_EXTRA vr20, vr21, vr22, vr23, vr24, vr25, vr26, vr27

    vssrarni.h.w  vr12,    vr8,    \_shift
    vssrarni.h.w  vr13,    vr9,    \_shift
    vssrarni.h.w  vr14,    vr10,   \_shift
    vssrarni.h.w  vr15,    vr11,   \_shift  //[0...7]
    vssrarni.h.w  vr24,    vr4,    \_shift
    vssrarni.h.w  vr25,    vr5,    \_shift
    vssrarni.h.w  vr26,    vr6,    \_shift
    vssrarni.h.w  vr27,    vr7,    \_shift  //[24...31]

    vld           vr4,     t4,      0
    vld           vr5,     t4,      16
    vld           vr6,     t4,      16 * 2
    vld           vr7,     t4,      16 * 3
    vld           vr8,     t4,      16 * 4
    vld           vr9,     t4,      16 * 5
    vld           vr10,    t4,      16 * 6
    vld           vr11,    t4,      16 * 7

    vadd.w        vr20,    vr0,      vr4 //[8]
    vsub.w        vr31,    vr0,      vr4 //[23]
    vadd.w        vr21,    vr1,      vr5 //[9]
    vsub.w        vr30,    vr1,      vr5 //[22]
    vadd.w        vr22,    vr2,      vr6 //[10]
    vsub.w        vr29,    vr2,      vr6 //[21]
    vadd.w        vr23,    vr3,      vr7 //[11]
    vsub.w        vr28,    vr3,      vr7 //[20]

    vadd.w        vr4,     vr16,     vr8  //[12]
    vsub.w        vr3,     vr16,     vr8  //[19]
    vadd.w        vr5,     vr17,     vr9  //[13]
    vsub.w        vr2,     vr17,     vr9  //[18]
    vadd.w        vr6,     vr18,     vr10 //[14]
    vsub.w        vr1,     vr18,     vr10 //[17]
    vadd.w        vr7,     vr19,     vr11 //[15]
    vsub.w        vr0,     vr19,     vr11 //[16]

    LSX_TRANSPOSE4x4_W_EXTRA vr20, vr21, vr22, vr23, vr8, vr9, vr10, vr11
    LSX_TRANSPOSE4x4_W_EXTRA vr4, vr5, vr6, vr7, vr20, vr21, vr22, vr23
    LSX_TRANSPOSE4x4_W_EXTRA vr0, vr1, vr2, vr3, vr4, vr5, vr6, vr7
    LSX_TRANSPOSE4x4_W_EXTRA vr28, vr29, vr30, vr31, vr0, vr1, vr2, vr3

    vssrarni.h.w  vr20,    vr8,    \_shift
    vssrarni.h.w  vr21,    vr9,    \_shift
    vssrarni.h.w  vr22,    vr10,   \_shift
    vssrarni.h.w  vr23,    vr11,   \_shift  //[8...15]
    vssrarni.h.w  vr0,     vr4,    \_shift
    vssrarni.h.w  vr1,     vr5,    \_shift
    vssrarni.h.w  vr2,     vr6,    \_shift
    vssrarni.h.w  vr3,     vr7,    \_shift  //[16...23]
.endm

/* void x265_idct32_lsx(const int16_t* src, int16_t* dst, intptr_t dstStride) */
function x265_idct32_lsx
    addi.d        sp,      sp,      -1120 //-(64 + 8*16 + 32*32*2) si12 Immediate overflow
    addi.d        sp,      sp,      -1120
    fst.d         f24,     sp,      0
    fst.d         f25,     sp,      8
    fst.d         f26,     sp,      16
    fst.d         f27,     sp,      24
    fst.d         f28,     sp,      32
    fst.d         f29,     sp,      40
    fst.d         f30,     sp,      48
    fst.d         f31,     sp,      56
    la.local      t1,      table_dct32
    slli.d        a2,      a2,      1  //stride
    addi.d        t5,      t1,      128 * 15
    addi.d        t6,      t5,      128 * 15

    /*
     * The first butterfly operation.
     */
    addi.d        t4,      sp,      64
    addi.d        t2,      t4,      8 * 16

    /* row 0 ~ 3  */
    LSX_IDCT32_4_ROW a0, 7
    addi.d        a0,      a0,     8
    vst           vr12,    t2,     0
    vst           vr20,    t2,     16
    vst           vr0,     t2,     32
    vst           vr24,    t2,     48
    vst           vr13,    t2,     64
    vst           vr21,    t2,     80
    vst           vr1,     t2,     96
    vst           vr25,    t2,     112
    vst           vr14,    t2,     128
    vst           vr22,    t2,     144
    vst           vr2,     t2,     160
    vst           vr26,    t2,     176
    vst           vr15,    t2,     192
    vst           vr23,    t2,     208
    vst           vr3,     t2,     224
    vst           vr27,    t2,     240

    /* row 4 ~ 7  */
    LSX_IDCT32_4_ROW a0, 7
    addi.d        a0,      a0,     8
    vst           vr12,    t2,     256
    vst           vr20,    t2,     272
    vst           vr0,     t2,     288
    vst           vr24,    t2,     304
    vst           vr13,    t2,     320
    vst           vr21,    t2,     336
    vst           vr1,     t2,     352
    vst           vr25,    t2,     368
    vst           vr14,    t2,     384
    vst           vr22,    t2,     400
    vst           vr2,     t2,     416
    vst           vr26,    t2,     432
    vst           vr15,    t2,     448
    vst           vr23,    t2,     464
    vst           vr3,     t2,     480
    vst           vr27,    t2,     496

    /* row 8 ~ 11  */
    LSX_IDCT32_4_ROW a0, 7
    addi.d        a0,      a0,     8
    vst           vr12,    t2,     512
    vst           vr20,    t2,     528
    vst           vr0,     t2,     544
    vst           vr24,    t2,     560
    vst           vr13,    t2,     576
    vst           vr21,    t2,     592
    vst           vr1,     t2,     608
    vst           vr25,    t2,     624
    vst           vr14,    t2,     640
    vst           vr22,    t2,     656
    vst           vr2,     t2,     672
    vst           vr26,    t2,     688
    vst           vr15,    t2,     704
    vst           vr23,    t2,     720
    vst           vr3,     t2,     736
    vst           vr27,    t2,     752

    /* row 12 ~ 15  */
    LSX_IDCT32_4_ROW a0, 7
    addi.d        a0,      a0,     8
    vst           vr12,    t2,     768
    vst           vr20,    t2,     784
    vst           vr0,     t2,     800
    vst           vr24,    t2,     816
    vst           vr13,    t2,     832
    vst           vr21,    t2,     848
    vst           vr1,     t2,     864
    vst           vr25,    t2,     880
    vst           vr14,    t2,     896
    vst           vr22,    t2,     912
    vst           vr2,     t2,     928
    vst           vr26,    t2,     944
    vst           vr15,    t2,     960
    vst           vr23,    t2,     976
    vst           vr3,     t2,     992
    vst           vr27,    t2,     1008

    /* row 16 ~ 19  */
    LSX_IDCT32_4_ROW a0, 7
    addi.d        a0,      a0,     8
    vst           vr12,    t2,     1024
    vst           vr20,    t2,     1040
    vst           vr0,     t2,     1056
    vst           vr24,    t2,     1072
    vst           vr13,    t2,     1088
    vst           vr21,    t2,     1104
    vst           vr1,     t2,     1120
    vst           vr25,    t2,     1136
    vst           vr14,    t2,     1152
    vst           vr22,    t2,     1168
    vst           vr2,     t2,     1184
    vst           vr26,    t2,     1200
    vst           vr15,    t2,     1216
    vst           vr23,    t2,     1232
    vst           vr3,     t2,     1248
    vst           vr27,    t2,     1264

    /* row 20 ~ 23  */
    LSX_IDCT32_4_ROW a0, 7
    addi.d        a0,      a0,     8
    vst           vr12,    t2,     1280
    vst           vr20,    t2,     1296
    vst           vr0,     t2,     1312
    vst           vr24,    t2,     1328
    vst           vr13,    t2,     1344
    vst           vr21,    t2,     1360
    vst           vr1,     t2,     1376
    vst           vr25,    t2,     1392
    vst           vr14,    t2,     1408
    vst           vr22,    t2,     1424
    vst           vr2,     t2,     1440
    vst           vr26,    t2,     1456
    vst           vr15,    t2,     1472
    vst           vr23,    t2,     1488
    vst           vr3,     t2,     1504
    vst           vr27,    t2,     1520

    /* row 24 ~ 27  */
    LSX_IDCT32_4_ROW a0, 7
    addi.d        a0,      a0,     8
    vst           vr12,    t2,     1536
    vst           vr20,    t2,     1552
    vst           vr0,     t2,     1568
    vst           vr24,    t2,     1584
    vst           vr13,    t2,     1600
    vst           vr21,    t2,     1616
    vst           vr1,     t2,     1632
    vst           vr25,    t2,     1648
    vst           vr14,    t2,     1664
    vst           vr22,    t2,     1680
    vst           vr2,     t2,     1696
    vst           vr26,    t2,     1712
    vst           vr15,    t2,     1728
    vst           vr23,    t2,     1744
    vst           vr3,     t2,     1760
    vst           vr27,    t2,     1776

    /* row 28 ~ 31  */
    LSX_IDCT32_4_ROW a0, 7
    vst           vr12,    t2,     1792
    vst           vr20,    t2,     1808
    vst           vr0,     t2,     1824
    vst           vr24,    t2,     1840
    vst           vr13,    t2,     1856
    vst           vr21,    t2,     1872
    vst           vr1,     t2,     1888
    vst           vr25,    t2,     1904
    vst           vr14,    t2,     1920
    vst           vr22,    t2,     1936
    vst           vr2,     t2,     1952
    vst           vr26,    t2,     1968
    vst           vr15,    t2,     1984
    vst           vr23,    t2,     2000
    vst           vr3,     t2,     2016
    vst           vr27,    t2,     2032

    /*
     * The second butterfly operation.
     */

    /* row 0 ~ 3  */
    LSX_IDCT32_4_ROW t2, 12
    addi.d        t2,      t2,     8
    vst           vr12,    a1,     0
    vst           vr20,    a1,     16
    vst           vr0,     a1,     32
    vst           vr24,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr13,    a1,     0
    vst           vr21,    a1,     16
    vst           vr1,     a1,     32
    vst           vr25,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr14,    a1,     0
    vst           vr22,    a1,     16
    vst           vr2,     a1,     32
    vst           vr26,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr15,    a1,     0
    vst           vr23,    a1,     16
    vst           vr3,     a1,     32
    vst           vr27,    a1,     48
    add.d         a1,      a1,     a2

    /* row 4 ~ 7  */
    LSX_IDCT32_4_ROW t2, 12
    addi.d        t2,      t2,     8
    vst           vr12,    a1,     0
    vst           vr20,    a1,     16
    vst           vr0,     a1,     32
    vst           vr24,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr13,    a1,     0
    vst           vr21,    a1,     16
    vst           vr1,     a1,     32
    vst           vr25,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr14,    a1,     0
    vst           vr22,    a1,     16
    vst           vr2,     a1,     32
    vst           vr26,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr15,    a1,     0
    vst           vr23,    a1,     16
    vst           vr3,     a1,     32
    vst           vr27,    a1,     48
    add.d         a1,      a1,     a2

    /* row 8 ~ 11  */
    LSX_IDCT32_4_ROW t2, 12
    addi.d        t2,      t2,     8
    vst           vr12,    a1,     0
    vst           vr20,    a1,     16
    vst           vr0,     a1,     32
    vst           vr24,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr13,    a1,     0
    vst           vr21,    a1,     16
    vst           vr1,     a1,     32
    vst           vr25,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr14,    a1,     0
    vst           vr22,    a1,     16
    vst           vr2,     a1,     32
    vst           vr26,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr15,    a1,     0
    vst           vr23,    a1,     16
    vst           vr3,     a1,     32
    vst           vr27,    a1,     48
    add.d         a1,      a1,     a2

    /* row 12 ~ 15  */
    LSX_IDCT32_4_ROW t2, 12
    addi.d        t2,      t2,     8
    vst           vr12,    a1,     0
    vst           vr20,    a1,     16
    vst           vr0,     a1,     32
    vst           vr24,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr13,    a1,     0
    vst           vr21,    a1,     16
    vst           vr1,     a1,     32
    vst           vr25,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr14,    a1,     0
    vst           vr22,    a1,     16
    vst           vr2,     a1,     32
    vst           vr26,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr15,    a1,     0
    vst           vr23,    a1,     16
    vst           vr3,     a1,     32
    vst           vr27,    a1,     48
    add.d         a1,      a1,     a2

    /* row 16 ~ 19  */
    LSX_IDCT32_4_ROW t2, 12
    addi.d        t2,      t2,     8
    vst           vr12,    a1,     0
    vst           vr20,    a1,     16
    vst           vr0,     a1,     32
    vst           vr24,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr13,    a1,     0
    vst           vr21,    a1,     16
    vst           vr1,     a1,     32
    vst           vr25,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr14,    a1,     0
    vst           vr22,    a1,     16
    vst           vr2,     a1,     32
    vst           vr26,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr15,    a1,     0
    vst           vr23,    a1,     16
    vst           vr3,     a1,     32
    vst           vr27,    a1,     48
    add.d         a1,      a1,     a2

    /* row 20 ~ 23  */
    LSX_IDCT32_4_ROW t2, 12
    addi.d        t2,      t2,     8
    vst           vr12,    a1,     0
    vst           vr20,    a1,     16
    vst           vr0,     a1,     32
    vst           vr24,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr13,    a1,     0
    vst           vr21,    a1,     16
    vst           vr1,     a1,     32
    vst           vr25,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr14,    a1,     0
    vst           vr22,    a1,     16
    vst           vr2,     a1,     32
    vst           vr26,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr15,    a1,     0
    vst           vr23,    a1,     16
    vst           vr3,     a1,     32
    vst           vr27,    a1,     48
    add.d         a1,      a1,     a2

    /* row 24 ~ 27  */
    LSX_IDCT32_4_ROW t2, 12
    addi.d        t2,      t2,     8
    vst           vr12,    a1,     0
    vst           vr20,    a1,     16
    vst           vr0,     a1,     32
    vst           vr24,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr13,    a1,     0
    vst           vr21,    a1,     16
    vst           vr1,     a1,     32
    vst           vr25,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr14,    a1,     0
    vst           vr22,    a1,     16
    vst           vr2,     a1,     32
    vst           vr26,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr15,    a1,     0
    vst           vr23,    a1,     16
    vst           vr3,     a1,     32
    vst           vr27,    a1,     48
    add.d         a1,      a1,     a2

    /* row 28 ~ 31  */
    LSX_IDCT32_4_ROW t2, 12
    addi.d        t2,      t2,     8
    vst           vr12,    a1,     0
    vst           vr20,    a1,     16
    vst           vr0,     a1,     32
    vst           vr24,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr13,    a1,     0
    vst           vr21,    a1,     16
    vst           vr1,     a1,     32
    vst           vr25,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr14,    a1,     0
    vst           vr22,    a1,     16
    vst           vr2,     a1,     32
    vst           vr26,    a1,     48
    add.d         a1,      a1,     a2
    vst           vr15,    a1,     0
    vst           vr23,    a1,     16
    vst           vr3,     a1,     32
    vst           vr27,    a1,     48

    fld.d         f24,   sp,   0
    fld.d         f25,   sp,   8
    fld.d         f26,   sp,   16
    fld.d         f27,   sp,   24
    fld.d         f28,   sp,   32
    fld.d         f29,   sp,   40
    fld.d         f30,   sp,   48
    fld.d         f31,   sp,   56
    addi.d        sp,    sp,   1120
    addi.d        sp,    sp,   1120
endfunc

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 4 outputs)
 * temp reg: _tmp0 ~ _tmp7
 */
.macro LASX_CAL_IDCT_8_ELE_4 _rin, _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                             _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15, \
                             _tmp0, _tmp1, _tmp2, _tmp3, \
                             _out0, _out1, _out2, _out3, \
                             _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7
    xvldrepl.w     \_tmp0,  \_rin,    \_si0
    xvldrepl.w     \_tmp1,  \_rin,    \_si1
    xvldrepl.w     \_tmp2,  \_rin,    \_si2
    xvldrepl.w     \_tmp3,  \_rin,    \_si3
    xvmul.w        \_out0,  \_in0,    \_tmp0
    xvmul.w        \_out1,  \_in8,    \_tmp0
    xvmadd.w       \_out0,  \_in1,    \_tmp1
    xvmadd.w       \_out1,  \_in9,    \_tmp1
    xvmadd.w       \_out0,  \_in2,    \_tmp2
    xvmadd.w       \_out1,  \_in10,   \_tmp2
    xvmadd.w       \_out0,  \_in3,    \_tmp3
    xvmadd.w       \_out1,  \_in11,   \_tmp3

    xvmul.w        \_out2,  \_in4,    \_tmp3
    xvmul.w        \_out3,  \_in12,   \_tmp3
    xvmsub.w       \_out2,  \_in5,    \_tmp2
    xvmsub.w       \_out3,  \_in13,   \_tmp2
    xvmadd.w       \_out2,  \_in6,    \_tmp1
    xvmadd.w       \_out3,  \_in14,   \_tmp1
    xvmsub.w       \_out2,  \_in7,    \_tmp0
    xvmsub.w       \_out3,  \_in15,   \_tmp0

    xvldrepl.w     \_tmp0,  \_rin,    \_si4
    xvldrepl.w     \_tmp1,  \_rin,    \_si5
    xvldrepl.w     \_tmp2,  \_rin,    \_si6
    xvldrepl.w     \_tmp3,  \_rin,    \_si7
    xvmadd.w       \_out0,  \_in4,    \_tmp0
    xvmadd.w       \_out1,  \_in12,   \_tmp0
    xvmadd.w       \_out0,  \_in5,    \_tmp1
    xvmadd.w       \_out1,  \_in13,   \_tmp1
    xvmadd.w       \_out0,  \_in6,    \_tmp2
    xvmadd.w       \_out1,  \_in14,   \_tmp2
    xvmadd.w       \_out0,  \_in7,    \_tmp3
    xvmadd.w       \_out1,  \_in15,   \_tmp3

    xvmadd.w       \_out2,  \_in0,    \_tmp3
    xvmadd.w       \_out3,  \_in8,    \_tmp3
    xvmsub.w       \_out2,  \_in1,    \_tmp2
    xvmsub.w       \_out3,  \_in9,    \_tmp2
    xvmadd.w       \_out2,  \_in2,    \_tmp1
    xvmadd.w       \_out3,  \_in10,   \_tmp1
    xvmsub.w       \_out2,  \_in3,    \_tmp0
    xvmsub.w       \_out3,  \_in11,   \_tmp0
.endm

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 4 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: _tmp0 ~ _tmp7
 */
.macro LASX_CAL_IDCT_8_ELE_4X _rin, _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                              _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15, \
                              _tmp0, _tmp1, _tmp2, _tmp3, \
                              _out0, _out1, _out2, _out3, \
                              _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7
    xvldrepl.w     \_tmp0,  \_rin,    \_si0
    xvldrepl.w     \_tmp1,  \_rin,    \_si1
    xvldrepl.w     \_tmp2,  \_rin,    \_si2
    xvldrepl.w     \_tmp3,  \_rin,    \_si3
    xvmul.w        \_out0,  \_in0,    \_tmp0
    xvmul.w        \_out1,  \_in8,    \_tmp0
    xvmadd.w       \_out0,  \_in1,    \_tmp1
    xvmadd.w       \_out1,  \_in9,    \_tmp1
    xvmadd.w       \_out0,  \_in2,    \_tmp2
    xvmadd.w       \_out1,  \_in10,   \_tmp2
    xvmadd.w       \_out0,  \_in3,    \_tmp3
    xvmadd.w       \_out1,  \_in11,   \_tmp3

    xvmul.w        \_out2,  \_in7,    \_tmp0
    xvmul.w        \_out3,  \_in15,   \_tmp0
    xvmsub.w       \_out2,  \_in6,    \_tmp1
    xvmsub.w       \_out3,  \_in14,   \_tmp1
    xvmadd.w       \_out2,  \_in5,    \_tmp2
    xvmadd.w       \_out3,  \_in13,   \_tmp2
    xvmsub.w       \_out2,  \_in4,    \_tmp3
    xvmsub.w       \_out3,  \_in12,   \_tmp3

    xvldrepl.w     \_tmp0,  \_rin,    \_si4
    xvldrepl.w     \_tmp1,  \_rin,    \_si5
    xvldrepl.w     \_tmp2,  \_rin,    \_si6
    xvldrepl.w     \_tmp3,  \_rin,    \_si7
    xvmadd.w       \_out0,  \_in4,    \_tmp0
    xvmadd.w       \_out1,  \_in12,   \_tmp0
    xvmadd.w       \_out0,  \_in5,    \_tmp1
    xvmadd.w       \_out1,  \_in13,   \_tmp1
    xvmadd.w       \_out0,  \_in6,    \_tmp2
    xvmadd.w       \_out1,  \_in14,   \_tmp2
    xvmadd.w       \_out0,  \_in7,    \_tmp3
    xvmadd.w       \_out1,  \_in15,   \_tmp3

    xvmadd.w       \_out2,  \_in3,    \_tmp0
    xvmadd.w       \_out3,  \_in11,   \_tmp0
    xvmsub.w       \_out2,  \_in2,    \_tmp1
    xvmsub.w       \_out3,  \_in10,   \_tmp1
    xvmadd.w       \_out2,  \_in1,    \_tmp2
    xvmadd.w       \_out3,  \_in9,    \_tmp2
    xvmsub.w       \_out2,  \_in0,    \_tmp3
    xvmsub.w       \_out3,  \_in8,    \_tmp3
.endm

.macro LASX_CLA_IDCT16_O _rin
    xvld           xr8,     \_rin,  32   //line1
    xvld           xr9,     \_rin,  96   //line3
    xvld           xr10,    \_rin,  160  //line5
    xvld           xr11,    \_rin,  224  //line7
    xvld           xr12,    \_rin,  288  //line9
    xvld           xr13,    \_rin,  352  //line11
    xvld           xr14,    \_rin,  416  //line13
    xvld           xr15,    \_rin,  480  //line15
    LASX_EXT_W_H   xr8,     xr0,    xr8
    LASX_EXT_W_H   xr9,     xr1,    xr9
    LASX_EXT_W_H   xr10,    xr2,    xr10
    LASX_EXT_W_H   xr11,    xr3,    xr11
    LASX_EXT_W_H   xr12,    xr4,    xr12
    LASX_EXT_W_H   xr13,    xr5,    xr13
    LASX_EXT_W_H   xr14,    xr6,    xr14
    LASX_EXT_W_H   xr15,    xr7,    xr15

    LASX_CAL_IDCT_8_ELE_4 t1, xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7, \
                          xr8, xr9, xr10, xr11, xr12, xr13, xr14, xr15, \
                          xr16, xr17, xr18, xr19, xr24, xr20, xr31, xr23, \
                          64 * 1, 64 * 3, 64 * 5, 64 * 7, \
                          64 * 9, 64 * 11, 64 * 13, 64 * 15
    LASX_CAL_IDCT_8_ELE_4X t1, xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7, \
                           xr8, xr9, xr10, xr11, xr12, xr13, xr14, xr15, \
                           xr16, xr17, xr18, xr19, xr25, xr21, xr30, xr22, \
                           64 * 1 + 4, 64 * 3 + 4, 64 * 5 + 4, 64 * 7 + 4, \
                           64 * 9 + 4, 64 * 11 + 4, 64 * 13 + 4, 64 * 15 + 4
    xvst           xr20,     t4,      0
    xvst           xr21,     t4,      32
    xvst           xr22,     t4,      32 * 6
    xvst           xr23,     t4,      32 * 7

    LASX_CAL_IDCT_8_ELE_4 t1, xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7, \
                          xr8, xr9, xr10, xr11, xr12, xr13, xr14, xr15, \
                          xr16, xr17, xr18, xr19, xr26, xr20, xr29, xr23, \
                          64 * 1 + 8, 64 * 3 + 8, 64 * 5 + 8, 64 * 7 + 8, \
                          64 * 9 + 8, 64 * 11 + 8, 64 * 13 + 8, 64 * 15 + 8
    LASX_CAL_IDCT_8_ELE_4X t1, xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7, \
                           xr8, xr9, xr10, xr11, xr12, xr13, xr14, xr15, \
                           xr16, xr17, xr18, xr19, xr27, xr21, xr28, xr22, \
                           64 * 1 + 12, 64 * 3 + 12, 64 * 5 + 12, 64 * 7 + 12, \
                           64 * 9 + 12, 64 * 11 + 12, 64 * 13 + 12, 64 * 15 + 12
    xvst           xr20,     t4,      32 * 2
    xvst           xr21,     t4,      32 * 3
    xvst           xr22,     t4,      32 * 4
    xvst           xr23,     t4,      32 * 5
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 4 outputs)
 * temp reg: _temp0 ~ _temp3
 */
.macro LASX_CAL_IDCT_4_ELE_4 _rin, _in0, _in1, _in2, _in3, \
                             _in4, _in5, _in6, _in7, _out0, _out1, _out2, _out3, \
                             _temp0, _temp1, _temp2, _temp3, \
                             _si0, _si1, _si2, _si3
    xvldrepl.w     \_temp0, \_rin,    \_si0
    xvldrepl.w     \_temp1, \_rin,    \_si1
    xvldrepl.w     \_temp2, \_rin,    \_si2
    xvldrepl.w     \_temp3, \_rin,    \_si3
    xvmul.w        \_out0,  \_in0,    \_temp0
    xvmul.w        \_out1,  \_in4,    \_temp0
    xvmadd.w       \_out0,  \_in1,    \_temp1
    xvmadd.w       \_out1,  \_in5,    \_temp1
    xvmadd.w       \_out0,  \_in2,    \_temp2
    xvmadd.w       \_out1,  \_in6,    \_temp2
    xvmadd.w       \_out0,  \_in3,    \_temp3
    xvmadd.w       \_out1,  \_in7,    \_temp3

    xvmul.w        \_out2,  \_in0,    \_temp3
    xvmul.w        \_out3,  \_in4,    \_temp3
    xvmsub.w       \_out2,  \_in1,    \_temp2
    xvmsub.w       \_out3,  \_in5,    \_temp2
    xvmadd.w       \_out2,  \_in2,    \_temp1
    xvmadd.w       \_out3,  \_in6,    \_temp1
    xvmsub.w       \_out2,  \_in3,    \_temp0
    xvmsub.w       \_out3,  \_in7,    \_temp0
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 4 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: _temp0 ~ _temp3
 */
.macro LASX_CAL_IDCT_4_ELE_4X _rin, _in0, _in1, _in2, _in3, \
                              _in4, _in5, _in6, _in7, _out0, _out1, _out2, _out3, \
                              _temp0, _temp1, _temp2, _temp3, \
                              _si0, _si1, _si2, _si3
    xvldrepl.w     \_temp0, \_rin,    \_si0
    xvldrepl.w     \_temp1, \_rin,    \_si1
    xvldrepl.w     \_temp2, \_rin,    \_si2
    xvldrepl.w     \_temp3, \_rin,    \_si3
    xvmul.w        \_out0,  \_in0,    \_temp0
    xvmul.w        \_out1,  \_in4,    \_temp0
    xvmadd.w       \_out0,  \_in1,    \_temp1
    xvmadd.w       \_out1,  \_in5,    \_temp1
    xvmadd.w       \_out0,  \_in2,    \_temp2
    xvmadd.w       \_out1,  \_in6,    \_temp2
    xvmadd.w       \_out0,  \_in3,    \_temp3
    xvmadd.w       \_out1,  \_in7,    \_temp3

    xvmul.w        \_out2,  \_in3,    \_temp0
    xvmul.w        \_out3,  \_in7,    \_temp0
    xvmsub.w       \_out2,  \_in2,    \_temp1
    xvmsub.w       \_out3,  \_in6,    \_temp1
    xvmadd.w       \_out2,  \_in1,    \_temp2
    xvmadd.w       \_out3,  \_in5,    \_temp2
    xvmsub.w       \_out2,  \_in0,    \_temp3
    xvmsub.w       \_out3,  \_in4,    \_temp3
.endm

.macro LASX_CLA_IDCT16_E  _rin
    xvld           xr8,     \_rin,  0    //line0
    xvld           xr9,     \_rin,  64   //line2
    xvld           xr10,    \_rin,  128  //line4
    xvld           xr11,    \_rin,  192  //line6
    xvld           xr12,    \_rin,  256  //line8
    xvld           xr13,    \_rin,  320  //line10
    xvld           xr14,    \_rin,  384  //line12
    xvld           xr15,    \_rin,  448  //line14
    LASX_EXT_W_H   xr9,     xr1,    xr9
    LASX_EXT_W_H   xr11,    xr3,    xr11
    LASX_EXT_W_H   xr13,    xr5,    xr13
    LASX_EXT_W_H   xr15,    xr7,    xr15

    /* EO[0...3] */
    LASX_CAL_IDCT_4_ELE_4 t1, xr1, xr3, xr5, xr7, xr9, xr11, xr13, xr15, \
                          xr16, xr17, xr22, xr23, xr0, xr2, xr4, xr6, \
                          64 * 2, 64 * 6, 64 * 10, 64 * 14
    LASX_CAL_IDCT_4_ELE_4X t1, xr1, xr3, xr5, xr7, xr9, xr11, xr13, xr15, \
                           xr18, xr19, xr20, xr21, xr0, xr2, xr4, xr6, \
                           64 * 2 + 4, 64 * 6 + 4, 64 * 10 + 4, 64 * 14 + 4

    LASX_EXT_W_H   xr8,     xr0,    xr8
    LASX_EXT_W_H   xr10,    xr2,    xr10
    LASX_EXT_W_H   xr12,    xr4,    xr12
    LASX_EXT_W_H   xr14,    xr6,    xr14

    /* EEE */
    xvldrepl.w     xr9,     t1,     0
    xvmul.w        xr1,     xr0,    xr9
    xvmul.w        xr3,     xr8,    xr9
    xvmadd.w       xr1,     xr4,    xr9
    xvmadd.w       xr3,     xr12,   xr9  // EEE[0]
    xvmul.w        xr5,     xr0,    xr9
    xvmul.w        xr7,     xr8,    xr9
    xvmsub.w       xr5,     xr4,    xr9
    xvmsub.w       xr7,     xr12,   xr9  // EEE[1]

    /* EEO */
    xvldrepl.w     xr0,     t1,     64 * 4
    xvldrepl.w     xr4,     t1,     64 * 4 + 4
    xvmul.w        xr9,     xr2,    xr0
    xvmul.w        xr11,    xr10,   xr0
    xvmadd.w       xr9,     xr6,    xr4
    xvmadd.w       xr11,    xr14,   xr4   // EEO[0]
    xvmul.w        xr13,    xr2,    xr4
    xvmul.w        xr15,    xr10,   xr4
    xvmsub.w       xr13,    xr6,    xr0
    xvmsub.w       xr15,    xr14,   xr0   // EEO[1]

    /* EE */
    xvadd.w        xr0,     xr1,     xr9
    xvadd.w        xr2,     xr3,     xr11  //EE[0]
    xvsub.w        xr4,     xr1,     xr9
    xvsub.w        xr6,     xr3,     xr11  //EE[3]
    xvadd.w        xr8,     xr5,     xr13
    xvadd.w        xr10,    xr7,     xr15  //EE[1]
    xvsub.w        xr12,    xr5,     xr13
    xvsub.w        xr14,    xr7,     xr15  //EE[2]

    /* E */
    xvadd.w        xr1,     xr2,     xr17  //E[0]
    xvsub.w        xr15,    xr2,     xr17  //E[7]
    xvadd.w        xr3,     xr10,    xr19  //E[1]
    xvsub.w        xr13,    xr10,    xr19  //E[6]
    xvadd.w        xr5,     xr14,    xr21  //E[2]
    xvsub.w        xr11,    xr14,    xr21  //E[5]
    xvadd.w        xr7,     xr6,     xr23  //E[3]
    xvsub.w        xr9,     xr6,     xr23  //E[4]

    xvst           xr1,     t4,      32 * 8
    xvst           xr15,    t4,      32 * 9
    xvst           xr3,     t4,      32 * 10
    xvst           xr13,    t4,      32 * 11
    xvst           xr5,     t4,      32 * 12
    xvst           xr11,    t4,      32 * 13
    xvst           xr7,     t4,      32 * 14
    xvst           xr9,     t4,      32 * 15

    xvadd.w        xr1,     xr0,     xr16
    xvsub.w        xr15,    xr0,     xr16
    xvadd.w        xr3,     xr8,     xr18
    xvsub.w        xr13,    xr8,     xr18
    xvadd.w        xr5,     xr12,    xr20
    xvsub.w        xr11,    xr12,    xr20
    xvadd.w        xr7,     xr4,     xr22
    xvsub.w        xr9,     xr4,     xr22
.endm

.macro LASX_IDCT16_16_ROW_1 _rin, _rout, _shift

    LASX_CLA_IDCT16_O \_rin  /* xr24 ~ xr31 */

    LASX_CLA_IDCT16_E \_rin  /* xr:1\3\5\7\9\11\13\15 */

    /* row0~7 dst */
    xvadd.w         xr0,     xr1,     xr24  //dst[0]
    xvsub.w         xr23,    xr1,     xr24  //dst[15]
    xvadd.w         xr2,     xr3,     xr25  //dst[1]
    xvsub.w         xr22,    xr3,     xr25  //dst[14]
    xvadd.w         xr4,     xr5,     xr26  //dst[2]
    xvsub.w         xr21,    xr5,     xr26  //dst[13]
    xvadd.w         xr6,     xr7,     xr27  //dst[3]
    xvsub.w         xr20,    xr7,     xr27  //dst[12]
    xvadd.w         xr8,     xr9,     xr28  //dst[4]
    xvsub.w         xr19,    xr9,     xr28  //dst[11]
    xvadd.w         xr10,    xr11,    xr29  //dst[5]
    xvsub.w         xr18,    xr11,    xr29  //dst[10]
    xvadd.w         xr12,    xr13,    xr30  //dst[6]
    xvsub.w         xr17,    xr13,    xr30  //dst[9]
    xvadd.w         xr14,    xr15,    xr31  //dst[7]
    xvsub.w         xr16,    xr15,    xr31  //dst[8]

    LASX_TRANSPOSE8x8_W xr0, xr2, xr4, xr6, xr8, xr10, xr12, xr14, \
                        xr1, xr3, xr5, xr7, xr9, xr11, xr13, xr15, \
                        xr24, xr25, xr26, xr27
    LASX_TRANSPOSE8x8_W xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                        xr0, xr2, xr4, xr6, xr8, xr10, xr12, xr14, \
                        xr24, xr25, xr26, xr27

    xvssrarni.h.w   xr0,    xr1,     \_shift
    xvssrarni.h.w   xr2,    xr3,     \_shift
    xvssrarni.h.w   xr4,    xr5,     \_shift
    xvssrarni.h.w   xr6,    xr7,     \_shift
    xvssrarni.h.w   xr8,    xr9,     \_shift
    xvssrarni.h.w   xr10,   xr11,    \_shift
    xvssrarni.h.w   xr12,   xr13,    \_shift
    xvssrarni.h.w   xr14,   xr15,    \_shift

    xvstelm.d       xr0,    \_rout,  0,         0
    xvstelm.d       xr0,    \_rout,  8,         2
    xvstelm.d       xr0,    \_rout,  16,        1
    xvstelm.d       xr0,    \_rout,  24,        3  // k = 0
    xvstelm.d       xr2,    \_rout,  32,        0
    xvstelm.d       xr2,    \_rout,  40,        2
    xvstelm.d       xr2,    \_rout,  48,        1
    xvstelm.d       xr2,    \_rout,  56,        3  // k = 1
    xvstelm.d       xr4,    \_rout,  64,        0
    xvstelm.d       xr4,    \_rout,  72,        2
    xvstelm.d       xr4,    \_rout,  80,        1
    xvstelm.d       xr4,    \_rout,  88,        3  // k = 2
    xvstelm.d       xr6,    \_rout,  96,        0
    xvstelm.d       xr6,    \_rout,  104,       2
    xvstelm.d       xr6,    \_rout,  112,       1
    xvstelm.d       xr6,    \_rout,  120,       3  // k = 3
    xvstelm.d       xr8,    \_rout,  128,       0
    xvstelm.d       xr8,    \_rout,  136,       2
    xvstelm.d       xr8,    \_rout,  144,       1
    xvstelm.d       xr8,    \_rout,  152,       3  // k = 4
    xvstelm.d       xr10,   \_rout,  160,       0
    xvstelm.d       xr10,   \_rout,  168,       2
    xvstelm.d       xr10,   \_rout,  176,       1
    xvstelm.d       xr10,   \_rout,  184,       3  // k = 5
    xvstelm.d       xr12,   \_rout,  192,       0
    xvstelm.d       xr12,   \_rout,  200,       2
    xvstelm.d       xr12,   \_rout,  208,       1
    xvstelm.d       xr12,   \_rout,  216,       3  // k = 6
    xvstelm.d       xr14,   \_rout,  224,       0
    xvstelm.d       xr14,   \_rout,  232,       2
    xvstelm.d       xr14,   \_rout,  240,       1
    xvstelm.d       xr14,   \_rout,  248,       3  // k = 7

    xvld            xr24,    t4,      0
    xvld            xr25,    t4,      32
    xvld            xr26,    t4,      32 * 2
    xvld            xr27,    t4,      32 * 3
    xvld            xr28,    t4,      32 * 4
    xvld            xr29,    t4,      32 * 5
    xvld            xr30,    t4,      32 * 6
    xvld            xr31,    t4,      32 * 7

    xvld            xr1,     t4,      32 * 8
    xvld            xr15,    t4,      32 * 9
    xvld            xr3,     t4,      32 * 10
    xvld            xr13,    t4,      32 * 11
    xvld            xr5,     t4,      32 * 12
    xvld            xr11,    t4,      32 * 13
    xvld            xr7,     t4,      32 * 14
    xvld            xr9,     t4,      32 * 15
    /* row8~15 dst */
    xvadd.w         xr0,     xr1,     xr24  //dst[0]
    xvsub.w         xr23,    xr1,     xr24  //dst[15]
    xvadd.w         xr2,     xr3,     xr25  //dst[1]
    xvsub.w         xr22,    xr3,     xr25  //dst[14]
    xvadd.w         xr4,     xr5,     xr26  //dst[2]
    xvsub.w         xr21,    xr5,     xr26  //dst[13]
    xvadd.w         xr6,     xr7,     xr27  //dst[3]
    xvsub.w         xr20,    xr7,     xr27  //dst[12]
    xvadd.w         xr8,     xr9,     xr28  //dst[4]
    xvsub.w         xr19,    xr9,     xr28  //dst[11]
    xvadd.w         xr10,    xr11,    xr29  //dst[5]
    xvsub.w         xr18,    xr11,    xr29  //dst[10]
    xvadd.w         xr12,    xr13,    xr30  //dst[6]
    xvsub.w         xr17,    xr13,    xr30  //dst[9]
    xvadd.w         xr14,    xr15,    xr31  //dst[7]
    xvsub.w         xr16,    xr15,    xr31  //dst[8]

    LASX_TRANSPOSE8x8_W xr0, xr2, xr4, xr6, xr8, xr10, xr12, xr14, \
                        xr1, xr3, xr5, xr7, xr9, xr11, xr13, xr15, \
                        xr24, xr25, xr26, xr27
    LASX_TRANSPOSE8x8_W xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                        xr0, xr2, xr4, xr6, xr8, xr10, xr12, xr14, \
                        xr24, xr25, xr26, xr27

    xvssrarni.h.w   xr0,    xr1,     \_shift
    xvssrarni.h.w   xr2,    xr3,     \_shift
    xvssrarni.h.w   xr4,    xr5,     \_shift
    xvssrarni.h.w   xr6,    xr7,     \_shift
    xvssrarni.h.w   xr8,    xr9,     \_shift
    xvssrarni.h.w   xr10,   xr11,    \_shift
    xvssrarni.h.w   xr12,   xr13,    \_shift
    xvssrarni.h.w   xr14,   xr15,    \_shift

    xvstelm.d       xr0,    \_rout,  256,       0
    xvstelm.d       xr0,    \_rout,  264,       2
    xvstelm.d       xr0,    \_rout,  272,       1
    xvstelm.d       xr0,    \_rout,  280,       3  // k = 8
    xvstelm.d       xr2,    \_rout,  288,       0
    xvstelm.d       xr2,    \_rout,  296,       2
    xvstelm.d       xr2,    \_rout,  304,       1
    xvstelm.d       xr2,    \_rout,  312,       3  // k = 9
    xvstelm.d       xr4,    \_rout,  320,       0
    xvstelm.d       xr4,    \_rout,  328,       2
    xvstelm.d       xr4,    \_rout,  336,       1
    xvstelm.d       xr4,    \_rout,  344,       3  // k = 10
    xvstelm.d       xr6,    \_rout,  352,       0
    xvstelm.d       xr6,    \_rout,  360,       2
    xvstelm.d       xr6,    \_rout,  368,       1
    xvstelm.d       xr6,    \_rout,  376,       3  // k = 11
    xvstelm.d       xr8,    \_rout,  384,       0
    xvstelm.d       xr8,    \_rout,  392,       2
    xvstelm.d       xr8,    \_rout,  400,       1
    xvstelm.d       xr8,    \_rout,  408,       3  // k = 12
    xvstelm.d       xr10,   \_rout,  416,       0
    xvstelm.d       xr10,   \_rout,  424,       2
    xvstelm.d       xr10,   \_rout,  432,       1
    xvstelm.d       xr10,   \_rout,  440,       3  // k = 13
    xvstelm.d       xr12,   \_rout,  448,       0
    xvstelm.d       xr12,   \_rout,  456,       2
    xvstelm.d       xr12,   \_rout,  464,       1
    xvstelm.d       xr12,   \_rout,  472,       3  // k = 14
    xvstelm.d       xr14,   \_rout,  480,       0
    xvstelm.d       xr14,   \_rout,  488,       2
    xvstelm.d       xr14,   \_rout,  496,       1
    xvstelm.d       xr14,   \_rout,  504,       3  // k = 15
.endm

.macro LASX_IDCT16_16_ROW_2 _rin, _shift

    LASX_CLA_IDCT16_O \_rin  /* xr24 ~ xr31 */

    LASX_CLA_IDCT16_E \_rin  /* xr:1\3\5\7\9\11\13\15 */

    /* row0~7 dst */
    xvadd.w         xr0,     xr1,     xr24  //dst[0]
    xvsub.w         xr23,    xr1,     xr24  //dst[15]
    xvadd.w         xr2,     xr3,     xr25  //dst[1]
    xvsub.w         xr22,    xr3,     xr25  //dst[14]
    xvadd.w         xr4,     xr5,     xr26  //dst[2]
    xvsub.w         xr21,    xr5,     xr26  //dst[13]
    xvadd.w         xr6,     xr7,     xr27  //dst[3]
    xvsub.w         xr20,    xr7,     xr27  //dst[12]
    xvadd.w         xr8,     xr9,     xr28  //dst[4]
    xvsub.w         xr19,    xr9,     xr28  //dst[11]
    xvadd.w         xr10,    xr11,    xr29  //dst[5]
    xvsub.w         xr18,    xr11,    xr29  //dst[10]
    xvadd.w         xr12,    xr13,    xr30  //dst[6]
    xvsub.w         xr17,    xr13,    xr30  //dst[9]
    xvadd.w         xr14,    xr15,    xr31  //dst[7]
    xvsub.w         xr16,    xr15,    xr31  //dst[8]

    LASX_TRANSPOSE8x8_W xr0, xr2, xr4, xr6, xr8, xr10, xr12, xr14, \
                        xr1, xr3, xr5, xr7, xr9, xr11, xr13, xr15, \
                        xr24, xr25, xr26, xr27
    LASX_TRANSPOSE8x8_W xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                        xr0, xr2, xr4, xr6, xr8, xr10, xr12, xr14, \
                        xr24, xr25, xr26, xr27

    xvssrarni.h.w   xr0,    xr1,     \_shift
    xvssrarni.h.w   xr2,    xr3,     \_shift
    xvssrarni.h.w   xr4,    xr5,     \_shift
    xvssrarni.h.w   xr6,    xr7,     \_shift
    xvssrarni.h.w   xr8,    xr9,     \_shift
    xvssrarni.h.w   xr10,   xr11,    \_shift
    xvssrarni.h.w   xr12,   xr13,    \_shift
    xvssrarni.h.w   xr14,   xr15,    \_shift

    xvstelm.d       xr0,    a1,      0,         0
    xvstelm.d       xr0,    a1,      8,         2
    xvstelm.d       xr0,    a1,      16,        1
    xvstelm.d       xr0,    a1,      24,        3  // k = 0
    add.d           a1,     a1,      a2
    xvstelm.d       xr2,    a1,      0,         0
    xvstelm.d       xr2,    a1,      8,         2
    xvstelm.d       xr2,    a1,      16,        1
    xvstelm.d       xr2,    a1,      24,        3  // k = 1
    add.d           a1,     a1,      a2
    xvstelm.d       xr4,    a1,      0,         0
    xvstelm.d       xr4,    a1,      8,         2
    xvstelm.d       xr4,    a1,      16,        1
    xvstelm.d       xr4,    a1,      24,        3  // k = 2
    add.d           a1,     a1,      a2
    xvstelm.d       xr6,    a1,      0,         0
    xvstelm.d       xr6,    a1,      8,         2
    xvstelm.d       xr6,    a1,      16,        1
    xvstelm.d       xr6,    a1,      24,        3  // k = 3
    add.d           a1,     a1,      a2
    xvstelm.d       xr8,    a1,      0,         0
    xvstelm.d       xr8,    a1,      8,         2
    xvstelm.d       xr8,    a1,      16,        1
    xvstelm.d       xr8,    a1,      24,        3  // k = 4
    add.d           a1,     a1,      a2
    xvstelm.d       xr10,   a1,      0,         0
    xvstelm.d       xr10,   a1,      8,         2
    xvstelm.d       xr10,   a1,      16,        1
    xvstelm.d       xr10,   a1,      24,        3  // k = 5
    add.d           a1,     a1,      a2
    xvstelm.d       xr12,   a1,      0,         0
    xvstelm.d       xr12,   a1,      8,         2
    xvstelm.d       xr12,   a1,      16,        1
    xvstelm.d       xr12,   a1,      24,        3  // k = 6
    add.d           a1,     a1,      a2
    xvstelm.d       xr14,   a1,      0,         0
    xvstelm.d       xr14,   a1,      8,         2
    xvstelm.d       xr14,   a1,      16,        1
    xvstelm.d       xr14,   a1,      24,        3  // k = 7
    add.d           a1,     a1,      a2

    xvld            xr24,    t4,      0
    xvld            xr25,    t4,      32
    xvld            xr26,    t4,      32 * 2
    xvld            xr27,    t4,      32 * 3
    xvld            xr28,    t4,      32 * 4
    xvld            xr29,    t4,      32 * 5
    xvld            xr30,    t4,      32 * 6
    xvld            xr31,    t4,      32 * 7

    xvld            xr1,     t4,      32 * 8
    xvld            xr15,    t4,      32 * 9
    xvld            xr3,     t4,      32 * 10
    xvld            xr13,    t4,      32 * 11
    xvld            xr5,     t4,      32 * 12
    xvld            xr11,    t4,      32 * 13
    xvld            xr7,     t4,      32 * 14
    xvld            xr9,     t4,      32 * 15
    /* row8~15 dst */
    xvadd.w         xr0,     xr1,     xr24  //dst[0]
    xvsub.w         xr23,    xr1,     xr24  //dst[15]
    xvadd.w         xr2,     xr3,     xr25  //dst[1]
    xvsub.w         xr22,    xr3,     xr25  //dst[14]
    xvadd.w         xr4,     xr5,     xr26  //dst[2]
    xvsub.w         xr21,    xr5,     xr26  //dst[13]
    xvadd.w         xr6,     xr7,     xr27  //dst[3]
    xvsub.w         xr20,    xr7,     xr27  //dst[12]
    xvadd.w         xr8,     xr9,     xr28  //dst[4]
    xvsub.w         xr19,    xr9,     xr28  //dst[11]
    xvadd.w         xr10,    xr11,    xr29  //dst[5]
    xvsub.w         xr18,    xr11,    xr29  //dst[10]
    xvadd.w         xr12,    xr13,    xr30  //dst[6]
    xvsub.w         xr17,    xr13,    xr30  //dst[9]
    xvadd.w         xr14,    xr15,    xr31  //dst[7]
    xvsub.w         xr16,    xr15,    xr31  //dst[8]

    LASX_TRANSPOSE8x8_W xr0, xr2, xr4, xr6, xr8, xr10, xr12, xr14, \
                        xr1, xr3, xr5, xr7, xr9, xr11, xr13, xr15, \
                        xr24, xr25, xr26, xr27
    LASX_TRANSPOSE8x8_W xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, \
                        xr0, xr2, xr4, xr6, xr8, xr10, xr12, xr14, \
                        xr24, xr25, xr26, xr27

    xvssrarni.h.w   xr0,    xr1,     \_shift
    xvssrarni.h.w   xr2,    xr3,     \_shift
    xvssrarni.h.w   xr4,    xr5,     \_shift
    xvssrarni.h.w   xr6,    xr7,     \_shift
    xvssrarni.h.w   xr8,    xr9,     \_shift
    xvssrarni.h.w   xr10,   xr11,    \_shift
    xvssrarni.h.w   xr12,   xr13,    \_shift
    xvssrarni.h.w   xr14,   xr15,    \_shift

    xvstelm.d       xr0,    a1,      0,         0
    xvstelm.d       xr0,    a1,      8,         2
    xvstelm.d       xr0,    a1,      16,        1
    xvstelm.d       xr0,    a1,      24,        3  // k = 8
    add.d           a1,     a1,      a2
    xvstelm.d       xr2,    a1,      0,         0
    xvstelm.d       xr2,    a1,      8,         2
    xvstelm.d       xr2,    a1,      16,        1
    xvstelm.d       xr2,    a1,      24,        3  // k = 9
    add.d           a1,     a1,      a2
    xvstelm.d       xr4,    a1,      0,         0
    xvstelm.d       xr4,    a1,      8,         2
    xvstelm.d       xr4,    a1,      16,        1
    xvstelm.d       xr4,    a1,      24,        3  // k = 10
    add.d           a1,     a1,      a2
    xvstelm.d       xr6,    a1,      0,         0
    xvstelm.d       xr6,    a1,      8,         2
    xvstelm.d       xr6,    a1,      16,        1
    xvstelm.d       xr6,    a1,      24,        3  // k = 11
    add.d           a1,     a1,      a2
    xvstelm.d       xr8,    a1,      0,         0
    xvstelm.d       xr8,    a1,      8,         2
    xvstelm.d       xr8,    a1,      16,        1
    xvstelm.d       xr8,    a1,      24,        3  // k = 12
    add.d           a1,     a1,      a2
    xvstelm.d       xr10,   a1,      0,         0
    xvstelm.d       xr10,   a1,      8,         2
    xvstelm.d       xr10,   a1,      16,        1
    xvstelm.d       xr10,   a1,      24,        3  // k = 13
    add.d           a1,     a1,      a2
    xvstelm.d       xr12,   a1,      0,         0
    xvstelm.d       xr12,   a1,      8,         2
    xvstelm.d       xr12,   a1,      16,        1
    xvstelm.d       xr12,   a1,      24,        3  // k = 14
    add.d           a1,     a1,      a2
    xvstelm.d       xr14,   a1,      0,         0
    xvstelm.d       xr14,   a1,      8,         2
    xvstelm.d       xr14,   a1,      16,        1
    xvstelm.d       xr14,   a1,      24,        3  // k = 15
.endm

/* void x265_idct16_lasx(const int16_t* src, int16_t* dst, intptr_t dstStride) */
function x265_idct16_lasx
    addi.d        sp,      sp,      -1088 //-(64 + 32*16 + 16 *16*2)
    fst.d         f24,     sp,      0
    fst.d         f25,     sp,      8
    fst.d         f26,     sp,      16
    fst.d         f27,     sp,      24
    fst.d         f28,     sp,      32
    fst.d         f29,     sp,      40
    fst.d         f30,     sp,      48
    fst.d         f31,     sp,      56
    la.local      t1,      table_dct16
    slli.d        a2,      a2,      1  //stride
    addi.d        t4,      sp,      64
    addi.d        t2,      t4,      32 * 16

    /*
     * The first butterfly operation.
     */
    LASX_IDCT16_16_ROW_1 a0, t2, 7

    /*
     * The second butterfly operation.
     */
    LASX_IDCT16_16_ROW_2 t2, 12

    fld.d         f24,      sp,     0
    fld.d         f25,      sp,     8
    fld.d         f26,      sp,     16
    fld.d         f27,      sp,     24
    fld.d         f28,      sp,     32
    fld.d         f29,      sp,     40
    fld.d         f30,      sp,     48
    fld.d         f31,      sp,     56
    addi.d        sp,       sp,     1088
endfunc

/*
 * Description : Multiplication and addition calculation of 16 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * in reg: xr0 ~ xr15
 * temp reg: _temp0 ~ _temp1
 */
.macro LASX_CAL_IDCT_16_ELE_2 _out0,  _out1, _temp0, _temp1, _temp2, _temp3, \
                              _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7, \
                              _si8, _si9, _si10, _si11, _si12, _si13, _si14, _si15
    xvldrepl.w     \_temp0, t1,       \_si0
    xvldrepl.w     \_temp1, t1,       \_si1
    xvldrepl.w     \_temp2, t1,       \_si2
    xvldrepl.w     \_temp3, t1,       \_si3
    xvmul.w        \_out0,  xr0,      \_temp0
    xvmul.w        \_out1,  xr12,     \_temp3
    xvmadd.w       \_out0,  xr1,      \_temp1
    xvmsub.w       \_out1,  xr13,     \_temp2
    xvmadd.w       \_out0,  xr2,      \_temp2
    xvmadd.w       \_out1,  xr14,     \_temp1
    xvmadd.w       \_out0,  xr3,      \_temp3
    xvmsub.w       \_out1,  xr15,     \_temp0

    xvldrepl.w     \_temp0, t1,       \_si4
    xvldrepl.w     \_temp1, t1,       \_si5
    xvldrepl.w     \_temp2, t1,       \_si6
    xvldrepl.w     \_temp3, t5,       \_si7
    xvmadd.w       \_out0,  xr4,      \_temp0
    xvmadd.w       \_out1,  xr8,      \_temp3
    xvmadd.w       \_out0,  xr5,      \_temp1
    xvmsub.w       \_out1,  xr9,      \_temp2
    xvmadd.w       \_out0,  xr6,      \_temp2
    xvmadd.w       \_out1,  xr10,     \_temp1
    xvmadd.w       \_out0,  xr7,      \_temp3
    xvmsub.w       \_out1,  xr11,     \_temp0

    xvldrepl.w     \_temp0, t5,       \_si8
    xvldrepl.w     \_temp1, t5,       \_si9
    xvldrepl.w     \_temp2, t5,       \_si10
    xvldrepl.w     \_temp3, t5,       \_si11
    xvmadd.w       \_out0,  xr8,      \_temp0
    xvmadd.w       \_out1,  xr4,      \_temp3
    xvmadd.w       \_out0,  xr9,      \_temp1
    xvmsub.w       \_out1,  xr5,      \_temp2
    xvmadd.w       \_out0,  xr10,     \_temp2
    xvmadd.w       \_out1,  xr6,      \_temp1
    xvmadd.w       \_out0,  xr11,     \_temp3
    xvmsub.w       \_out1,  xr7,      \_temp0

    xvldrepl.w     \_temp0, t5,       \_si12
    xvldrepl.w     \_temp1, t5,       \_si13
    xvldrepl.w     \_temp2, t5,       \_si14
    xvldrepl.w     \_temp3, t6,       \_si15
    xvmadd.w       \_out0,  xr12,     \_temp0
    xvmadd.w       \_out1,  xr0,      \_temp3
    xvmadd.w       \_out0,  xr13,     \_temp1
    xvmsub.w       \_out1,  xr1,      \_temp2
    xvmadd.w       \_out0,  xr14,     \_temp2
    xvmadd.w       \_out1,  xr2,      \_temp1
    xvmadd.w       \_out0,  xr15,     \_temp3
    xvmsub.w       \_out1,  xr3,      \_temp0
.endm

/*
 * Description : Multiplication and addition calculation of 16 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * in reg: xr0 ~ xr15
 * temp reg: _temp0 ~ _temp1
 */
.macro LASX_CAL_IDCT_16_ELE_2X _out0, _out1, _temp0, _temp1, _temp2, _temp3, \
                               _si0, _si1, _si2, _si3, _si4, _si5, _si6, _si7, \
                               _si8, _si9, _si10, _si11, _si12, _si13, _si14, _si15
    xvldrepl.w     \_temp0, t1,       \_si0
    xvldrepl.w     \_temp1, t1,       \_si1
    xvldrepl.w     \_temp2, t1,       \_si2
    xvldrepl.w     \_temp3, t1,       \_si3
    xvmul.w        \_out0,  xr0,      \_temp0
    xvmul.w        \_out1,  xr15,     \_temp0
    xvmadd.w       \_out0,  xr1,      \_temp1
    xvmsub.w       \_out1,  xr14,     \_temp1
    xvmadd.w       \_out0,  xr2,      \_temp2
    xvmadd.w       \_out1,  xr13,     \_temp2
    xvmadd.w       \_out0,  xr3,      \_temp3
    xvmsub.w       \_out1,  xr12,     \_temp3

    xvldrepl.w     \_temp0, t1,       \_si4
    xvldrepl.w     \_temp1, t1,       \_si5
    xvldrepl.w     \_temp2, t1,       \_si6
    xvldrepl.w     \_temp3, t5,       \_si7
    xvmadd.w       \_out0,  xr4,      \_temp0
    xvmadd.w       \_out1,  xr11,     \_temp0
    xvmadd.w       \_out0,  xr5,      \_temp1
    xvmsub.w       \_out1,  xr10,     \_temp1
    xvmadd.w       \_out0,  xr6,      \_temp2
    xvmadd.w       \_out1,  xr9,      \_temp2
    xvmadd.w       \_out0,  xr7,      \_temp3
    xvmsub.w       \_out1,  xr8,      \_temp3

    xvldrepl.w     \_temp0, t5,       \_si8
    xvldrepl.w     \_temp1, t5,       \_si9
    xvldrepl.w     \_temp2, t5,       \_si10
    xvldrepl.w     \_temp3, t5,       \_si11
    xvmadd.w       \_out0,  xr8,      \_temp0
    xvmadd.w       \_out1,  xr7,      \_temp0
    xvmadd.w       \_out0,  xr9,      \_temp1
    xvmsub.w       \_out1,  xr6,      \_temp1
    xvmadd.w       \_out0,  xr10,     \_temp2
    xvmadd.w       \_out1,  xr5,      \_temp2
    xvmadd.w       \_out0,  xr11,     \_temp3
    xvmsub.w       \_out1,  xr4,      \_temp3

    xvldrepl.w     \_temp0, t5,       \_si12
    xvldrepl.w     \_temp1, t5,       \_si13
    xvldrepl.w     \_temp2, t5,       \_si14
    xvldrepl.w     \_temp3, t6,       \_si15
    xvmadd.w       \_out0,  xr12,     \_temp0
    xvmadd.w       \_out1,  xr3,      \_temp0
    xvmadd.w       \_out0,  xr13,     \_temp1
    xvmsub.w       \_out1,  xr2,      \_temp1
    xvmadd.w       \_out0,  xr14,     \_temp2
    xvmadd.w       \_out1,  xr1,      \_temp2
    xvmadd.w       \_out0,  xr15,     \_temp3
    xvmsub.w       \_out1,  xr0,      \_temp3
.endm

.macro LASX_CLA_IDCT32_O
    LASX_CAL_IDCT_16_ELE_2 xr24, xr23, xr16, xr17, xr18, xr19, \
                           128 * 1, 128 * 3, 128 * 5, 128 * 7, \
                           128 * 9, 128 * 11, 128 * 13, 0, \
                           128 * 2, 128 * 4, 128 * 6, 128 * 8, \
                           128 * 10, 128 * 12, 128 * 14, 128 * 1
    LASX_CAL_IDCT_16_ELE_2X xr25, xr22, xr16, xr17, xr18, xr19, \
                           128 * 1 + 4, 128 * 3 + 4, 128 * 5 + 4, 128 * 7 + 4, \
                           128 * 9 + 4, 128 * 11 + 4, 128 * 13 + 4, 4, \
                           128 * 2 + 4, 128 * 4 + 4, 128 * 6 + 4, 128 * 8 + 4, \
                           128 * 10 + 4, 128 * 12 + 4, 128 * 14 + 4, 128 * 1 + 4
    LASX_CAL_IDCT_16_ELE_2 xr26, xr21, xr16, xr17, xr18, xr19, \
                           128 * 1 + 8, 128 * 3 + 8, 128 * 5 + 8, 128 * 7 + 8, \
                           128 * 9 + 8, 128 * 11 + 8, 128 * 13 + 8, 8, \
                           128 * 2 + 8, 128 * 4 + 8, 128 * 6 + 8, 128 * 8 + 8, \
                           128 * 10 + 8, 128 * 12 + 8, 128 * 14 + 8, 128 * 1 + 8
    LASX_CAL_IDCT_16_ELE_2X xr27, xr20, xr16, xr17, xr18, xr19, \
                           128 * 1 + 12, 128 * 3 + 12, 128 * 5 + 12, 128 * 7 + 12, \
                           128 * 9 + 12, 128 * 11 + 12, 128 * 13 + 12, 12, \
                           128 * 2 + 12, 128 * 4 + 12, 128 * 6 + 12, 128 * 8 + 12, \
                           128 * 10 + 12, 128 * 12 + 12, 128 * 14 + 12, 128 * 1 + 12
    xvst           xr20,     t4,      32 * 4
    xvst           xr21,     t4,      32 * 5
    xvst           xr22,     t4,      32 * 6
    xvst           xr23,     t4,      32 * 7

    LASX_CAL_IDCT_16_ELE_2 xr28, xr23, xr16, xr17, xr18, xr19, \
                           128 * 1 + 16, 128 * 3 + 16, 128 * 5 + 16, 128 * 7 + 16, \
                           128 * 9 + 16, 128 * 11 + 16, 128 * 13 + 16, 16, \
                           128 * 2 + 16, 128 * 4 + 16, 128 * 6 + 16, 128 * 8 + 16, \
                           128 * 10 + 16, 128 * 12 + 16, 128 * 14 + 16, 128 * 1 + 16
    LASX_CAL_IDCT_16_ELE_2X xr29, xr22, xr16, xr17, xr18, xr19, \
                           128 * 1 + 20, 128 * 3 + 20, 128 * 5 + 20, 128 * 7 + 20, \
                           128 * 9 + 20, 128 * 11 + 20, 128 * 13 + 20, 20, \
                           128 * 2 + 20, 128 * 4 + 20, 128 * 6 + 20, 128 * 8 + 20, \
                           128 * 10 + 20, 128 * 12 + 20, 128 * 14 + 20, 128 * 1 + 20
    LASX_CAL_IDCT_16_ELE_2 xr30, xr21, xr16, xr17, xr18, xr19, \
                           128 * 1 + 24, 128 * 3 + 24, 128 * 5 + 24, 128 * 7 + 24, \
                           128 * 9 + 24, 128 * 11 + 24, 128 * 13 + 24, 24, \
                           128 * 2 + 24, 128 * 4 + 24, 128 * 6 + 24, 128 * 8 + 24, \
                           128 * 10 + 24, 128 * 12 + 24, 128 * 14 + 24, 128 * 1 + 24
    LASX_CAL_IDCT_16_ELE_2X xr31, xr20, xr16, xr17, xr18, xr19, \
                            128 * 1 + 28, 128 * 3 + 28, 128 * 5 + 28, 128 * 7 + 28, \
                            128 * 9 + 28, 128 * 11 + 28, 128 * 13 + 28, 28, \
                            128 * 2 + 28, 128 * 4 + 28, 128 * 6 + 28, 128 * 8 + 28, \
                            128 * 10 + 28, 128 * 12 + 28, 128 * 14 + 28, 128 * 1 + 28
    xvst           xr20,     t4,      0
    xvst           xr21,     t4,      32
    xvst           xr22,     t4,      32 * 2
    xvst           xr23,     t4,      32 * 3
.endm

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * temp reg: _tmp0 ~ _tmp7
 */
.macro LASX_CAL_IDCT_8_ELE_2 _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                             _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7, \
                             _out0, _out1, _si0, _si1, _si2, _si3, \
                             _si4, _si5, _si6, _si7
    xvldrepl.w     \_tmp0,  t1,       \_si0
    xvldrepl.w     \_tmp1,  t1,       \_si1
    xvldrepl.w     \_tmp2,  t1,       \_si2
    xvldrepl.w     \_tmp3,  t1,       \_si3
    xvldrepl.w     \_tmp4,  t5,       \_si4
    xvldrepl.w     \_tmp5,  t5,       \_si5
    xvldrepl.w     \_tmp6,  t5,       \_si6
    xvldrepl.w     \_tmp7,  t6,       \_si7

    xvmul.w        \_out0,  \_in0,    \_tmp0
    xvmul.w        \_out1,  \_in0,    \_tmp7
    xvmadd.w       \_out0,  \_in1,    \_tmp1
    xvmsub.w       \_out1,  \_in1,    \_tmp6
    xvmadd.w       \_out0,  \_in2,    \_tmp2
    xvmadd.w       \_out1,  \_in2,    \_tmp5
    xvmadd.w       \_out0,  \_in3,    \_tmp3
    xvmsub.w       \_out1,  \_in3,    \_tmp4
    xvmadd.w       \_out0,  \_in4,    \_tmp4
    xvmadd.w       \_out1,  \_in4,    \_tmp3
    xvmadd.w       \_out0,  \_in5,    \_tmp5
    xvmsub.w       \_out1,  \_in5,    \_tmp2
    xvmadd.w       \_out0,  \_in6,    \_tmp6
    xvmadd.w       \_out1,  \_in6,    \_tmp1
    xvmadd.w       \_out0,  \_in7,    \_tmp7
    xvmsub.w       \_out1,  \_in7,    \_tmp0
.endm

/*
 * Description : Multiplication and addition calculation of 8 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: _tmp0 ~ _tmp7
 */
.macro LASX_CAL_IDCT_8_ELE_2X _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \
                              _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7, \
                              _out0, _out1, _si0, _si1, _si2, _si3, \
                              _si4, _si5, _si6, _si7
    xvldrepl.w     \_tmp0,  t1,       \_si0
    xvldrepl.w     \_tmp1,  t1,       \_si1
    xvldrepl.w     \_tmp2,  t1,       \_si2
    xvldrepl.w     \_tmp3,  t1,       \_si3
    xvldrepl.w     \_tmp4,  t5,       \_si4
    xvldrepl.w     \_tmp5,  t5,       \_si5
    xvldrepl.w     \_tmp6,  t5,       \_si6
    xvldrepl.w     \_tmp7,  t6,       \_si7

    xvmul.w       \_out0,  \_in0,     \_tmp0
    xvmul.w       \_out1,  \_in7,     \_tmp0
    xvmadd.w      \_out0,  \_in1,     \_tmp1
    xvmsub.w      \_out1,  \_in6,     \_tmp1
    xvmadd.w      \_out0,  \_in2,     \_tmp2
    xvmadd.w      \_out1,  \_in5,     \_tmp2
    xvmadd.w      \_out0,  \_in3,     \_tmp3
    xvmsub.w      \_out1,  \_in4,     \_tmp3
    xvmadd.w      \_out0,  \_in4,     \_tmp4
    xvmadd.w      \_out1,  \_in3,     \_tmp4
    xvmadd.w      \_out0,  \_in5,     \_tmp5
    xvmsub.w      \_out1,  \_in2,     \_tmp5
    xvmadd.w      \_out0,  \_in6,     \_tmp6
    xvmadd.w      \_out1,  \_in1,     \_tmp6
    xvmadd.w      \_out0,  \_in7,     \_tmp7
    xvmsub.w      \_out1,  \_in0,     \_tmp7
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * temp reg: _temp0 ~ _temp3
 */
.macro LASX_CAL_IDCT_4_ELE_2 _in0, _in1, _in2, _in3, \
                             _tmp0, _tmp1, _tmp2, _tmp3, _out0, _out1\
                             _si0, _si1, _si2, _si3
    xvldrepl.w     \_tmp0,  t1,       \_si0
    xvldrepl.w     \_tmp1,  t1,       \_si1
    xvldrepl.w     \_tmp2,  t5,       \_si2
    xvldrepl.w     \_tmp3,  t5,       \_si3

    xvmul.w       \_out0,  \_in0,     \_tmp0
    xvmul.w       \_out1,  \_in0,     \_tmp3
    xvmadd.w      \_out0,  \_in1,     \_tmp1
    xvmsub.w      \_out1,  \_in1,     \_tmp2
    xvmadd.w      \_out0,  \_in2,     \_tmp2
    xvmadd.w      \_out1,  \_in2,     \_tmp1
    xvmadd.w      \_out0,  \_in3,     \_tmp3
    xvmsub.w      \_out1,  \_in3,     \_tmp0
.endm

/*
 * Description : Multiplication and addition calculation of 4 input elements
 *               and DCT coefficients.(Calculate 2 outputs)
 * Note        : DCT coefficient symmetry is different from above.
 * temp reg: _temp0 ~ _temp3
 */
.macro LASX_CAL_IDCT_4_ELE_2X _in0, _in1, _in2, _in3, \
                              _tmp0, _tmp1, _tmp2, _tmp3, _out0, _out1\
                              _si0, _si1, _si2, _si3
    xvldrepl.w     \_tmp0,  t1,       \_si0
    xvldrepl.w     \_tmp1,  t1,       \_si1
    xvldrepl.w     \_tmp2,  t5,       \_si2
    xvldrepl.w     \_tmp3,  t5,       \_si3
    xvmul.w       \_out0,  \_in0,     \_tmp0
    xvmul.w       \_out1,  \_in3,     \_tmp0
    xvmadd.w      \_out0,  \_in1,     \_tmp1
    xvmsub.w      \_out1,  \_in2,     \_tmp1
    xvmadd.w      \_out0,  \_in2,     \_tmp2
    xvmadd.w      \_out1,  \_in1,     \_tmp2
    xvmadd.w      \_out0,  \_in3,     \_tmp3
    xvmsub.w      \_out1,  \_in0,     \_tmp3
.endm

.macro LASX_CLA_IDCT32_EO
    LASX_CAL_IDCT_8_ELE_2 xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7, \
                          xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, xr8, xr15, \
                          128 * 2, 128 * 6, 128 * 10, 128 * 14, \
                          128 * 3, 128 * 7, 128 * 11, 0
    LASX_CAL_IDCT_8_ELE_2X xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7, \
                           xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, xr9, xr14, \
                           128 * 2 + 4, 128 * 6 + 4, 128 * 10 + 4, 128 * 14 + 4, \
                           128 * 3 + 4, 128 * 7 + 4, 128 * 11 + 4, 4
    LASX_CAL_IDCT_8_ELE_2 xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7, \
                          xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, xr10, xr13, \
                          128 * 2 + 8, 128 * 6 + 8, 128 * 10 + 8, 128 * 14 + 8, \
                          128 * 3 + 8, 128 * 7 + 8, 128 * 11 + 8, 8
    LASX_CAL_IDCT_8_ELE_2X xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7, \
                           xr16, xr17, xr18, xr19, xr20, xr21, xr22, xr23, xr11, xr12, \
                           128 * 2 + 12, 128 * 6 + 12, 128 * 10 + 12, 128 * 14 + 12, \
                           128 * 3 + 12, 128 * 7 + 12, 128 * 11 + 12, 12
.endm

.macro LASX_IDCT32_OUT_SORT _in0, _in1, _tmp
    xvpermi.d     \_in0,   \_in0,  0xd8
    xvpermi.d     \_in1,   \_in1,  0xd8
    xmov          \_tmp,   \_in0
    xvpermi.q     \_in0,   \_in1,  0x02
    xvpermi.q     \_in1,   \_tmp,  0x13
.endm

.macro LASX_CLA_IDCT32_EE
    /* EEO[0...3] */
    LASX_CAL_IDCT_4_ELE_2 xr1, xr3, xr5, xr7, xr20, xr21, xr22, xr23, xr16, xr19, \
                          128 * 4, 128 * 12, 128 * 5, 128 * 13
    LASX_CAL_IDCT_4_ELE_2X xr1, xr3, xr5, xr7, xr20, xr21, xr22, xr23, xr17, xr18, \
                           128 * 4 + 4, 128 * 12 + 4, 128 * 5 + 4, 128 * 13 + 4

    /* EEEE */
    xvldrepl.w     xr1,    t1,     0
    xvmul.w        xr20,   xr0,    xr1
    xvmadd.w       xr20,   xr4,    xr1  // EEEE[0]
    xvmul.w        xr21,   xr0,    xr1
    xvmsub.w       xr21,   xr4,    xr1  // EEEE[1]

    /* EEEO */
    xvldrepl.w     xr1,    t1,     128 * 8
    xvldrepl.w     xr5,    t1,     128 * 8 + 4
    xvmul.w        xr22,    xr2,    xr1
    xvmadd.w       xr22,    xr6,    xr5  // EEEO[0]
    xvmul.w        xr23,    xr2,    xr5
    xvmsub.w       xr23,    xr6,    xr1  // EEEO[1]

    /* EEE */
    xvadd.w        xr4,     xr20,     xr22 // EEE[0]
    xvsub.w        xr7,     xr20,     xr22 // EEE[3]
    xvadd.w        xr5,     xr21,     xr23 // EEE[1]
    xvsub.w        xr6,     xr21,     xr23 // EEE[2]

    /* EE*/
    xvadd.w        xr0,     xr4,      xr16 //EE[0]
    xvsub.w        xr23,    xr4,      xr16 //EE[7]
    xvadd.w        xr1,     xr5,      xr17 //EE[1]
    xvsub.w        xr22,    xr5,      xr17 //EE[6]
    xvadd.w        xr2,     xr6,      xr18 //EE[2]
    xvsub.w        xr21,    xr6,      xr18 //EE[5]
    xvadd.w        xr3,     xr7,      xr19 //EE[3]
    xvsub.w        xr20,    xr7,      xr19 //EE[4]
.endm

.macro LASX_IDCT32_8_ROW _rin, _shift
    /* O */
    xvld          xr0,     \_rin,  64    //line1
    xvld          xr1,     \_rin,  192   //line3
    xvld          xr2,     \_rin,  320   //line5
    xvld          xr3,     \_rin,  448   //line7
    xvld          xr4,     \_rin,  576   //line9
    xvld          xr5,     \_rin,  704   //line11
    xvld          xr6,     \_rin,  832   //line13
    xvld          xr7,     \_rin,  960   //line15
    xvld          xr8,     \_rin,  1088  //line17
    xvld          xr9,     \_rin,  1216  //line19
    xvld          xr10,    \_rin,  1344  //line21
    xvld          xr11,    \_rin,  1472  //line23
    xvld          xr12,    \_rin,  1600  //line25
    xvld          xr13,    \_rin,  1728  //line27
    xvld          xr14,    \_rin,  1856  //line29
    xvld          xr15,    \_rin,  1984  //line31

    .irp i, xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7, xr8, xr9, \
            xr10, xr11, xr12, xr13, xr14, xr15
    xvpermi.d     \i,      \i,     0xd8
    xvsllwil.w.h  \i,      \i,     0
    .endr
    LASX_CLA_IDCT32_O

    xvld          xr0,     \_rin,  128   //line2
    xvld          xr1,     \_rin,  384   //line6
    xvld          xr2,     \_rin,  640   //line10
    xvld          xr3,     \_rin,  896   //line14
    xvld          xr4,     \_rin,  1152  //line18
    xvld          xr5,     \_rin,  1408  //line22
    xvld          xr6,     \_rin,  1664  //line26
    xvld          xr7,     \_rin,  1920  //line30
    .irp i, xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7
    xvpermi.d     \i,      \i,     0xd8
    xvsllwil.w.h  \i,      \i,     0
    .endr
    LASX_CLA_IDCT32_EO

    xvld          xr0,     \_rin,  0     //line0
    xvld          xr1,     \_rin,  256   //line4
    xvld          xr2,     \_rin,  512   //line8
    xvld          xr3,     \_rin,  768   //line12
    xvld          xr4,     \_rin,  1024  //line16
    xvld          xr5,     \_rin,  1280  //line20
    xvld          xr6,     \_rin,  1536  //line24
    xvld          xr7,     \_rin,  1792  //line38
    .irp i, xr0, xr1, xr2, xr3, xr4, xr5, xr6, xr7
    xvpermi.d     \i,      \i,     0xd8
    xvsllwil.w.h  \i,      \i,     0
    .endr
    LASX_CLA_IDCT32_EE

    /* E */
    xvadd.w        xr4,     xr0,      xr8  //E[0]
    xvsub.w        xr19,    xr0,      xr8  //E[15]
    xvadd.w        xr5,     xr1,      xr9  //E[1]
    xvsub.w        xr18,    xr1,      xr9  //E[14]
    xvadd.w        xr6,     xr2,      xr10 //E[2]
    xvsub.w        xr17,    xr2,      xr10 //E[13]
    xvadd.w        xr7,     xr3,      xr11 //E[3]
    xvsub.w        xr16,    xr3,      xr11 //E[12]
    xvadd.w        xr8,     xr20,     xr12 //E[4]
    xvsub.w        xr3,     xr20,     xr12 //E[11]
    xvadd.w        xr9,     xr21,     xr13 //E[5]
    xvsub.w        xr2,     xr21,     xr13 //E[10]
    xvadd.w        xr10,    xr22,     xr14 //E[6]
    xvsub.w        xr1,     xr22,     xr14 //E[9]
    xvadd.w        xr11,    xr23,     xr15 //E[7]
    xvsub.w        xr0,     xr23,     xr15 //E[8]

    /* dst */
    xvadd.w        xr12,    xr4,      xr24 //[0]
    xvsub.w        xr23,    xr4,      xr24 //[31]
    xvadd.w        xr13,    xr5,      xr25 //[1]
    xvsub.w        xr22,    xr5,      xr25 //[30]
    xvadd.w        xr14,    xr6,      xr26 //[2]
    xvsub.w        xr21,    xr6,      xr26 //[29]
    xvadd.w        xr15,    xr7,      xr27 //[3]
    xvsub.w        xr20,    xr7,      xr27 //[28]

    xvadd.w        xr4,     xr8,      xr28 //[4]
    xvsub.w        xr27,    xr8,      xr28 //[27]
    xvadd.w        xr5,     xr9,      xr29 //[5]
    xvsub.w        xr26,    xr9,      xr29 //[26]
    xvadd.w        xr6,     xr10,     xr30 //[6]
    xvsub.w        xr25,    xr10,     xr30 //[25]
    xvadd.w        xr7,     xr11,     xr31 //[7]
    xvsub.w        xr24,    xr11,     xr31 //[24]

    LASX_TRANSPOSE8x8_W_EXTRA xr12, xr13, xr14, xr15, xr4, xr5, xr6, xr7, \
                              xr8, xr9, xr10, xr11, xr28, xr29, xr30, xr31
    LASX_TRANSPOSE8x8_W_EXTRA xr24, xr25, xr26, xr27, xr20, xr21, xr22, xr23, \
                              xr12, xr13, xr14, xr15, xr4, xr5, xr6, xr7

    xvssrarni.h.w  xr12,    xr8,     \_shift
    xvssrarni.h.w  xr13,    xr9,     \_shift
    xvssrarni.h.w  xr14,    xr10,    \_shift
    xvssrarni.h.w  xr15,    xr11,    \_shift
    xvssrarni.h.w  xr4,     xr28,    \_shift
    xvssrarni.h.w  xr5,     xr29,    \_shift
    xvssrarni.h.w  xr6,     xr30,    \_shift
    xvssrarni.h.w  xr7,     xr31,    \_shift

    xvld           xr24,    t4,      0
    xvld           xr25,    t4,      32
    xvld           xr26,    t4,      32 * 2
    xvld           xr27,    t4,      32 * 3
    xvld           xr8,     t4,      32 * 4
    xvld           xr9,     t4,      32 * 5
    xvld           xr10,    t4,      32 * 6
    xvld           xr11,    t4,      32 * 7

    xvadd.w        xr20,    xr0,      xr24 //[8]
    xvsub.w        xr31,    xr0,      xr24 //[23]
    xvadd.w        xr21,    xr1,      xr25 //[9]
    xvsub.w        xr30,    xr1,      xr25 //[22]
    xvadd.w        xr22,    xr2,      xr26 //[10]
    xvsub.w        xr29,    xr2,      xr26 //[21]
    xvadd.w        xr23,    xr3,      xr27 //[11]
    xvsub.w        xr28,    xr3,      xr27 //[20]

    xvadd.w        xr24,    xr16,     xr8  //[12]
    xvsub.w        xr3,     xr16,     xr8  //[19]
    xvadd.w        xr25,    xr17,     xr9  //[13]
    xvsub.w        xr2,     xr17,     xr9  //[18]
    xvadd.w        xr26,    xr18,     xr10 //[14]
    xvsub.w        xr1,     xr18,     xr10 //[17]
    xvadd.w        xr27,    xr19,     xr11 //[15]
    xvsub.w        xr0,     xr19,     xr11 //[16]

    LASX_TRANSPOSE8x8_W_EXTRA xr20, xr21, xr22, xr23, xr24, xr25, xr26, xr27, \
                              xr8, xr9, xr10, xr11, xr16, xr17, xr18, xr19
    LASX_TRANSPOSE8x8_W_EXTRA xr0, xr1, xr2, xr3, xr28, xr29, xr30, xr31, \
                              xr20, xr21, xr22, xr23, xr24, xr25, xr26, xr27

    xvssrarni.h.w  xr20,    xr8,    \_shift
    xvssrarni.h.w  xr21,    xr9,    \_shift
    xvssrarni.h.w  xr22,    xr10,   \_shift
    xvssrarni.h.w  xr23,    xr11,   \_shift
    xvssrarni.h.w  xr24,    xr16,   \_shift
    xvssrarni.h.w  xr25,    xr17,   \_shift
    xvssrarni.h.w  xr26,    xr18,   \_shift
    xvssrarni.h.w  xr27,    xr19,   \_shift

    /* Output sorting */
    LASX_IDCT32_OUT_SORT  xr12, xr20, xr0
    LASX_IDCT32_OUT_SORT  xr13, xr21, xr0
    LASX_IDCT32_OUT_SORT  xr14, xr22, xr0
    LASX_IDCT32_OUT_SORT  xr15, xr23, xr0
    LASX_IDCT32_OUT_SORT  xr4,  xr24, xr0
    LASX_IDCT32_OUT_SORT  xr5,  xr25, xr0
    LASX_IDCT32_OUT_SORT  xr6,  xr26, xr0
    LASX_IDCT32_OUT_SORT  xr7,  xr27, xr0
.endm

/* void x265_idct32_lasx(const int16_t* src, int16_t* dst, intptr_t dstStride) */
function x265_idct32_lasx
    addi.d        sp,      sp,      -1184 //-(64 + 8*32 + 32*32*2) si12 Immediate overflow
    addi.d        sp,      sp,      -1184
    fst.d         f24,     sp,      0
    fst.d         f25,     sp,      8
    fst.d         f26,     sp,      16
    fst.d         f27,     sp,      24
    fst.d         f28,     sp,      32
    fst.d         f29,     sp,      40
    fst.d         f30,     sp,      48
    fst.d         f31,     sp,      56
    la.local      t1,      table_dct32
    slli.d        a2,      a2,      1  //stride
    addi.d        t5,      t1,      128 * 15
    addi.d        t6,      t5,      128 * 15

    /*
     * The first butterfly operation.
     */
    addi.d        t4,      sp,      64
    addi.d        t2,      t4,      8 * 32

    /* row 0 ~ 7  */
    LASX_IDCT32_8_ROW a0, 7
    addi.d        a0,       a0,     16
    xvst          xr12,     t2,     0
    xvst          xr20,     t2,     32
    xvst          xr13,     t2,     64
    xvst          xr21,     t2,     96
    xvst          xr14,     t2,     128
    xvst          xr22,     t2,     160
    xvst          xr15,     t2,     192
    xvst          xr23,     t2,     224
    xvst          xr4,      t2,     256
    xvst          xr24,     t2,     288
    xvst          xr5,      t2,     320
    xvst          xr25,     t2,     352
    xvst          xr6,      t2,     384
    xvst          xr26,     t2,     416
    xvst          xr7,      t2,     448
    xvst          xr27,     t2,     480

    /* row 8 ~ 15  */
    LASX_IDCT32_8_ROW a0, 7
    addi.d        a0,       a0,     16
    xvst          xr12,     t2,     512
    xvst          xr20,     t2,     544
    xvst          xr13,     t2,     576
    xvst          xr21,     t2,     608
    xvst          xr14,     t2,     640
    xvst          xr22,     t2,     672
    xvst          xr15,     t2,     704
    xvst          xr23,     t2,     736
    xvst          xr4,      t2,     768
    xvst          xr24,     t2,     800
    xvst          xr5,      t2,     832
    xvst          xr25,     t2,     864
    xvst          xr6,      t2,     896
    xvst          xr26,     t2,     928
    xvst          xr7,      t2,     960
    xvst          xr27,     t2,     992

    /* row 16 ~ 23  */
    LASX_IDCT32_8_ROW a0, 7
    addi.d        a0,       a0,     16
    xvst          xr12,     t2,     1024
    xvst          xr20,     t2,     1056
    xvst          xr13,     t2,     1088
    xvst          xr21,     t2,     1120
    xvst          xr14,     t2,     1152
    xvst          xr22,     t2,     1184
    xvst          xr15,     t2,     1216
    xvst          xr23,     t2,     1248
    xvst          xr4,      t2,     1280
    xvst          xr24,     t2,     1312
    xvst          xr5,      t2,     1344
    xvst          xr25,     t2,     1376
    xvst          xr6,      t2,     1408
    xvst          xr26,     t2,     1440
    xvst          xr7,      t2,     1472
    xvst          xr27,     t2,     1504

    /* row 24 ~ 31  */
    LASX_IDCT32_8_ROW a0, 7
    xvst          xr12,     t2,     1536
    xvst          xr20,     t2,     1568
    xvst          xr13,     t2,     1600
    xvst          xr21,     t2,     1632
    xvst          xr14,     t2,     1664
    xvst          xr22,     t2,     1696
    xvst          xr15,     t2,     1728
    xvst          xr23,     t2,     1760
    xvst          xr4,      t2,     1792
    xvst          xr24,     t2,     1824
    xvst          xr5,      t2,     1856
    xvst          xr25,     t2,     1888
    xvst          xr6,      t2,     1920
    xvst          xr26,     t2,     1952
    xvst          xr7,      t2,     1984
    xvst          xr27,     t2,     2016

    /*
     * The second butterfly operation.
     */

    /* row 0 ~ 7  */
    LASX_IDCT32_8_ROW t2, 12
    addi.d        t2,       t2,     16
    xvst          xr12,     a1,     0
    xvst          xr20,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr13,     a1,     0
    xvst          xr21,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr14,     a1,     0
    xvst          xr22,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr15,     a1,     0
    xvst          xr23,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr4,      a1,     0
    xvst          xr24,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr5,      a1,     0
    xvst          xr25,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr6,      a1,     0
    xvst          xr26,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr7,      a1,     0
    xvst          xr27,     a1,     32
    add.d         a1,       a1,     a2

    /* row 8 ~ 15  */
    LASX_IDCT32_8_ROW t2, 12
    addi.d        t2,       t2,     16
    xvst          xr12,     a1,     0
    xvst          xr20,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr13,     a1,     0
    xvst          xr21,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr14,     a1,     0
    xvst          xr22,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr15,     a1,     0
    xvst          xr23,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr4,      a1,     0
    xvst          xr24,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr5,      a1,     0
    xvst          xr25,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr6,      a1,     0
    xvst          xr26,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr7,      a1,     0
    xvst          xr27,     a1,     32
    add.d         a1,       a1,     a2

    /* row 16 ~ 23  */
    LASX_IDCT32_8_ROW t2, 12
    addi.d        t2,       t2,     16
    xvst          xr12,     a1,     0
    xvst          xr20,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr13,     a1,     0
    xvst          xr21,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr14,     a1,     0
    xvst          xr22,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr15,     a1,     0
    xvst          xr23,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr4,      a1,     0
    xvst          xr24,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr5,      a1,     0
    xvst          xr25,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr6,      a1,     0
    xvst          xr26,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr7,      a1,     0
    xvst          xr27,     a1,     32
    add.d         a1,       a1,     a2

    /* row 24 ~ 31  */
    LASX_IDCT32_8_ROW t2, 12
    xvst          xr12,     a1,     0
    xvst          xr20,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr13,     a1,     0
    xvst          xr21,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr14,     a1,     0
    xvst          xr22,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr15,     a1,     0
    xvst          xr23,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr4,      a1,     0
    xvst          xr24,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr5,      a1,     0
    xvst          xr25,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr6,      a1,     0
    xvst          xr26,     a1,     32
    add.d         a1,       a1,     a2
    xvst          xr7,      a1,     0
    xvst          xr27,     a1,     32

    fld.d         f24,   sp,   0
    fld.d         f25,   sp,   8
    fld.d         f26,   sp,   16
    fld.d         f27,   sp,   24
    fld.d         f28,   sp,   32
    fld.d         f29,   sp,   40
    fld.d         f30,   sp,   48
    fld.d         f31,   sp,   56
    addi.d        sp,    sp,   1184
    addi.d        sp,    sp,   1184
endfunc

/*
 * scanPosLast_lsx(const uint16_t *scan, const coeff_t *coeff, uint16_t *coeffSign,
 *                 uint16_t *coeffFlag, uint8_t *coeffNum, int numSig,
 *                 const uint16_t* /*scanCG4x4*, const int /*trSize*)
 */
function x265_scanPosLast_lsx
    /* loading scan table and convert to Byte */
    vld           vr0,   a6,   0
    vld           vr20,  a6,   16
    vssrarni.b.h  vr20,  vr0,  0      // Zigzag scan table
    vxori.b       vr21,  vr20, 15

    /* convert unit of Stride(trSize) to int16_t */
    slli.d        a7,    a7,   1
    slli.d        t1,    a7,   1
    add.d         t2,    t1,   a7

    /* clear CG count */
    xor           t7,    t7,   t7
    li.d          t0,    0xffffffff00000000
    li.d          a6,    0xffffffff
1:
    /* position of current CG */
    ld.h          t8,    a0,   0
    slli.d        t8,    t8,   1
    add.d         t8,    a1,   t8
    addi.d        a0,    a0,   16 * 2

    /* loading current CG */
    vld           vr0,   t8,   0
    vldx          vr1,   t8,   a7
    vldx          vr2,   t8,   t1
    vldx          vr3,   t8,   t2
    vilvl.d       vr1,   vr1,  vr0
    vilvl.d       vr3,   vr3,  vr2
    vssrarni.b.h  vr3,   vr1,  0

    /* Zigzag */
    vshuf.b       vr4,   vr3,  vr3,  vr20
    vshuf.b       vr8,   vr3,  vr3,  vr21

    /* get sign */
    vmskltz.b     vr5,   vr4
    vpickve2gr.hu t4,    vr5,  0
    vmsknz.b      vr6,   vr4
    vpickve2gr.hu t5,    vr6,  0

    /* pext */
    addi.d        t3,    zero, 64
    beqz          t5,    3f
2:
    cto.w         t8,    t5
    rotr.d        t4,    t4,   t8
    and           t6,    t4,   t0
    srl.d         t5,    t5,   t8
    sub.d         t3,    t3,   t8

    ctz.w         t8,    t5
    srl.d         t4,    t4,   t8
    and           t4,    t4,   a6
    or            t4,    t4,   t6
    srl.d         t5,    t5,   t8
    bnez          t5,    2b
3:
    srl.d         t4,    t4,   t3

    /* get non-zero flag */
    vmsknz.b      vr6,   vr8
    vpickve2gr.hu t5,    vr6,  0    //coeffFlag
    vpcnt.h       vr7,   vr6
    vpickve2gr.hu t8,    vr7,  0    //coeffNum

    slli.d        t6,    t7,   1
    sub.d         a5,    a5,   t8
    stx.b         t8,    a4,   t7
    stx.h         t5,    a3,   t6
    stx.h         t4,    a2,   t6
    addi.d        t7,    t7,   1
    blt           zero,  a5,   1b

    /* fixup last CG non-zero flag */
    ctz.w         t8,    t5
    srl.d         t0,    t5,   t8
    stx.h         t0,    a3,   t6

    /* get last pos */
    addi.d        t7,    t7,   -1
    slli.w        t7,    t7,   4
    xori          t8,    t8,   15
    add.d         a0,    t7,   t8
endfunc

/* costCoeffNxN_lsx(const uint16_t *scan, const coeff_t *coeff, intptr_t trSize,
 *                  uint16_t *absCoeff, const uint8_t *tabSigCtx, uint32_t scanFlagMask,
 *                  uint8_t *baseCtx, int offset, int scanPosSigOff, int subPosBase)
 */
function x265_costCoeffNxN_lsx
    /* abs(coeff) */
    slli.d        a2,    a2,   1
    slli.d        t1,    a2,   1
    add.d         t0,    t1,   a2
    vldi          vr20,   0
    vld           vr0,   a1,   0
    vldx          vr1,   a1,   a2
    vldx          vr2,   a1,   t1
    vldx          vr3,   a1,   t0
    vilvl.d       vr0,   vr1,  vr0
    vilvl.d       vr1,   vr3,  vr2
    vabsd.h       vr4,   vr0,  vr20
    vabsd.h       vr5,   vr1,  vr20  //coeff

    /* loading scan table */
    ld.d          a2,    sp,   0
    addi.d        a1,    a2,   -15   //scanPosSigOff-16
    slli.d        a1,    a1,   1
    vldx          vr0,   a0,   a1
    addi.d        a0,    a0,   16
    vldx          vr1,   a0,   a1    //scan
    vmov          vr3,   vr1
    vssrarni.b.h  vr3,   vr0,  0

    /* scanPosSigOff < (SCAN_SET_SIZE - 1) ? 1 : 0 */
    addi.d        t5,    zero, 1
    addi.d        t6,    a2,   1
    srli.d        t6,    t6,   4
    masknez       t6,    t5,   t6

    /* reorder coeff */
    vshuf.h       vr0,   vr5,  vr4
    vshuf.h       vr1,   vr5,  vr4

    /* loading tabSigCtx (+offset) */
    vld           vr2,   a4,   0
    vreplgr2vr.b  vr8,   a7
    vshuf.b       vr9,   vr2,  vr2,  vr3
    vadd.b        vr2,   vr9,  vr8  //sigCtx

    // free {a0, a1, a2, a4, a7, sp + 0}
    la.local      a0,    entropyStateBits
    la.local      a4,    shift_1
    vld           vr20,  a4,   0
    la.local      a4,    shift_2
    vld           vr21,  a4,   0
    la.local      a4,    shift_3
    vld           vr22,  a4,   0
    li.d          t7,    0xffffff
    xor           a4,    a4,   a4  // numNonZero
    xor           t8,    t8,   t8  // sum
    beqz          a2,    3f        // scanPosSigOff
1:
    vstelm.h      vr1,   a3,   0,   7      // absCoeff[numNonZero] = tmpCoeff[blkPos]
    vpickve2gr.bu a7,    vr2,  15
    ldx.b         a1,    a6,   a7          // mstate = baseCtx[ctxSig]
    vshuf.b       vr1,   vr1,  vr0,  vr21  // update tmpCoeff
    vshuf.b       vr0,   vr0,  vr0,  vr20
    vshuf.b       vr2,   vr2,  vr2,  vr22  // ctxSig

    andi          t0,    a5,   1           // t0 = sig
    srli.d        a5,    a5,   1
    add.d         a4,    a4,   t0          // numNonZero += sig
    alsl.d        a3,    t0,   a3,  1      // absCoeff
    andi          t3,    a1,   1           // mps = mstate & 1
    xor           t4,    a1,   t0          // t4 = mstate ^ sig
    slli.d        t1,    t4,   2
    ldx.w         t2,    a0,   t1          // stateBits t2
    add.d         t8,    t8,   t2          // sum += stateBits

    addi.d        t4,    t4,   -1
    bnez          t4,    2f
    stx.b         t0,    a6,   a7
    addi.d        a2,    a2,   -1
    blt           zero,  a2,   1b
    b             3f
2:
    srli.d        t2,    t2,   24
    add.d         t3,    t3,   t2          // nextState = (stateBits >> 24) + mps
    stx.b         t3,    a6,   a7
    addi.d        a2,    a2,   -1
    blt           zero,  a2,   1b
3:
    ld.w          t4,    sp,   8           // subPosBase
    vstelm.h      vr1,   a3,   0,   7      // absCoeff[numNonZero] = tmpCoeff[blkPos]
    add.d         a4,    a4,   t6
    masknez       t4,    t5,   t4
    add.d         a4,    a4,   t4
    beqz          a4,    5f

    addi.d        t4,    t4,   -1
    vpickve2gr.bu a7,    vr2,  15
    and           a7,    a7,   t4          // ctxSig
    ldx.b         a1,    a6,   a7          // mstate = baseCtx[ctxSig]
    andi          t3,    a1,   1           // mps = mstate & 1
    xor           a1,    a1,   a5          // a1 = mstate ^ sig
    slli.d        t1,    a1,   2
    ldx.w         t2,    a0,   t1          // stateBits t2
    add.d         t8,    t8,   t2          // sum += stateBits
    srli.d        t2,    t2,   24
    add.d         t3,    t3,   t2          // nextState = (stateBits >> 24) + mps

    addi.d        a1,    a1,   -1
    bnez          a1,    4f
    slli.d        t3,    a5,   0
4:
    stx.b         t3,    a6,   a7
5:
    and           a0,    t8,   t7
endfunc

/* uint32_t quant_c(const int16_t* coef, const int32_t* quantCoeff,
   int32_t* deltaU, int16_t* qCoef, int qBits, int add, int numCoeff)
*/
function x265_quant_lsx
    srli.d        t0,    a6,   4     //numCoeff / 16
    vreplgr2vr.w  vr20,  a4         //qBits
    vreplgr2vr.w  vr22,  a5         //add
    vldi          vr23,  0          //numsig
    vldi          vr10,  0
    vldi          vr11,  0x401
    vsubi.wu      vr21,  vr20, 8    //qBits8
1:
    vld           vr0,   a0,   0     //level
    vld           vr1,   a0,   16
    vld           vr2,   a1,   0     //quantCoeff
    vld           vr3,   a1,   16
    vld           vr4,   a1,   32
    vld           vr5,   a1,   48
    vsigncov.h    vr6,   vr0,  vr11
    vsigncov.h    vr7,   vr1,  vr11
    vadda.h       vr8,   vr0,  vr10  //abs(level)
    vadda.h       vr9,   vr1,  vr10
    vor.v         vr6,   vr6,  vr11  //sign
    vor.v         vr7,   vr7,  vr11
    vilvl.h       vr12,  vr10, vr8
    vilvh.h       vr13,  vr10, vr8
    vilvl.h       vr14,  vr10, vr9
    vilvh.h       vr15,  vr10, vr9
    vmul.w        vr12,  vr12, vr2  //tmplevel
    vmul.w        vr13,  vr13, vr3
    vmul.w        vr14,  vr14, vr4
    vmul.w        vr15,  vr15, vr5
    vadd.w        vr2,   vr12, vr22   //templevel + add
    vadd.w        vr3,   vr13, vr22
    vadd.w        vr4,   vr14, vr22
    vadd.w        vr5,   vr15, vr22
    vsra.w        vr2,   vr2,  vr20   //level
    vsra.w        vr3,   vr3,  vr20
    vsra.w        vr4,   vr4,  vr20
    vsra.w        vr5,   vr5,  vr20
    vsll.w        vr16,  vr2,  vr20   //level << qBits
    vsll.w        vr17,  vr3,  vr20
    vsll.w        vr18,  vr4,  vr20
    vsll.w        vr19,  vr5,  vr20
    vsub.w        vr12,  vr12, vr16
    vsub.w        vr13,  vr13, vr17
    vsub.w        vr14,  vr14, vr18
    vsub.w        vr15,  vr15, vr19
    vsra.w        vr12,  vr12, vr21
    vsra.w        vr13,  vr13, vr21
    vsra.w        vr14,  vr14, vr21
    vsra.w        vr15,  vr15, vr21
    vst           vr12,  a2,   0
    vst           vr13,  a2,   16
    vst           vr14,  a2,   32
    vst           vr15,  a2,   48
    vseq.w        vr16,  vr2,  vr10
    vseq.w        vr17,  vr3,  vr10
    vseq.w        vr18,  vr4,  vr10
    vseq.w        vr19,  vr5,  vr10
    vpickev.h     vr8,   vr17, vr16
    vpickev.h     vr9,   vr19, vr18
    vilvl.h       vr16,  vr6,  vr6
    vilvl.h       vr18,  vr7,  vr7
    vandn.v       vr12,  vr8,  vr11
    vandn.v       vr13,  vr9,  vr11
    vilvh.h       vr17,  vr6,  vr6
    vilvh.h       vr19,  vr7,  vr7
    vsigncov.w    vr0,   vr16, vr2
    vsigncov.w    vr8,   vr18, vr4
    vsigncov.w    vr1,   vr17, vr3
    vsigncov.w    vr9,   vr19, vr5
    vadd.h        vr23,  vr23, vr12
    vssrani.h.w   vr1,   vr0,  0
    vssrani.h.w   vr9,   vr8,  0
    vadd.h        vr23,  vr23, vr13
    vst           vr1,   a3,   0
    vst           vr9,   a3,   16
    addi.d        t0,    t0,   -1
    addi.d        a0,    a0,   32
    addi.d        a1,    a1,   64
    addi.d        a2,    a2,   64
    addi.d        a3,    a3,   32
    blt           zero,  t0,   1b
    vhaddw.wu.hu  vr0,   vr23, vr23
    vhaddw.du.wu  vr1,   vr0,  vr0
    vhaddw.qu.du  vr2,   vr1,  vr1
    vpickve2gr.w  a0,    vr2,  0
endfunc

function x265_quant_lasx
    srli.d         t0,    a6,   4     //numCoeff / 16
    xvreplgr2vr.w  xr20,  a4         //qBits
    xvreplgr2vr.w  xr22,  a5         //add
    xvldi          xr23,  0          //numsig
    xvldi          xr10,  0
    xvldi          xr11,  0x401
    xvsubi.wu      xr21,  xr20, 8    //qBits8
2:
    xvld           xr0,   a0,   0     //level
    xvld           xr1,   a1,   0     //quantCoeff
    xvld           xr2,   a1,   32
    xvpermi.d      xr0,   xr0,  0xD8
    xvsigncov.h    xr6,   xr0,  xr11
    xvadda.h       xr8,   xr0,  xr10  //abs(level)
    xvor.v         xr6,   xr6,  xr11  //sign
    xvilvl.h       xr12,  xr10, xr8
    xvilvh.h       xr13,  xr10, xr8
    xvmul.w        xr12,  xr12, xr1  //tmplevel
    xvmul.w        xr13,  xr13, xr2
    xvadd.w        xr2,   xr12, xr22   //templevel + add
    xvadd.w        xr3,   xr13, xr22
    xvsra.w        xr2,   xr2,  xr20   //level
    xvsra.w        xr3,   xr3,  xr20
    xvsll.w        xr16,  xr2,  xr20   //level << qBits
    xvsll.w        xr17,  xr3,  xr20
    xvsub.w        xr12,  xr12, xr16
    xvsub.w        xr13,  xr13, xr17
    xvsra.w        xr12,  xr12, xr21
    xvsra.w        xr13,  xr13, xr21
    xvseq.w        xr16,  xr2,  xr10
    xvseq.w        xr17,  xr3,  xr10
    xvst           xr12,  a2,   0
    xvst           xr13,  a2,   32
    xvpickev.h     xr8,   xr17, xr16
    xvilvl.h       xr16,  xr6,  xr6
    xvilvh.h       xr17,  xr6,  xr6
    xvandn.v       xr12,  xr8,  xr11
    xvsigncov.w    xr0,   xr16, xr2
    xvsigncov.w    xr1,   xr17, xr3
    xvadd.h        xr23,  xr23, xr12
    xvssrani.h.w   xr1,   xr0,  0
    addi.d         t0,    t0,   -1
    addi.d         a0,    a0,   32
    xvpermi.d      xr2,   xr1,  0xD8
    addi.d         a1,    a1,   64
    addi.d         a2,    a2,   64
    xvst           xr2,   a3,   0
    addi.d         a3,    a3,   32
    blt            zero,  t0,   2b
    xvhaddw.wu.hu  xr0,   xr23, xr23
    xvhaddw.du.wu  xr1,   xr0,  xr0
    xvhaddw.qu.du  xr2,   xr1,  xr1
    xvpickve2gr.w  t0,    xr2,  0
    xvpickve2gr.w  t1,    xr2,  4
    add.d          a0,    t0,   t1
endfunc

/* void dequant_normal(const int16_t* quantCoef, int16_t* coef, int num,
   int scale, int shift)
*/
function x265_dequant_normal_lsx
    srli.d        t0,    a2,   4     //num / 16
    andi          t1,    a2,   15
    vreplgr2vr.w  vr20,  a3         //scale
    vreplgr2vr.w  vr21,  a4
1:
    beqz          t0,    2f
    vld           vr0,   a0,   0     //quantCoef
    vld           vr1,   a0,   16
    addi.d        a0,    a0,   32
    vsllwil.w.h   vr2,   vr0,  0
    vsllwil.w.h   vr4,   vr1,  0
    vexth.w.h     vr3,   vr0
    vexth.w.h     vr5,   vr1
    vmul.w        vr6,   vr2,  vr20
    vmul.w        vr7,   vr3,  vr20
    vmul.w        vr8,   vr4,  vr20
    vmul.w        vr9,   vr5,  vr20
    vssrarn.h.w   vr0,   vr6,  vr21
    vssrarn.h.w   vr1,   vr7,  vr21
    vssrarn.h.w   vr2,   vr8,  vr21
    vssrarn.h.w   vr3,   vr9,  vr21
    vilvl.d       vr7,   vr1,  vr0
    vilvl.d       vr9,   vr3,  vr2
    addi.d        t0,    t0,   -1
    vst           vr7,   a1,   0
    vst           vr9,   a1,   16
    addi.d        a1,    a1,   32
    b             1b
2:
    beqz          t1,    3f
    vld           vr0,   a0,   0
    vsllwil.w.h   vr1,   vr0,  0
    vexth.w.h     vr2,   vr0
    vmul.w        vr3,   vr1,  vr20
    vmul.w        vr4,   vr2,  vr20
    vssrarn.h.w   vr5,   vr3,  vr21
    vssrarn.h.w   vr6,   vr4,  vr21
    vilvl.d       vr7,   vr6,  vr5
    vst           vr7,   a1,   0
3:
endfunc

function x265_dequant_normal_lasx
    srli.d         t0,    a2,   4     //num / 16
    andi           t1,    a2,   15
    xvreplgr2vr.w  xr20,  a3         //scale
    xvreplgr2vr.w  xr21,  a4
1:
    beqz           t0,    2f
    xvld           xr0,   a0,   0     //quantCoef
    addi.d         a0,    a0,   32
    xvsllwil.w.h   xr1,   xr0,  0
    xvexth.w.h     xr2,   xr0
    xvmul.w        xr3,   xr1,  xr20
    xvmul.w        xr4,   xr2,  xr20
    addi.d         t0,    t0,   -1
    xvssrarn.h.w   xr5,   xr3,  xr21
    xvssrarn.h.w   xr6,   xr4,  xr21
    xvilvl.d       xr7,   xr6,  xr5
    xvst           xr7,   a1,   0
    addi.d         a1,    a1,   32
    blt            zero,  t0,   1b
2:
    beqz           t1,    3f
    vld            vr0,   a0,   0
    vext2xv.w.h    xr1,   xr0
    xvmul.w        xr2,   xr1,  xr20
    xvssrarn.h.w   xr3,   xr2,  xr21
    xvpermi.d      xr4,   xr3,  0xD8
    vst            vr4,   a1,   0
3:
endfunc

/* void dequant_scaling(const int16_t* quantCoef, const int32_t* deQuantCoef,
   int16_t* coef, int num, int per, int shift)
*/
function x265_dequant_scaling_lsx
    addi.d         a5,    a5,   4
    srli.d         t0,    a3,   4
    bge            a4,    a5,   1f
    sub.d          t3,    a5,   a4
    vreplgr2vr.w   vr20,  t3
2:
    beqz           t0,    3f
    vld            vr0,   a0,   0
    vld            vr1,   a0,   16
    vld            vr2,   a1,   0
    vld            vr3,   a1,   16
    vld            vr4,   a1,   32
    vld            vr5,   a1,   48
    vsllwil.w.h    vr6,   vr0,  0
    vsllwil.w.h    vr8,   vr1,  0
    vexth.w.h      vr7,   vr0
    vexth.w.h      vr9,   vr1
    vmul.w         vr10,  vr6,  vr2
    vmul.w         vr11,  vr7,  vr3
    vmul.w         vr12,  vr8,  vr4
    vmul.w         vr13,  vr9,  vr5
    vssrarn.h.w    vr0,   vr10, vr20
    vssrarn.h.w    vr1,   vr11, vr20
    vssrarn.h.w    vr2,   vr12, vr20
    vssrarn.h.w    vr3,   vr13, vr20
    addi.d         t0,    t0,   -1
    vilvl.d        vr4,   vr1,  vr0
    vilvl.d        vr5,   vr3,  vr2
    addi.d         a0,    a0,   32
    addi.d         a1,    a1,   64
    vst            vr4,   a2,   0
    vst            vr5,   a2,   16
    addi.d         a2,    a2,   32
    b              2b
1:
    sub.d          t3,    a4,   a5
    vreplgr2vr.w   vr20,  t3
4:
    beqz           t0,    3f
    vld            vr0,   a0,   0
    vld            vr1,   a0,   16
    vld            vr2,   a1,   0
    vld            vr3,   a1,   16
    vld            vr4,   a1,   32
    vld            vr5,   a1,   48
    vsllwil.w.h    vr6,   vr0,  0
    vsllwil.w.h    vr8,   vr1,  0
    vexth.w.h      vr7,   vr0
    vexth.w.h      vr9,   vr1
    vmul.w         vr10,  vr6,  vr2
    vmul.w         vr11,  vr7,  vr3
    vmul.w         vr12,  vr8,  vr4
    vmul.w         vr13,  vr9,  vr5
    vsat.w         vr0,   vr10, 31
    vsat.w         vr1,   vr11, 31
    vsat.w         vr2,   vr12, 31
    vsat.w         vr3,   vr13, 31
    vsll.w         vr4,   vr0,  vr20
    vsll.w         vr5,   vr1,  vr20
    vsll.w         vr6,   vr2,  vr20
    vsll.w         vr7,   vr3,  vr20
    addi.d         a0,    a0,   32
    vssrani.h.w    vr5,   vr4,  0
    vssrani.h.w    vr7,   vr6,  0
    addi.d         a1,    a1,   64
    addi.d         t0,    t0,   -1
    vst            vr5,   a2,   0
    vst            vr7,   a2,   16
    addi.d         a2,    a2,   32
    b              4b
3:
endfunc

function x265_dequant_scaling_lasx
    addi.d         a5,    a5,   4
    srli.d         t0,    a3,   4
    bge            a4,    a5,   1f
    sub.d          t3,    a5,   a4
    xvreplgr2vr.w  xr20,  t3
2:
    beqz           t0,    4f
    xvld           xr0,   a0,   0
    xvld           xr2,   a1,   0
    xvld           xr3,   a1,   32
    xvpermi.d      xr1,   xr0,  0xD8
    xvsllwil.w.h   xr6,   xr1,  0
    xvexth.w.h     xr7,   xr1
    xvmul.w        xr10,  xr6,  xr2
    xvmul.w        xr11,  xr7,  xr3
    xvssrarn.h.w   xr0,   xr10, xr20
    xvssrarn.h.w   xr1,   xr11, xr20
    addi.d         t0,    t0,   -1
    xvilvl.d       xr4,   xr1,  xr0
    addi.d         a0,    a0,   32
    xvpermi.d      xr5,   xr4,  0xD8
    addi.d         a1,    a1,   64
    xvst           xr5,   a2,   0
    addi.d         a2,    a2,   32
    b              2b
1:
    sub.d          t3,    a4,   a5
    xvreplgr2vr.w  xr20,  t3
3:
    beqz           t0,    4f
    xvld           xr0,   a0,   0
    xvld           xr2,   a1,   0
    xvld           xr3,   a1,   32
    xvpermi.d      xr1,   xr0,  0xD8
    xvsllwil.w.h   xr6,   xr1,  0
    xvexth.w.h     xr7,   xr1
    xvmul.w        xr10,  xr6,  xr2
    xvmul.w        xr11,  xr7,  xr3
    xvsat.w        xr0,   xr10, 31
    xvsat.w        xr1,   xr11, 31
    xvsll.w        xr4,   xr0,  xr20
    xvsll.w        xr5,   xr1,  xr20
    addi.d         a0,    a0,   32
    xvssrani.h.w   xr5,   xr4,  0
    addi.d         a1,    a1,   64
    xvpermi.d      xr6,   xr5,  0xD8
    addi.d         t0,    t0,   -1
    xvst           xr6,   a2,   0
    addi.d         a2,    a2,   32
    b              3b
4:
endfunc

/* uint32_t nquant_c(const int16_t* coef, const int32_t* quantCoeff,
   int16_t* qCoef, int qBits, int add, int numCoeff)
*/
function x265_nquant_lsx
    srli.d        t0,    a5,   4     //numCoeff / 16
    vreplgr2vr.w  vr20,  a3         //qBits
    vreplgr2vr.w  vr22,  a4         //add
    vldi          vr23,  0          //numsig
    vldi          vr10,  0
    vldi          vr11,  0x401
1:
    vld           vr0,   a0,   0     //level
    vld           vr1,   a0,   16
    vld           vr2,   a1,   0     //quantCoeff
    vld           vr3,   a1,   16
    vld           vr4,   a1,   32
    vld           vr5,   a1,   48
    vsigncov.h    vr6,   vr0,  vr11
    vsigncov.h    vr7,   vr1,  vr11
    vadda.h       vr8,   vr0,  vr10  //abs(level)
    vadda.h       vr9,   vr1,  vr10
    vor.v         vr6,   vr6,  vr11  //sign
    vor.v         vr7,   vr7,  vr11
    vilvl.h       vr12,  vr10, vr8
    vilvh.h       vr13,  vr10, vr8
    vilvl.h       vr14,  vr10, vr9
    vilvh.h       vr15,  vr10, vr9
    vmul.w        vr12,  vr12, vr2  //tmplevel
    vmul.w        vr13,  vr13, vr3
    vmul.w        vr14,  vr14, vr4
    vmul.w        vr15,  vr15, vr5
    vadd.w        vr2,   vr12, vr22   //templevel + add
    vadd.w        vr3,   vr13, vr22
    vadd.w        vr4,   vr14, vr22
    vadd.w        vr5,   vr15, vr22
    vsra.w        vr2,   vr2,  vr20   //level
    vsra.w        vr3,   vr3,  vr20
    vsra.w        vr4,   vr4,  vr20
    vsra.w        vr5,   vr5,  vr20

    vseq.w        vr16,  vr2,  vr10
    vseq.w        vr17,  vr3,  vr10
    vseq.w        vr18,  vr4,  vr10
    vseq.w        vr19,  vr5,  vr10
    vpickev.h     vr8,   vr17, vr16
    vpickev.h     vr9,   vr19, vr18
    vilvl.h       vr16,  vr6,  vr6
    vilvl.h       vr18,  vr7,  vr7
    vandn.v       vr12,  vr8,  vr11
    vandn.v       vr13,  vr9,  vr11
    vilvh.h       vr17,  vr6,  vr6
    vilvh.h       vr19,  vr7,  vr7
    vsigncov.w    vr0,   vr16, vr2
    vsigncov.w    vr8,   vr18, vr4
    vsigncov.w    vr1,   vr17, vr3
    vsigncov.w    vr9,   vr19, vr5
    vadd.h        vr23,  vr23, vr12
    vssrani.h.w   vr1,   vr0,  0
    vssrani.h.w   vr9,   vr8,  0
    vadd.h        vr23,  vr23, vr13
    vadda.h       vr1,   vr1,  vr10
    vadda.h       vr9,   vr9,  vr10
    vst           vr1,   a2,   0
    vst           vr9,   a2,   16
    addi.d        t0,    t0,   -1
    addi.d        a0,    a0,   32
    addi.d        a1,    a1,   64
    addi.d        a2,    a2,   32
    blt           zero,  t0,   1b
    vhaddw.wu.hu  vr0,   vr23, vr23
    vhaddw.du.wu  vr1,   vr0,  vr0
    vhaddw.qu.du  vr2,   vr1,  vr1
    vpickve2gr.w  a0,    vr2,  0
endfunc

function x265_nquant_lasx
    srli.d         t0,    a5,   4     //numCoeff / 16
    xvreplgr2vr.w  xr20,  a3         //qBits
    xvreplgr2vr.w  xr22,  a4         //add
    xvldi          xr23,  0          //numsig
    xvldi          xr10,  0
    xvldi          xr11,  0x401
1:
    xvld           xr0,   a0,   0     //level
    xvld           xr1,   a1,   0     //quantCoeff
    xvld           xr2,   a1,   32
    xvpermi.d      xr0,   xr0,  0xD8
    xvsigncov.h    xr6,   xr0,  xr11
    xvadda.h       xr8,   xr0,  xr10  //abs(level)
    xvor.v         xr6,   xr6,  xr11  //sign
    xvilvl.h       xr12,  xr10, xr8
    xvilvh.h       xr13,  xr10, xr8
    xvmul.w        xr12,  xr12, xr1  //tmplevel
    xvmul.w        xr13,  xr13, xr2
    xvadd.w        xr2,   xr12, xr22   //templevel + add
    xvadd.w        xr3,   xr13, xr22
    xvsra.w        xr2,   xr2,  xr20   //level
    xvsra.w        xr3,   xr3,  xr20
    xvseq.w        xr16,  xr2,  xr10
    xvseq.w        xr17,  xr3,  xr10
    xvpickev.h     xr8,   xr17, xr16
    xvilvl.h       xr16,  xr6,  xr6
    xvilvh.h       xr17,  xr6,  xr6
    xvandn.v       xr12,  xr8,  xr11
    xvsigncov.w    xr0,   xr16, xr2
    xvsigncov.w    xr1,   xr17, xr3
    xvadd.h        xr23,  xr23, xr12
    xvssrani.h.w   xr1,   xr0,  0
    addi.d         t0,    t0,   -1
    addi.d         a0,    a0,   32
    xvpermi.d      xr2,   xr1,  0xD8
    addi.d         a1,    a1,   64
    xvadda.h       xr2,   xr2,  xr10
    xvst           xr2,   a2,   0
    addi.d         a2,    a2,   32
    blt            zero,  t0,   1b
    xvhaddw.wu.hu  xr0,   xr23, xr23
    xvhaddw.du.wu  xr1,   xr0,  xr0
    xvhaddw.qu.du  xr2,   xr1,  xr1
    xvpickve2gr.w  t0,    xr2,  0
    xvpickve2gr.w  t1,    xr2,  4
    add.d          a0,    t0,   t1
endfunc

function x265_count_nonzero_32_lsx
    or             t0,    zero, zero //count
    or             t5,    zero, zero //index
    ori            t2,    zero, 128  //loop max

.CN32L01: //8
    vldx           vr0,   a0,   t5
    vseqi.h        vr1,   vr0,  0
    vaddi.hu       vr1,   vr1,  1
    vhaddw.wu.hu   vr2,   vr1,  vr1
    vhaddw.du.wu   vr3,   vr2,  vr2
    vhaddw.qu.du   vr3,   vr3,  vr3
    vpickve2gr.hu  t6,    vr3,  0
    add.d          t0,    t0,   t6

    addi.d         t5,    t5,   16
    addi.d         t2,    t2,   -1
    bnez           t2,   .CN32L01

.CN32L02:
    move           a0,    t0
endfunc

function x265_count_nonzero_16_lsx
    or             t0,    zero, zero //count
    or             t5,    zero, zero //index
    ori            t2,    zero, 32  //loop max

.CN16L01: //8
    vldx           vr0,   a0,   t5
    vseqi.h        vr1,   vr0,  0
    vaddi.hu       vr1,   vr1,  1
    vhaddw.wu.hu   vr2,   vr1,  vr1
    vhaddw.du.wu   vr3,   vr2,  vr2
    vhaddw.qu.du   vr3,   vr3,  vr3
    vpickve2gr.hu  t6,    vr3,  0
    add.d          t0,    t0,   t6

    addi.d         t5,    t5,   16
    addi.d         t2,    t2,   -1
    bnez           t2,   .CN16L01

.CN16L02:
    move           a0,    t0
endfunc

function x265_count_nonzero_8_lsx
    or             t0,    zero, zero //count
    or             t5,    zero, zero //index
    ori            t2,    zero, 8  //loop max

.CN8L01: //8
    vldx           vr0,   a0,   t5
    vseqi.h        vr1,   vr0,  0
    vaddi.hu       vr1,   vr1,  1
    vhaddw.wu.hu   vr2,   vr1,  vr1
    vhaddw.du.wu   vr3,   vr2,  vr2
    vhaddw.qu.du   vr3,   vr3,  vr3
    vpickve2gr.hu  t6,    vr3,  0
    add.d          t0,    t0,   t6

    addi.d         t5,    t5,   16
    addi.d         t2,    t2,   -1
    bnez           t2,   .CN8L01

.CN8L02:
    move           a0,    t0
endfunc

function x265_count_nonzero_4_lsx
    or             t0,    zero, zero //count
    or             t5,    zero, zero //index
    ori            t2,    zero, 2  //loop max

.CN4L01: //8
    vldx           vr0,   a0,   t5
    vseqi.h        vr1,   vr0,  0
    vaddi.hu       vr1,   vr1,  1
    vhaddw.wu.hu   vr2,   vr1,  vr1
    vhaddw.du.wu   vr3,   vr2,  vr2
    vhaddw.qu.du   vr3,   vr3,  vr3
    vpickve2gr.hu  t6,    vr3,  0
    add.d          t0,    t0,   t6

    addi.d         t5,    t5,   16
    addi.d         t2,    t2,   -1
    bnez           t2,   .CN4L01

.CN4L02:
    move           a0,    t0
endfunc

function x265_count_nonzero_32_lasx
    or             t0,    zero, zero //count
    or             t3,    zero, zero //index
    ori            t2,    zero, 64  //loop max

.CN32LA01: //16
    xvldx          xr0,   a0,   t3
    xvseqi.h       xr1,   xr0,  0
    xvaddi.hu      xr1,   xr1,  1
    xvhaddw.wu.hu  xr1,   xr1,  xr1
    xvhaddw.du.wu  xr1,   xr1,  xr1
    xvhaddw.qu.du  xr1,   xr1,  xr1
    xvpermi.q      xr0,   xr1,  0x01
    vadd.d         vr1,   vr1,  vr0
    vpickve2gr.hu  t4,    vr1,  0
    add.d          t0,    t0,   t4

    addi.d         t3,    t3,   32
    addi.d         t2,    t2,   -1
    bnez           t2,   .CN32LA01

.CN32LA02:
    move           a0,    t0
endfunc

function x265_count_nonzero_16_lasx
    or             t0,    zero, zero //count
    or             t3,    zero, zero //index
    ori            t2,    zero, 16  //loop max

.CN16LA01: //16
    xvldx          xr0,   a0,   t3
    xvseqi.h       xr1,   xr0,  0
    xvaddi.hu      xr1,   xr1,  1
    xvhaddw.wu.hu  xr1,   xr1,  xr1
    xvhaddw.du.wu  xr1,   xr1,  xr1
    xvhaddw.qu.du  xr1,   xr1,  xr1
    xvpermi.q      xr0,   xr1,  0x01
    vadd.d         vr1,   vr1,  vr0
    vpickve2gr.hu  t4,    vr1,  0
    add.d          t0,    t0,   t4

    addi.d         t3,    t3,   32
    addi.d         t2,    t2,   -1
    bnez           t2,   .CN16LA01

.CN16LA02:
    move           a0,    t0
endfunc

function x265_count_nonzero_8_lasx
    or             t0,    zero, zero //count
    or             t3,    zero, zero //index
    ori            t2,    zero, 4  //loop max

.CN8LA01: //16
    xvldx          xr0,   a0,   t3
    xvseqi.h       xr1,   xr0,  0
    xvaddi.hu      xr1,   xr1,  1
    xvhaddw.wu.hu  xr1,   xr1,  xr1
    xvhaddw.du.wu  xr1,   xr1,  xr1
    xvhaddw.qu.du  xr1,   xr1,  xr1
    xvpermi.q      xr0,   xr1,  0x01
    vadd.d         vr1,   vr1,  vr0
    vpickve2gr.hu  t4,    vr1,  0
    add.d          t0,    t0,   t4

    addi.d         t3,    t3,   32
    addi.d         t2,    t2,   -1
    bnez           t2,   .CN8LA01

.CN8LA02:
    move           a0,    t0
endfunc

function x265_count_nonzero_4_lasx
    or             t0,    zero, zero //count
    or             t3,    zero, zero //index
    ori            t2,    zero, 1  //loop max

.CN4LA01: //16
    xvldx          xr0,   a0,   t3
    xvseqi.h       xr1,   xr0,  0
    xvaddi.hu      xr1,   xr1,  1
    xvhaddw.wu.hu  xr1,   xr1,  xr1
    xvhaddw.du.wu  xr1,   xr1,  xr1
    xvhaddw.qu.du  xr1,   xr1,  xr1
    xvpermi.q      xr0,   xr1,  0x01
    vadd.d         vr1,   vr1,  vr0
    vpickve2gr.hu  t4,    vr1,  0
    add.d          t0,    t0,   t4

    addi.d         t3,    t3,   32
    addi.d         t2,    t2,   -1
    bnez           t2,   .CN4LA01

.CN4LA02:
    move           a0,    t0
endfunc

.macro COSTC1C2FLAG_CALC_BASECTXMOD_AND_SUM in0, in1, in2, in3, in4, out0, tmp0, tmp1
    ldx.bu         \tmp0, \in2, \in0
    add.d          \tmp1, \tmp0,\tmp0
    add.d          \tmp1, \tmp1,\in1
    ldx.bu         \tmp1, \in3, \tmp1  //baseCtxMod
    stx.b          \tmp1, \in2, \in0
    slli.d         \tmp0, \tmp0,2
    slli.d         \tmp1, \in1, 2
    xor            \tmp1, \tmp0,\tmp1
    ldx.wu         \tmp1, \in4, \tmp1
    add.d          \out0, \out0,\tmp1  //sum
.endm

//param: absCoeff:a0, numC1Flag:a1, baseCtxMod:a2, ctxOffset:a3
function x265_costC1C2Flag_lsx
    or             a4,    zero, zero //sum
    addi.d         a5,    zero, 8    //firstC2Idx
    addi.d         a6,    zero, 2    //firstC2Flag
    li.d           a7,    0xfffffffe //c1Next
    addi.d         t0,    zero, 1    //c1
    or             t1,    zero, zero //idx
    vandi.b        vr0,   vr0,  0
    vaddi.hu       vr1,   vr0,  1
    vaddi.hu       vr2,   vr0,  2

    la.local       t5,    gt_nextState
    la.local       t6,    gt_entropyBits

    beqz           a1,    .CC1C2FL030

    srai.d         t2,    a1,   2   //loop param
    beqz           t2,   .CC1C2FL02

.CC1C2FL01: //4
    fldx.d         f0,    a0,   t1
    vslt.hu        vr3,   vr1,  vr0
    vslt.hu        vr4,   vr2,  vr0
    vneg.h         vr3,   vr3  //symbol1
    vneg.h         vr4,   vr4  //symbol2
    srai.d         t8,    t1,   1

    vpickve2gr.hu  t3,    vr3,  0
    COSTC1C2FLAG_CALC_BASECTXMOD_AND_SUM t0, t3, a2, t5, t6, a4, t4, t7
    ori            t4,    zero, 3
    add.d          t7,    t3,   a6
    bne            t7,    t4,   .CC1C2FL0101
    vpickve2gr.hu  a6,    vr4,  0
.CC1C2FL0101:
    ori            t4,    zero, 9
    add.d          t7,    t3,   a5
    bne            t7,    t4,   .CC1C2FL0102
    or             a5,    t8,   t8
.CC1C2FL0102:
    beqz           t3,    .CC1C2FL0103
    or             a7,    zero, zero
    or             t0,    zero, zero
    b              .CC1C2FL01040
.CC1C2FL0103:
    andi           t0,    a7,   3
    srai.d         a7,    a7,   2

.CC1C2FL01040:
    vpickve2gr.hu  t3,    vr3,  1
    COSTC1C2FLAG_CALC_BASECTXMOD_AND_SUM t0, t3, a2, t5, t6, a4, t4, t7
    ori            t4,    zero, 3
    add.d          t7,    t3,   a6
    bne            t7,    t4,   .CC1C2FL0104
    vpickve2gr.hu  a6,    vr4,  1
.CC1C2FL0104:
    ori            t4,    zero, 9
    add.d          t7,    t3,   a5
    bne            t7,    t4,   .CC1C2FL0105
    addi.d         a5,    t8,   1
.CC1C2FL0105:
    beqz           t3,    .CC1C2FL0106
    or             a7,    zero, zero
    or             t0,    zero, zero
    b              .CC1C2FL01070
.CC1C2FL0106:
    andi           t0,    a7,   3
    srai.d         a7,    a7,   2

.CC1C2FL01070:
    vpickve2gr.hu  t3,    vr3,  2
    COSTC1C2FLAG_CALC_BASECTXMOD_AND_SUM t0, t3, a2, t5, t6, a4, t4, t7
    ori            t4,    zero, 3
    add.d          t7,    t3,   a6
    bne            t7,    t4,   .CC1C2FL0107
    vpickve2gr.hu  a6,    vr4,  2
.CC1C2FL0107:
    ori            t4,    zero, 9
    add.d          t7,    t3,   a5
    bne            t7,    t4,   .CC1C2FL0108
    addi.d         a5,    t8,   2
.CC1C2FL0108:
    beqz           t3,    .CC1C2FL0109
    or             a7,    zero, zero
    or             t0,    zero, zero
    b              .CC1C2FL01100
.CC1C2FL0109:
    andi           t0,    a7,   3
    srai.d         a7,    a7,   2

.CC1C2FL01100:
    vpickve2gr.hu  t3,    vr3,  3
    COSTC1C2FLAG_CALC_BASECTXMOD_AND_SUM t0, t3, a2, t5, t6, a4, t4, t7
    ori            t4,    zero, 3
    add.d          t7,    t3,   a6
    bne            t7,    t4,   .CC1C2FL0110
    vpickve2gr.hu  a6,    vr4,  3
.CC1C2FL0110:
    ori            t4,    zero, 9
    add.d          t7,    t3,   a5
    bne            t7,    t4,   .CC1C2FL0111
    addi.d         a5,    t8,   3
.CC1C2FL0111:
    beqz           t3,    .CC1C2FL0112
    or             a7,    zero, zero
    or             t0,    zero, zero
    b              .CC1C2FL0113
.CC1C2FL0112:
    andi           t0,    a7,   3
    srai.d         a7,    a7,   2

.CC1C2FL0113:
    addi.d         t1,    t1,   8
    addi.d         t2,    t2,   -1
    bnez           t2,    .CC1C2FL01

.CC1C2FL02: //2
    andi           t7,    a1,   2
    beqz           t7,    .CC1C2FL03

    fldx.d         f0,    a0,   t1
    vslt.hu        vr3,   vr1,  vr0
    vslt.hu        vr4,   vr2,  vr0
    vneg.h         vr3,   vr3  //symbol1
    vneg.h         vr4,   vr4  //symbol2
    srai.d         t8,    t1,   1

    vpickve2gr.hu  t3,    vr3,  0
    COSTC1C2FLAG_CALC_BASECTXMOD_AND_SUM t0, t3, a2, t5, t6, a4, t4, t7
    ori            t4,    zero, 3
    add.d          t7,    t3,   a6
    bne            t7,    t4,   .CC1C2FL0201
    vpickve2gr.hu  a6,    vr4,  0
.CC1C2FL0201:
    ori            t4,    zero, 9
    add.d          t7,    t3,   a5
    bne            t7,    t4,   .CC1C2FL0202
    or             a5,    t8,   t8
.CC1C2FL0202:
    beqz           t3,    .CC1C2FL0203
    or             a7,    zero, zero
.CC1C2FL0203:
    andi           t0,    a7,   3
    srai.d         a7,    a7,   2

    vpickve2gr.hu  t3,    vr3,  1
    COSTC1C2FLAG_CALC_BASECTXMOD_AND_SUM t0, t3, a2, t5, t6, a4, t4, t7
    ori            t4,    zero, 3
    add.d          t7,    t3,   a6
    bne            t7,    t4,   .CC1C2FL0204
    vpickve2gr.hu  a6,    vr4,  1
.CC1C2FL0204:
    ori            t4,    zero, 9
    add.d          t7,    t3,   a5
    bne            t7,    t4,   .CC1C2FL0205
    addi.d         a5,    t8,   1
.CC1C2FL0205:
    beqz           t3,    .CC1C2FL0206
    or             a7,    zero, zero
.CC1C2FL0206:
    andi           t0,    a7,   3
    srai.d         a7,    a7,   2

    addi.d         t1,    t1,   4

.CC1C2FL03: //1
    andi           t7,    a1,   1
    beqz           t7,    .CC1C2FL04

.CC1C2FL030:
    fldx.d         f0,    a0,   t1
    vslt.hu        vr3,   vr1,  vr0
    vslt.hu        vr4,   vr2,  vr0
    vneg.h         vr3,   vr3  //symbol1
    vneg.h         vr4,   vr4  //symbol2
    srai.d         t8,    t1,   1

    vpickve2gr.hu  t3,    vr3,  0
    COSTC1C2FLAG_CALC_BASECTXMOD_AND_SUM t0, t3, a2, t5, t6, a4, t4, t7
    ori            t4,    zero, 3
    add.d          t7,    t3,   a6
    bne            t7,    t4,   .CC1C2FL0301
    vpickve2gr.hu  a6,    vr4,  0
.CC1C2FL0301:
    ori            t4,    zero, 9
    add.d          t7,    t3,   a5
    bne            t7,    t4,   .CC1C2FL0302
    or             a5,    t8,   t8
.CC1C2FL0302:
    beqz           t3,    .CC1C2FL0303
    or             a7,    zero, zero
.CC1C2FL0303:
    andi           t0,    a7,   3
    srai.d         a7,    a7,   2

    addi.d         t1,    t1,   4

.CC1C2FL04: //!c1
    bnez           t0,    .CC1C2FL05
    add.d          a2,    a2,   a3
    COSTC1C2FLAG_CALC_BASECTXMOD_AND_SUM t0, a6, a2, t5, t6, a4, t4, t7

.CC1C2FL05: //return
    li.d           t1,    0x00FFFFFF
    and            t2,    a4,   t1
    slli.d         t3,    t0,   26
    slli.d         t4,    a5,   28
    add.d          a0,    t2,   t3
    add.d          a0,    a0,   t4
endfunc

.macro CCRL_CALC_SUM in0, in1, h, out0
    sra.d          \in0,  \in0, \in1
    addi.d         \in0,  \in0, -3
    blt            \in0,  zero, 1f
    addi.d         t3,    \in0, 1
    clz.w          t3,    t3
    xori           t3,    t3,   31
    add.d          \in0,  t3,   t3
1:
    addi.d         \out0, \out0,4
    add.d          \out0, \out0,\in1
    add.d          \out0, \out0,\in0

    add.d          t7,    a0,   a6
    ld.h           t2,    t7,   \h
    sll.d          t3,    t5,   \in1
    beq            t2,    t3,   2f
    blt            t2,    t3,   2f
    addi.d         t2,    \in1, 1
    srai.d         t3,    \in1, 2
    sub.d          \in1,  t2,   t3
2:
.endm

//uint32_t costCoeffRemain_lsx(uint16_t *absCoeff, int numNonZero, int idx)
//param: absCoeff:a0, numNonZero:a1, idx:a2
function x265_costCoeffRemain_lsx
    or             a3,    zero, zero //goRiceParam
    or             a4,    zero, zero //sum
    ori            t0,    zero, 3    //baseLevel0
    slli.d         a6,    a2,   1    //data indx
    ori            t4,    zero, 8    //C1FLAG_NUMBER
    ori            t5,    zero, 3    //COEF_REMAIN_BIN_REDUCTION

    sub.d          a7,    a1,   a2
    bge            zero,  a7,   .CCRL030
    srai.d         a7,    a7,   2
    add.d          a7,    a7,   a2  //loop max
    beq            a2,    a7,   .CCRL02

.CCRL01: //4
    ori            t1,    zero, 2
    ori            t2,    zero, 2
    ori            t3,    zero, 2

    srai.d         t6,    a6,   1
    blt            t6,    t4,   .CCRL0101
    ori            t0,    zero, 1
.CCRL0101:
    addi.d         t7,    t6,   1
    blt            t7,    t4,   .CCRL0102
    ori            t1,    zero, 1
.CCRL0102:
    addi.d         t7,    t6,   2
    blt            t7,    t4,   .CCRL0103
    ori            t2,    zero, 1
.CCRL0103:
    addi.d         t7,    t6,   3
    blt            t7,    t4,   .CCRL0104
    ori            t3,    zero, 1
.CCRL0104:
    vinsgr2vr.h    vr1,   t0,   0
    vinsgr2vr.h    vr1,   t1,   1
    vinsgr2vr.h    vr1,   t2,   2
    vinsgr2vr.h    vr1,   t3,   3

    fldx.d         f0,    a0,   a6
    vsub.h         vr0,   vr0,  vr1

    ori            t0,    zero, 2

    vpickve2gr.h   t1,    vr0,  0  //codeNumber0
    blt            t1,    zero, .CCRL0105
    CCRL_CALC_SUM  t1,    a3,   0,   a4

.CCRL0105:
    vpickve2gr.h   t1,    vr0,  1  //codeNumber1
    blt            t1,    zero, .CCRL0106
    CCRL_CALC_SUM  t1,    a3,   2,   a4

.CCRL0106:
    vpickve2gr.h   t1,    vr0,  2  //codeNumber2
    blt            t1,    zero, .CCRL0107
    CCRL_CALC_SUM  t1,    a3,   4,   a4

.CCRL0107:
    vpickve2gr.h   t1,    vr0,  3  //codeNumber3
    blt            t1,    zero, .CCRL0108
    CCRL_CALC_SUM  t1,    a3,   6,   a4

.CCRL0108:
    addi.d         a6,    a6,   8
    addi.d         a7,    a7,   -1
    blt            a2,    a7,   .CCRL01

.CCRL02: //2
    sub.d          t2,    a1,   a2
    bge            zero,  t2,   .CCRL03
    andi           t2,    t2,   2
    beqz           t2,    .CCRL03

    ori            t1,    zero, 2

    srai.d         t6,    a6,   1
    blt            t6,    t4,   .CCRL0201
    ori            t0,    zero, 1
.CCRL0201:
    addi.d         t6,    t6,   1
    blt            t6,    t4,   .CCRL0202
    ori            t1,    zero, 1
.CCRL0202:
    vinsgr2vr.h    vr1,   t0,   0
    vinsgr2vr.h    vr1,   t1,   1

    fldx.s         f0,    a0,   a6
    vsub.h         vr0,   vr0,  vr1

    ori            t0,    zero, 2

    vpickve2gr.h   t1,    vr0,  0  //codeNumber0
    blt            t1,    zero, .CCRL0205
    CCRL_CALC_SUM  t1,    a3,   0,   a4

.CCRL0205:
    vpickve2gr.h   t1,    vr0,  1  //codeNumber1
    blt            t1,    zero, .CCRL0206
    CCRL_CALC_SUM  t1,    a3,   2,   a4

.CCRL0206:
    addi.d         a6,    a6,   4

.CCRL03:  //1
    sub.d          t2,    a1,   a2
    bge            zero,  t2,   .CCRL04
    andi           t2,    t2,   1
    beqz           t2,    .CCRL04
.CCRL030:
    srai.d         t6,    a6,   1
    blt            t6,    t4,   .CCRL0301
    ori            t0,    zero, 1
.CCRL0301:
    ldx.h          t2,    a0,   a6
    sub.w          t1,    t2,   t0

    ori            t0,    zero, 2

    blt            t1,    zero, .CCRL0305
    CCRL_CALC_SUM  t1,    a3,   0,   a4

.CCRL0305:
    addi.d         a6,    a6,   2

.CCRL04:
    or             a0,    a4,   a4
endfunc

//uint32_t findPosFirstLast_c(const int16_t *dstCoeff, const intptr_t trSize, const uint16_t scanTbl[16]);
//param: dstCoeff: a0, trSize: a1, scanTbl[16]: a2
function x265_findPosFirstLast_lasx
    slli.d         a1,    a1,   1   //trSize
    add.d          a3,    a1,   a1  //trSize * 2
    add.d          a4,    a3,   a1  //trSize * 3
    fld.d          f1,    a0,   0
    fldx.d         f2,    a0,   a1
    fldx.d         f3,    a0,   a3
    fldx.d         f4,    a0,   a4

    vpermi.w       vr2,   vr1,  0x44
    vpermi.w       vr4,   vr3,  0x44
    xvpermi.d      xr2,   xr2,  0x44
    xvpermi.d      xr4,   xr4,  0x44

    xvld           xr5,   a2,   0
    xvshuf.h       xr5,   xr4,  xr2

    xvhaddw.w.h    xr6,   xr5,  xr5
    xvhaddw.d.w    xr6,   xr6,  xr6
    xvhaddw.q.d    xr6,   xr6,  xr6
    xvpermi.q      xr7,   xr6,  0x01

    vadd.q         vr6,   vr6,  vr7
    vpickve2gr.d   a3,    vr6,  0  //absSumSign

    // calc lastNZPosInCG firstNZPosInCG
    xvxor.v        xr1,   xr1,  xr1
    xvabsd.h       xr2,   xr5,  xr1
    xvneg.h        xr2,   xr2
    xvmskltz.h     xr2,   xr2
    vpickve2gr.h   a4,    vr2,  0
    xvpermi.q      xr2,   xr2,  0x01
    vpickve2gr.h   a7,    vr2,  0

    ctz.w          t0,    a4   //firstNZPosInCG 1
    or             t1,    zero, zero
    addi.w         t2,    t0,   -32
    bnez           t2,    1f
    li.d           t0,    8
    ctz.w          t1,    a7   //firstNZPosInCG 2
    addi.w         t2,    t1,   -32
    bnez           t2,    1f
    li.d           t1,    8
1:
    add.w          a6,    t0,   t1

    clz.w          t0,    a7   //lastNZPosInCG 2
    addi.w         t0,    t0,   -24
    or             t1,    zero, zero
    li.d           t2,    8
    bne            t2,    t0,   2f
    clz.w          t1,    a4   //lastNZPosInCG 1
    addi.w         t1,    t1,   -24
2:
    add.w          a5,    t0,   t1
    li.d           a7,    15
    sub.w          a5,    a7,  a5

    bge            a5,    zero, 3f
    li.d           a5,    0xffffffff
3:
    andi           t0,    a3,   1
    beqz           t0,    4f
    li.w           t0,    0x80000000
4:
    li.d           t1,    0xffffff
    and            a5,    a5,   t1
    slli.d         t2,    a5,   8
    or             a7,    t0,   t2
    or             a0,    a7,   a6
endfunc

function x265_findPosFirstLast_lsx
    slli.d         a1,    a1,   1   //trSize
    add.d          a3,    a1,   a1  //trSize * 2
    add.d          a4,    a3,   a1  //trSize * 3
    fld.d          f1,    a0,   0
    fldx.d         f2,    a0,   a1
    fldx.d         f3,    a0,   a3
    fldx.d         f4,    a0,   a4

    vpermi.w       vr2,   vr1,  0x44
    vpermi.w       vr4,   vr3,  0x44

    vld            vr5,   a2,   0
    vld            vr3,   a2,   16

    vshuf.h        vr5,   vr4,  vr2
    vshuf.h        vr3,   vr4,  vr2

    vhaddw.w.h     vr6,   vr5,  vr5
    vhaddw.d.w     vr6,   vr6,  vr6
    vhaddw.q.d     vr6,   vr6,  vr6

    vhaddw.w.h     vr7,   vr3,  vr3
    vhaddw.d.w     vr7,   vr7,  vr7
    vhaddw.q.d     vr7,   vr7,  vr7

    vadd.q         vr6,   vr6,  vr7
    vpickve2gr.d   a3,    vr6,  0  //absSumSign

    // calc lastNZPosInCG firstNZPosInCG
    vxor.v         vr1,   vr1,  vr1
    vabsd.h        vr2,   vr5,  vr1
    vneg.h         vr2,   vr2
    vmskltz.h      vr2,   vr2
    vpickve2gr.h   a4,    vr2,  0
    vabsd.h        vr2,   vr3,  vr1
    vneg.h         vr2,   vr2
    vmskltz.h      vr2,   vr2
    vpickve2gr.h   a7,    vr2,  0

    ctz.w          t0,    a4   //firstNZPosInCG 1
    or             t1,    zero, zero
    addi.w         t2,    t0,   -32
    bnez           t2,    1f
    li.d           t0,    8
    ctz.w          t1,    a7   //firstNZPosInCG 2
    addi.w         t2,    t1,   -32
    bnez           t2,    1f
    li.d           t1,    8
1:
    add.w          a6,    t0,   t1

    clz.w          t0,    a7   //lastNZPosInCG 2
    addi.w         t0,    t0,   -24
    or             t1,    zero, zero
    li.d           t2,    8
    bne            t2,    t0,   2f
    clz.w          t1,    a4   //lastNZPosInCG 1
    addi.w         t1,    t1,   -24
2:
    add.w          a5,    t0,   t1
    li.d           a7,    15
    sub.w          a5,    a7,  a5

    bge            a5,    zero, 3f
    li.d           a5,    0xffffffff
3:
    andi           t0,    a3,   1
    beqz           t0,    4f
    li.w           t0,    0x80000000
4:
    li.d           t1,    0xffffff
    and            a5,    a5,   t1
    slli.d         t2,    a5,   8
    or             a7,    t0,   t2
    or             a0,    a7,   a6
endfunc

//void x265_denoiseDct_lsx(int16_t* dctCoef, uint32_t* resSum, const uint16_t* offset, int numCoeff)
function x265_denoiseDct_lsx
    vxor.v         vr4,   vr4,  vr4
    or             a4,    zero, zero  //data index
    srai.d         a5,    a3,   2     //loop param

    beqz           a5,    2f

1: // /4
    slli.d         a6,    a4,   1
    fldx.d         f0,    a0,   a4  //level
    vsllwil.w.h    vr7,   vr0,  0

    vsrai.w        vr1,   vr7,  31 //sign
    vadd.w         vr7,   vr7,  vr1
    vxor.v         vr7,   vr7,  vr1

    vldx           vr2,   a1,   a6  //resSum
    vadd.w         vr2,   vr2,  vr7
    vstx           vr2,   a1,   a6

    vldx           vr9,   a2,   a4  //offset
    vsllwil.wu.hu  vr3,   vr9,  0
    vsub.w         vr7,   vr7,  vr3

    vxor.v         vr8,   vr7,  vr1  //level l
    vsub.w         vr8,   vr8,  vr1

    vsle.w         vr0,   vr7,  vr4
    vbitsel.v      vr0,   vr8,  vr4,  vr0
    vsrlni.h.w     vr2,   vr0,  0

    fstx.d         f2,    a0,   a4

    addi.d         a4,    a4,   8
    addi.d         a5,    a5,   -1
    blt            zero,  a5,   1b

2:
endfunc

function x265_denoiseDct_lasx
    xvxor.v        xr4,   xr4,  xr4
    or             a4,    zero, zero  //data index
    srai.d         a5,    a3,   3     //loop param

    beqz           a5,    2f

1: // /8
    slli.d         a6,    a4,   1
    vldx           vr0,   a0,   a4  //level
    xvpermi.d      xr0,   xr0,  0x10
    xvsllwil.w.h   xr7,   xr0,  0

    xvsrai.w       xr1,   xr7,  31 //sign
    xvadd.w        xr7,   xr7,  xr1
    xvxor.v        xr7,   xr7,  xr1

    xvldx          xr2,   a1,   a6  //resSum
    xvadd.w        xr2,   xr2,  xr7
    xvstx          xr2,   a1,   a6

    vldx           vr9,   a2,   a4  //offset
    xvpermi.d      xr9,   xr9,  0x10
    xvsllwil.wu.hu xr3,   xr9,  0
    xvsub.w        xr7,   xr7,  xr3

    xvxor.v        xr8,   xr7,  xr1  //level l
    xvsub.w        xr8,   xr8,  xr1

    xvsle.w        xr0,   xr7,  xr4
    xvbitsel.v     xr0,   xr8,  xr4,  xr0
    xvsran.h.w     xr2,   xr0,  xr4
    xvpermi.d      xr2,   xr2,  0x08

    vstx           vr2,   a0,   a4

    addi.d         a4,    a4,   16
    addi.d         a5,    a5,   -1
    blt            zero,  a5,   1b

2:
    andi           a5,    a3,   4
    beqz           a5,    3f

    slli.d         a6,    a4,   1
    fldx.d         f0,    a0,   a4  //level
    vsllwil.w.h    vr7,   vr0,  0

    vsra.w         vr1,   vr7,  vr6 //sign
    vadd.w         vr7,   vr7,  vr1
    vxor.v         vr7,   vr7,  vr1

    vldx           vr2,   a1,   a6  //resSum
    vadd.w         vr2,   vr2,  vr7
    vstx           vr2,   a1,   a6

    vldx           vr9,   a2,   a4  //offset
    vsllwil.wu.hu  vr3,   vr9,  0
    vsub.w         vr7,   vr7,  vr3

    vxor.v         vr8,   vr7,  vr1  //level l
    vsub.w         vr8,   vr8,  vr1

    vsle.w         vr0,   vr7,  vr4
    vbitsel.v      vr0,   vr8,  vr4,  vr0
    vsrlni.h.w     vr2,   vr0,  0

    fstx.d         f2,    a0,   a4

    addi.d         a4,    a4,   8
3:
endfunc
