1/* 2 * Loongson LASX optimized h264dsp 3 * 4 * Copyright (c) 2021 Loongson Technology Corporation Limited 5 * Contributed by Shiyou Yin <yinshiyou-hf@loongson.cn> 6 * Xiwei Gu <guxiwei-hf@loongson.cn> 7 * 8 * This file is part of FFmpeg. 9 * 10 * FFmpeg is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * FFmpeg is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with FFmpeg; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25#include "libavutil/loongarch/loongson_intrinsics.h" 26#include "h264dsp_lasx.h" 27#include "libavcodec/bit_depth_template.c" 28 29#define AVC_ITRANS_H(in0, in1, in2, in3, out0, out1, out2, out3) \ 30{ \ 31 __m256i tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ 32 \ 33 tmp0_m = __lasx_xvadd_h(in0, in2); \ 34 tmp1_m = __lasx_xvsub_h(in0, in2); \ 35 tmp2_m = __lasx_xvsrai_h(in1, 1); \ 36 tmp2_m = __lasx_xvsub_h(tmp2_m, in3); \ 37 tmp3_m = __lasx_xvsrai_h(in3, 1); \ 38 tmp3_m = __lasx_xvadd_h(in1, tmp3_m); \ 39 \ 40 LASX_BUTTERFLY_4_H(tmp0_m, tmp1_m, tmp2_m, tmp3_m, \ 41 out0, out1, out2, out3); \ 42} 43 44void ff_h264_idct_add_lasx(uint8_t *dst, int16_t *src, int32_t dst_stride) 45{ 46 __m256i src0_m, src1_m, src2_m, src3_m; 47 __m256i dst0_m, dst1_m; 48 __m256i hres0, hres1, hres2, hres3, vres0, vres1, vres2, vres3; 49 __m256i inp0_m, inp1_m, res0_m, src1, src3; 50 __m256i src0 = __lasx_xvld(src, 0); 51 __m256i src2 = __lasx_xvld(src, 16); 52 __m256i zero = __lasx_xvldi(0); 53 int32_t dst_stride_2x = dst_stride << 1; 54 int32_t dst_stride_3x = dst_stride_2x + dst_stride; 55 56 __lasx_xvst(zero, src, 0); 57 DUP2_ARG2(__lasx_xvilvh_d, src0, src0, src2, src2, src1, src3); 58 AVC_ITRANS_H(src0, src1, src2, src3, hres0, hres1, hres2, hres3); 59 LASX_TRANSPOSE4x4_H(hres0, hres1, hres2, hres3, hres0, hres1, hres2, hres3); 60 AVC_ITRANS_H(hres0, hres1, hres2, hres3, vres0, vres1, vres2, vres3); 61 DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, 62 dst, dst_stride_3x, src0_m, src1_m, src2_m, src3_m); 63 DUP4_ARG2(__lasx_xvld, dst, 0, dst + dst_stride, 0, dst + dst_stride_2x, 64 0, dst + dst_stride_3x, 0, src0_m, src1_m, src2_m, src3_m); 65 DUP2_ARG2(__lasx_xvilvl_d, vres1, vres0, vres3, vres2, inp0_m, inp1_m); 66 inp0_m = __lasx_xvpermi_q(inp1_m, inp0_m, 0x20); 67 inp0_m = __lasx_xvsrari_h(inp0_m, 6); 68 DUP2_ARG2(__lasx_xvilvl_w, src1_m, src0_m, src3_m, src2_m, dst0_m, dst1_m); 69 dst0_m = __lasx_xvilvl_d(dst1_m, dst0_m); 70 res0_m = __lasx_vext2xv_hu_bu(dst0_m); 71 res0_m = __lasx_xvadd_h(res0_m, inp0_m); 72 res0_m = __lasx_xvclip255_h(res0_m); 73 dst0_m = __lasx_xvpickev_b(res0_m, res0_m); 74 __lasx_xvstelm_w(dst0_m, dst, 0, 0); 75 __lasx_xvstelm_w(dst0_m, dst + dst_stride, 0, 1); 76 __lasx_xvstelm_w(dst0_m, dst + dst_stride_2x, 0, 4); 77 __lasx_xvstelm_w(dst0_m, dst + dst_stride_3x, 0, 5); 78} 79 80void ff_h264_idct8_addblk_lasx(uint8_t *dst, int16_t *src, 81 int32_t dst_stride) 82{ 83 __m256i src0, src1, src2, src3, src4, src5, src6, src7; 84 __m256i vec0, vec1, vec2, vec3; 85 __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; 86 __m256i res0, res1, res2, res3, res4, res5, res6, res7; 87 __m256i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; 88 __m256i zero = __lasx_xvldi(0); 89 int32_t dst_stride_2x = dst_stride << 1; 90 int32_t dst_stride_4x = dst_stride << 2; 91 int32_t dst_stride_3x = dst_stride_2x + dst_stride; 92 93 src[0] += 32; 94 DUP4_ARG2(__lasx_xvld, src, 0, src, 16, src, 32, src, 48, 95 src0, src1, src2, src3); 96 DUP4_ARG2(__lasx_xvld, src, 64, src, 80, src, 96, src, 112, 97 src4, src5, src6, src7); 98 __lasx_xvst(zero, src, 0); 99 __lasx_xvst(zero, src, 32); 100 __lasx_xvst(zero, src, 64); 101 __lasx_xvst(zero, src, 96); 102 103 vec0 = __lasx_xvadd_h(src0, src4); 104 vec1 = __lasx_xvsub_h(src0, src4); 105 vec2 = __lasx_xvsrai_h(src2, 1); 106 vec2 = __lasx_xvsub_h(vec2, src6); 107 vec3 = __lasx_xvsrai_h(src6, 1); 108 vec3 = __lasx_xvadd_h(src2, vec3); 109 110 LASX_BUTTERFLY_4_H(vec0, vec1, vec2, vec3, tmp0, tmp1, tmp2, tmp3); 111 112 vec0 = __lasx_xvsrai_h(src7, 1); 113 vec0 = __lasx_xvsub_h(src5, vec0); 114 vec0 = __lasx_xvsub_h(vec0, src3); 115 vec0 = __lasx_xvsub_h(vec0, src7); 116 117 vec1 = __lasx_xvsrai_h(src3, 1); 118 vec1 = __lasx_xvsub_h(src1, vec1); 119 vec1 = __lasx_xvadd_h(vec1, src7); 120 vec1 = __lasx_xvsub_h(vec1, src3); 121 122 vec2 = __lasx_xvsrai_h(src5, 1); 123 vec2 = __lasx_xvsub_h(vec2, src1); 124 vec2 = __lasx_xvadd_h(vec2, src7); 125 vec2 = __lasx_xvadd_h(vec2, src5); 126 127 vec3 = __lasx_xvsrai_h(src1, 1); 128 vec3 = __lasx_xvadd_h(src3, vec3); 129 vec3 = __lasx_xvadd_h(vec3, src5); 130 vec3 = __lasx_xvadd_h(vec3, src1); 131 132 tmp4 = __lasx_xvsrai_h(vec3, 2); 133 tmp4 = __lasx_xvadd_h(tmp4, vec0); 134 tmp5 = __lasx_xvsrai_h(vec2, 2); 135 tmp5 = __lasx_xvadd_h(tmp5, vec1); 136 tmp6 = __lasx_xvsrai_h(vec1, 2); 137 tmp6 = __lasx_xvsub_h(tmp6, vec2); 138 tmp7 = __lasx_xvsrai_h(vec0, 2); 139 tmp7 = __lasx_xvsub_h(vec3, tmp7); 140 141 LASX_BUTTERFLY_8_H(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, 142 res0, res1, res2, res3, res4, res5, res6, res7); 143 LASX_TRANSPOSE8x8_H(res0, res1, res2, res3, res4, res5, res6, res7, 144 res0, res1, res2, res3, res4, res5, res6, res7); 145 146 DUP4_ARG1(__lasx_vext2xv_w_h, res0, res1, res2, res3, 147 tmp0, tmp1, tmp2, tmp3); 148 DUP4_ARG1(__lasx_vext2xv_w_h, res4, res5, res6, res7, 149 tmp4, tmp5, tmp6, tmp7); 150 vec0 = __lasx_xvadd_w(tmp0, tmp4); 151 vec1 = __lasx_xvsub_w(tmp0, tmp4); 152 153 vec2 = __lasx_xvsrai_w(tmp2, 1); 154 vec2 = __lasx_xvsub_w(vec2, tmp6); 155 vec3 = __lasx_xvsrai_w(tmp6, 1); 156 vec3 = __lasx_xvadd_w(vec3, tmp2); 157 158 tmp0 = __lasx_xvadd_w(vec0, vec3); 159 tmp2 = __lasx_xvadd_w(vec1, vec2); 160 tmp4 = __lasx_xvsub_w(vec1, vec2); 161 tmp6 = __lasx_xvsub_w(vec0, vec3); 162 163 vec0 = __lasx_xvsrai_w(tmp7, 1); 164 vec0 = __lasx_xvsub_w(tmp5, vec0); 165 vec0 = __lasx_xvsub_w(vec0, tmp3); 166 vec0 = __lasx_xvsub_w(vec0, tmp7); 167 168 vec1 = __lasx_xvsrai_w(tmp3, 1); 169 vec1 = __lasx_xvsub_w(tmp1, vec1); 170 vec1 = __lasx_xvadd_w(vec1, tmp7); 171 vec1 = __lasx_xvsub_w(vec1, tmp3); 172 173 vec2 = __lasx_xvsrai_w(tmp5, 1); 174 vec2 = __lasx_xvsub_w(vec2, tmp1); 175 vec2 = __lasx_xvadd_w(vec2, tmp7); 176 vec2 = __lasx_xvadd_w(vec2, tmp5); 177 178 vec3 = __lasx_xvsrai_w(tmp1, 1); 179 vec3 = __lasx_xvadd_w(tmp3, vec3); 180 vec3 = __lasx_xvadd_w(vec3, tmp5); 181 vec3 = __lasx_xvadd_w(vec3, tmp1); 182 183 tmp1 = __lasx_xvsrai_w(vec3, 2); 184 tmp1 = __lasx_xvadd_w(tmp1, vec0); 185 tmp3 = __lasx_xvsrai_w(vec2, 2); 186 tmp3 = __lasx_xvadd_w(tmp3, vec1); 187 tmp5 = __lasx_xvsrai_w(vec1, 2); 188 tmp5 = __lasx_xvsub_w(tmp5, vec2); 189 tmp7 = __lasx_xvsrai_w(vec0, 2); 190 tmp7 = __lasx_xvsub_w(vec3, tmp7); 191 192 LASX_BUTTERFLY_4_W(tmp0, tmp2, tmp5, tmp7, res0, res1, res6, res7); 193 LASX_BUTTERFLY_4_W(tmp4, tmp6, tmp1, tmp3, res2, res3, res4, res5); 194 195 DUP4_ARG2(__lasx_xvsrai_w, res0, 6, res1, 6, res2, 6, res3, 6, 196 res0, res1, res2, res3); 197 DUP4_ARG2(__lasx_xvsrai_w, res4, 6, res5, 6, res6, 6, res7, 6, 198 res4, res5, res6, res7); 199 DUP4_ARG2(__lasx_xvpickev_h, res1, res0, res3, res2, res5, res4, res7, 200 res6, res0, res1, res2, res3); 201 DUP4_ARG2(__lasx_xvpermi_d, res0, 0xd8, res1, 0xd8, res2, 0xd8, res3, 0xd8, 202 res0, res1, res2, res3); 203 204 DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, 205 dst, dst_stride_3x, dst0, dst1, dst2, dst3); 206 dst += dst_stride_4x; 207 DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, 208 dst, dst_stride_3x, dst4, dst5, dst6, dst7); 209 dst -= dst_stride_4x; 210 DUP4_ARG2(__lasx_xvilvl_b, zero, dst0, zero, dst1, zero, dst2, zero, dst3, 211 dst0, dst1, dst2, dst3); 212 DUP4_ARG2(__lasx_xvilvl_b, zero, dst4, zero, dst5, zero, dst6, zero, dst7, 213 dst4, dst5, dst6, dst7); 214 DUP4_ARG3(__lasx_xvpermi_q, dst1, dst0, 0x20, dst3, dst2, 0x20, dst5, 215 dst4, 0x20, dst7, dst6, 0x20, dst0, dst1, dst2, dst3); 216 res0 = __lasx_xvadd_h(res0, dst0); 217 res1 = __lasx_xvadd_h(res1, dst1); 218 res2 = __lasx_xvadd_h(res2, dst2); 219 res3 = __lasx_xvadd_h(res3, dst3); 220 DUP4_ARG1(__lasx_xvclip255_h, res0, res1, res2, res3, res0, res1, 221 res2, res3); 222 DUP2_ARG2(__lasx_xvpickev_b, res1, res0, res3, res2, res0, res1); 223 __lasx_xvstelm_d(res0, dst, 0, 0); 224 __lasx_xvstelm_d(res0, dst + dst_stride, 0, 2); 225 __lasx_xvstelm_d(res0, dst + dst_stride_2x, 0, 1); 226 __lasx_xvstelm_d(res0, dst + dst_stride_3x, 0, 3); 227 dst += dst_stride_4x; 228 __lasx_xvstelm_d(res1, dst, 0, 0); 229 __lasx_xvstelm_d(res1, dst + dst_stride, 0, 2); 230 __lasx_xvstelm_d(res1, dst + dst_stride_2x, 0, 1); 231 __lasx_xvstelm_d(res1, dst + dst_stride_3x, 0, 3); 232} 233 234void ff_h264_idct4x4_addblk_dc_lasx(uint8_t *dst, int16_t *src, 235 int32_t dst_stride) 236{ 237 const int16_t dc = (src[0] + 32) >> 6; 238 int32_t dst_stride_2x = dst_stride << 1; 239 int32_t dst_stride_3x = dst_stride_2x + dst_stride; 240 __m256i pred, out; 241 __m256i src0, src1, src2, src3; 242 __m256i input_dc = __lasx_xvreplgr2vr_h(dc); 243 244 src[0] = 0; 245 DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, 246 dst, dst_stride_3x, src0, src1, src2, src3); 247 DUP2_ARG2(__lasx_xvilvl_w, src1, src0, src3, src2, src0, src1); 248 249 pred = __lasx_xvpermi_q(src0, src1, 0x02); 250 pred = __lasx_xvaddw_h_h_bu(input_dc, pred); 251 pred = __lasx_xvclip255_h(pred); 252 out = __lasx_xvpickev_b(pred, pred); 253 __lasx_xvstelm_w(out, dst, 0, 0); 254 __lasx_xvstelm_w(out, dst + dst_stride, 0, 1); 255 __lasx_xvstelm_w(out, dst + dst_stride_2x, 0, 4); 256 __lasx_xvstelm_w(out, dst + dst_stride_3x, 0, 5); 257} 258 259void ff_h264_idct8_dc_addblk_lasx(uint8_t *dst, int16_t *src, 260 int32_t dst_stride) 261{ 262 int32_t dc_val; 263 int32_t dst_stride_2x = dst_stride << 1; 264 int32_t dst_stride_4x = dst_stride << 2; 265 int32_t dst_stride_3x = dst_stride_2x + dst_stride; 266 __m256i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; 267 __m256i dc; 268 269 dc_val = (src[0] + 32) >> 6; 270 dc = __lasx_xvreplgr2vr_h(dc_val); 271 272 src[0] = 0; 273 274 DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, 275 dst, dst_stride_3x, dst0, dst1, dst2, dst3); 276 dst += dst_stride_4x; 277 DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, 278 dst, dst_stride_3x, dst4, dst5, dst6, dst7); 279 dst -= dst_stride_4x; 280 DUP4_ARG1(__lasx_vext2xv_hu_bu, dst0, dst1, dst2, dst3, 281 dst0, dst1, dst2, dst3); 282 DUP4_ARG1(__lasx_vext2xv_hu_bu, dst4, dst5, dst6, dst7, 283 dst4, dst5, dst6, dst7); 284 DUP4_ARG3(__lasx_xvpermi_q, dst1, dst0, 0x20, dst3, dst2, 0x20, dst5, 285 dst4, 0x20, dst7, dst6, 0x20, dst0, dst1, dst2, dst3); 286 dst0 = __lasx_xvadd_h(dst0, dc); 287 dst1 = __lasx_xvadd_h(dst1, dc); 288 dst2 = __lasx_xvadd_h(dst2, dc); 289 dst3 = __lasx_xvadd_h(dst3, dc); 290 DUP4_ARG1(__lasx_xvclip255_h, dst0, dst1, dst2, dst3, 291 dst0, dst1, dst2, dst3); 292 DUP2_ARG2(__lasx_xvpickev_b, dst1, dst0, dst3, dst2, dst0, dst1); 293 __lasx_xvstelm_d(dst0, dst, 0, 0); 294 __lasx_xvstelm_d(dst0, dst + dst_stride, 0, 2); 295 __lasx_xvstelm_d(dst0, dst + dst_stride_2x, 0, 1); 296 __lasx_xvstelm_d(dst0, dst + dst_stride_3x, 0, 3); 297 dst += dst_stride_4x; 298 __lasx_xvstelm_d(dst1, dst, 0, 0); 299 __lasx_xvstelm_d(dst1, dst + dst_stride, 0, 2); 300 __lasx_xvstelm_d(dst1, dst + dst_stride_2x, 0, 1); 301 __lasx_xvstelm_d(dst1, dst + dst_stride_3x, 0, 3); 302} 303 304void ff_h264_idct_add16_lasx(uint8_t *dst, 305 const int32_t *blk_offset, 306 int16_t *block, int32_t dst_stride, 307 const uint8_t nzc[15 * 8]) 308{ 309 int32_t i; 310 311 for (i = 0; i < 16; i++) { 312 int32_t nnz = nzc[scan8[i]]; 313 314 if (nnz) { 315 if (nnz == 1 && ((dctcoef *) block)[i * 16]) 316 ff_h264_idct4x4_addblk_dc_lasx(dst + blk_offset[i], 317 block + i * 16 * sizeof(pixel), 318 dst_stride); 319 else 320 ff_h264_idct_add_lasx(dst + blk_offset[i], 321 block + i * 16 * sizeof(pixel), 322 dst_stride); 323 } 324 } 325} 326 327void ff_h264_idct8_add4_lasx(uint8_t *dst, const int32_t *blk_offset, 328 int16_t *block, int32_t dst_stride, 329 const uint8_t nzc[15 * 8]) 330{ 331 int32_t cnt; 332 333 for (cnt = 0; cnt < 16; cnt += 4) { 334 int32_t nnz = nzc[scan8[cnt]]; 335 336 if (nnz) { 337 if (nnz == 1 && ((dctcoef *) block)[cnt * 16]) 338 ff_h264_idct8_dc_addblk_lasx(dst + blk_offset[cnt], 339 block + cnt * 16 * sizeof(pixel), 340 dst_stride); 341 else 342 ff_h264_idct8_addblk_lasx(dst + blk_offset[cnt], 343 block + cnt * 16 * sizeof(pixel), 344 dst_stride); 345 } 346 } 347} 348 349 350void ff_h264_idct_add8_lasx(uint8_t **dst, 351 const int32_t *blk_offset, 352 int16_t *block, int32_t dst_stride, 353 const uint8_t nzc[15 * 8]) 354{ 355 int32_t i; 356 357 for (i = 16; i < 20; i++) { 358 if (nzc[scan8[i]]) 359 ff_h264_idct_add_lasx(dst[0] + blk_offset[i], 360 block + i * 16 * sizeof(pixel), 361 dst_stride); 362 else if (((dctcoef *) block)[i * 16]) 363 ff_h264_idct4x4_addblk_dc_lasx(dst[0] + blk_offset[i], 364 block + i * 16 * sizeof(pixel), 365 dst_stride); 366 } 367 for (i = 32; i < 36; i++) { 368 if (nzc[scan8[i]]) 369 ff_h264_idct_add_lasx(dst[1] + blk_offset[i], 370 block + i * 16 * sizeof(pixel), 371 dst_stride); 372 else if (((dctcoef *) block)[i * 16]) 373 ff_h264_idct4x4_addblk_dc_lasx(dst[1] + blk_offset[i], 374 block + i * 16 * sizeof(pixel), 375 dst_stride); 376 } 377} 378 379void ff_h264_idct_add8_422_lasx(uint8_t **dst, 380 const int32_t *blk_offset, 381 int16_t *block, int32_t dst_stride, 382 const uint8_t nzc[15 * 8]) 383{ 384 int32_t i; 385 386 for (i = 16; i < 20; i++) { 387 if (nzc[scan8[i]]) 388 ff_h264_idct_add_lasx(dst[0] + blk_offset[i], 389 block + i * 16 * sizeof(pixel), 390 dst_stride); 391 else if (((dctcoef *) block)[i * 16]) 392 ff_h264_idct4x4_addblk_dc_lasx(dst[0] + blk_offset[i], 393 block + i * 16 * sizeof(pixel), 394 dst_stride); 395 } 396 for (i = 32; i < 36; i++) { 397 if (nzc[scan8[i]]) 398 ff_h264_idct_add_lasx(dst[1] + blk_offset[i], 399 block + i * 16 * sizeof(pixel), 400 dst_stride); 401 else if (((dctcoef *) block)[i * 16]) 402 ff_h264_idct4x4_addblk_dc_lasx(dst[1] + blk_offset[i], 403 block + i * 16 * sizeof(pixel), 404 dst_stride); 405 } 406 for (i = 20; i < 24; i++) { 407 if (nzc[scan8[i + 4]]) 408 ff_h264_idct_add_lasx(dst[0] + blk_offset[i + 4], 409 block + i * 16 * sizeof(pixel), 410 dst_stride); 411 else if (((dctcoef *) block)[i * 16]) 412 ff_h264_idct4x4_addblk_dc_lasx(dst[0] + blk_offset[i + 4], 413 block + i * 16 * sizeof(pixel), 414 dst_stride); 415 } 416 for (i = 36; i < 40; i++) { 417 if (nzc[scan8[i + 4]]) 418 ff_h264_idct_add_lasx(dst[1] + blk_offset[i + 4], 419 block + i * 16 * sizeof(pixel), 420 dst_stride); 421 else if (((dctcoef *) block)[i * 16]) 422 ff_h264_idct4x4_addblk_dc_lasx(dst[1] + blk_offset[i + 4], 423 block + i * 16 * sizeof(pixel), 424 dst_stride); 425 } 426} 427 428void ff_h264_idct_add16_intra_lasx(uint8_t *dst, 429 const int32_t *blk_offset, 430 int16_t *block, 431 int32_t dst_stride, 432 const uint8_t nzc[15 * 8]) 433{ 434 int32_t i; 435 436 for (i = 0; i < 16; i++) { 437 if (nzc[scan8[i]]) 438 ff_h264_idct_add_lasx(dst + blk_offset[i], 439 block + i * 16 * sizeof(pixel), dst_stride); 440 else if (((dctcoef *) block)[i * 16]) 441 ff_h264_idct4x4_addblk_dc_lasx(dst + blk_offset[i], 442 block + i * 16 * sizeof(pixel), 443 dst_stride); 444 } 445} 446 447void ff_h264_deq_idct_luma_dc_lasx(int16_t *dst, int16_t *src, 448 int32_t de_qval) 449{ 450#define DC_DEST_STRIDE 16 451 452 __m256i src0, src1, src2, src3; 453 __m256i vec0, vec1, vec2, vec3; 454 __m256i tmp0, tmp1, tmp2, tmp3; 455 __m256i hres0, hres1, hres2, hres3; 456 __m256i vres0, vres1, vres2, vres3; 457 __m256i de_q_vec = __lasx_xvreplgr2vr_w(de_qval); 458 459 DUP4_ARG2(__lasx_xvld, src, 0, src, 8, src, 16, src, 24, 460 src0, src1, src2, src3); 461 LASX_TRANSPOSE4x4_H(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3); 462 LASX_BUTTERFLY_4_H(tmp0, tmp2, tmp3, tmp1, vec0, vec3, vec2, vec1); 463 LASX_BUTTERFLY_4_H(vec0, vec1, vec2, vec3, hres0, hres3, hres2, hres1); 464 LASX_TRANSPOSE4x4_H(hres0, hres1, hres2, hres3, 465 hres0, hres1, hres2, hres3); 466 LASX_BUTTERFLY_4_H(hres0, hres1, hres3, hres2, vec0, vec3, vec2, vec1); 467 LASX_BUTTERFLY_4_H(vec0, vec1, vec2, vec3, vres0, vres1, vres2, vres3); 468 DUP4_ARG1(__lasx_vext2xv_w_h, vres0, vres1, vres2, vres3, 469 vres0, vres1, vres2, vres3); 470 DUP2_ARG3(__lasx_xvpermi_q, vres1, vres0, 0x20, vres3, vres2, 0x20, 471 vres0, vres1); 472 473 vres0 = __lasx_xvmul_w(vres0, de_q_vec); 474 vres1 = __lasx_xvmul_w(vres1, de_q_vec); 475 476 vres0 = __lasx_xvsrari_w(vres0, 8); 477 vres1 = __lasx_xvsrari_w(vres1, 8); 478 vec0 = __lasx_xvpickev_h(vres1, vres0); 479 vec0 = __lasx_xvpermi_d(vec0, 0xd8); 480 __lasx_xvstelm_h(vec0, dst + 0 * DC_DEST_STRIDE, 0, 0); 481 __lasx_xvstelm_h(vec0, dst + 2 * DC_DEST_STRIDE, 0, 1); 482 __lasx_xvstelm_h(vec0, dst + 8 * DC_DEST_STRIDE, 0, 2); 483 __lasx_xvstelm_h(vec0, dst + 10 * DC_DEST_STRIDE, 0, 3); 484 __lasx_xvstelm_h(vec0, dst + 1 * DC_DEST_STRIDE, 0, 4); 485 __lasx_xvstelm_h(vec0, dst + 3 * DC_DEST_STRIDE, 0, 5); 486 __lasx_xvstelm_h(vec0, dst + 9 * DC_DEST_STRIDE, 0, 6); 487 __lasx_xvstelm_h(vec0, dst + 11 * DC_DEST_STRIDE, 0, 7); 488 __lasx_xvstelm_h(vec0, dst + 4 * DC_DEST_STRIDE, 0, 8); 489 __lasx_xvstelm_h(vec0, dst + 6 * DC_DEST_STRIDE, 0, 9); 490 __lasx_xvstelm_h(vec0, dst + 12 * DC_DEST_STRIDE, 0, 10); 491 __lasx_xvstelm_h(vec0, dst + 14 * DC_DEST_STRIDE, 0, 11); 492 __lasx_xvstelm_h(vec0, dst + 5 * DC_DEST_STRIDE, 0, 12); 493 __lasx_xvstelm_h(vec0, dst + 7 * DC_DEST_STRIDE, 0, 13); 494 __lasx_xvstelm_h(vec0, dst + 13 * DC_DEST_STRIDE, 0, 14); 495 __lasx_xvstelm_h(vec0, dst + 15 * DC_DEST_STRIDE, 0, 15); 496 497#undef DC_DEST_STRIDE 498} 499