diff --git a/include/libyuv/row.h b/include/libyuv/row.h index df11bca16..ef3efa5f3 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -374,6 +374,9 @@ extern "C" { #define HAS_YUY2TOUV422ROW_MSA #define HAS_YUY2TOUVROW_MSA #define HAS_YUY2TOYROW_MSA +#define HAS_ARGB4444TOARGBROW_MSA +#define HAS_ARGBTOYROW_MSA +#define HAS_ARGBTOUVROW_MSA #endif @@ -657,10 +660,13 @@ void RGB24ToYRow_SSSE3(const uint8* src_rgb24, uint8* dst_y, int width); void RAWToYRow_SSSE3(const uint8* src_raw, uint8* dst_y, int width); void ARGBToYRow_NEON(const uint8* src_argb, uint8* dst_y, int width); void ARGBToYJRow_NEON(const uint8* src_argb, uint8* dst_y, int width); +void ARGBToYRow_MSA(const uint8* src_argb, uint8* dst_y, int width); void ARGBToUV444Row_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int width); void ARGBToUVRow_NEON(const uint8* src_argb, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width); +void ARGBToUVRow_MSA(const uint8* src_argb, int src_stride_argb, + uint8* dst_u, uint8* dst_v, int width); void ARGBToUVJRow_NEON(const uint8* src_argb, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width); void BGRAToUVRow_NEON(const uint8* src_bgra, int src_stride_bgra, @@ -716,6 +722,7 @@ void ARGB1555ToYRow_Any_NEON(const uint8* src_argb1555, uint8* dst_y, int width); void ARGB4444ToYRow_Any_NEON(const uint8* src_argb4444, uint8* dst_y, int width); +void ARGBToYRow_Any_MSA(const uint8* src_argb, uint8* dst_y, int width); void ARGBToUVRow_AVX2(const uint8* src_argb, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width); @@ -749,6 +756,8 @@ void ARGBToUV444Row_Any_NEON(const uint8* src_argb, uint8* dst_u, uint8* dst_v, int width); void ARGBToUVRow_Any_NEON(const uint8* src_argb, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width); +void ARGBToUVRow_Any_MSA(const uint8* src_argb, int src_stride_argb, + uint8* dst_u, uint8* dst_v, int width); void ARGBToUVJRow_Any_NEON(const uint8* src_argb, int src_stride_argb, uint8* dst_u, uint8* dst_v, int width); void BGRAToUVRow_Any_NEON(const uint8* src_bgra, int src_stride_bgra, @@ -954,6 +963,8 @@ void ARGB1555ToARGBRow_NEON(const uint8* src_argb1555, uint8* dst_argb, int width); void ARGB4444ToARGBRow_NEON(const uint8* src_argb4444, uint8* dst_argb, int width); +void ARGB4444ToARGBRow_MSA(const uint8* src_argb4444, uint8* dst_argb, + int width); void RGB24ToARGBRow_C(const uint8* src_rgb24, uint8* dst_argb, int width); void RAWToARGBRow_C(const uint8* src_raw, uint8* dst_argb, int width); void RAWToRGB24Row_C(const uint8* src_raw, uint8* dst_rgb24, int width); @@ -988,6 +999,8 @@ void ARGB1555ToARGBRow_Any_NEON(const uint8* src_argb1555, uint8* dst_argb, int width); void ARGB4444ToARGBRow_Any_NEON(const uint8* src_argb4444, uint8* dst_argb, int width); +void ARGB4444ToARGBRow_Any_MSA(const uint8* src_argb4444, uint8* dst_argb, + int width); void ARGBToRGB24Row_SSSE3(const uint8* src_argb, uint8* dst_rgb, int width); void ARGBToRAWRow_SSSE3(const uint8* src_argb, uint8* dst_rgb, int width); diff --git a/source/convert.cc b/source/convert.cc index ba07b3959..077ae90b6 100644 --- a/source/convert.cc +++ b/source/convert.cc @@ -532,6 +532,22 @@ int ARGBToI420(const uint8* src_argb, int src_stride_argb, } } #endif +#if defined(HAS_ARGBTOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToYRow = ARGBToYRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGBToYRow = ARGBToYRow_MSA; + } + } +#endif +#if defined(HAS_ARGBTOUVROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToUVRow = ARGBToUVRow_Any_MSA; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_MSA; + } + } +#endif for (y = 0; y < height - 1; y += 2) { ARGBToUVRow(src_argb, src_stride_argb, dst_u, dst_v, width); @@ -1283,6 +1299,14 @@ int ARGB4444ToI420(const uint8* src_argb4444, int src_stride_argb4444, } } #endif +#if defined(HAS_ARGB4444TOARGBROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA; + } + } +#endif #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { ARGBToUVRow = ARGBToUVRow_Any_SSSE3; @@ -1302,6 +1326,18 @@ int ARGB4444ToI420(const uint8* src_argb4444, int src_stride_argb4444, ARGBToYRow = ARGBToYRow_AVX2; } } +#endif +#if defined(HAS_ARGBTOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToUVRow = ARGBToUVRow_Any_MSA; + ARGBToYRow = ARGBToYRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGBToYRow = ARGBToYRow_MSA; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_MSA; + } + } + } #endif { // Allocate 2 rows of ARGB. diff --git a/source/convert_argb.cc b/source/convert_argb.cc index 947d0fc64..da48b1859 100644 --- a/source/convert_argb.cc +++ b/source/convert_argb.cc @@ -1075,6 +1075,14 @@ int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444, } } #endif +#if defined(HAS_ARGB4444TOARGBROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA; + } + } +#endif for (y = 0; y < height; ++y) { ARGB4444ToARGBRow(src_argb4444, dst_argb, width); diff --git a/source/convert_from_argb.cc b/source/convert_from_argb.cc index 73c180d40..4e409f0d6 100644 --- a/source/convert_from_argb.cc +++ b/source/convert_from_argb.cc @@ -89,6 +89,14 @@ int ARGBToI444(const uint8* src_argb, int src_stride_argb, } } #endif +#if defined(HAS_ARGBTOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToYRow = ARGBToYRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGBToYRow = ARGBToYRow_MSA; + } + } +#endif for (y = 0; y < height; ++y) { ARGBToUV444Row(src_argb, dst_u, dst_v, width); @@ -169,6 +177,22 @@ int ARGBToI422(const uint8* src_argb, int src_stride_argb, } } #endif +#if defined(HAS_ARGBTOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToYRow = ARGBToYRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGBToYRow = ARGBToYRow_MSA; + } + } +#endif +#if defined(HAS_ARGBTOUVROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToUVRow = ARGBToUVRow_Any_MSA; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_MSA; + } + } +#endif for (y = 0; y < height; ++y) { ARGBToUVRow(src_argb, 0, dst_u, dst_v, width); @@ -241,6 +265,22 @@ int ARGBToNV12(const uint8* src_argb, int src_stride_argb, } } #endif +#if defined(HAS_ARGBTOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToYRow = ARGBToYRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGBToYRow = ARGBToYRow_MSA; + } + } +#endif +#if defined(HAS_ARGBTOUVROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToUVRow = ARGBToUVRow_Any_MSA; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_MSA; + } + } +#endif #if defined(HAS_MERGEUVROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { MergeUVRow_ = MergeUVRow_Any_SSE2; @@ -350,6 +390,22 @@ int ARGBToNV21(const uint8* src_argb, int src_stride_argb, } } #endif +#if defined(HAS_ARGBTOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToYRow = ARGBToYRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGBToYRow = ARGBToYRow_MSA; + } + } +#endif +#if defined(HAS_ARGBTOUVROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToUVRow = ARGBToUVRow_Any_MSA; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_MSA; + } + } +#endif #if defined(HAS_MERGEUVROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { MergeUVRow_ = MergeUVRow_Any_SSE2; @@ -464,6 +520,22 @@ int ARGBToYUY2(const uint8* src_argb, int src_stride_argb, } } #endif +#if defined(HAS_ARGBTOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToYRow = ARGBToYRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGBToYRow = ARGBToYRow_MSA; + } + } +#endif +#if defined(HAS_ARGBTOUVROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToUVRow = ARGBToUVRow_Any_MSA; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_MSA; + } + } +#endif #if defined(HAS_I422TOYUY2ROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; @@ -574,6 +646,22 @@ int ARGBToUYVY(const uint8* src_argb, int src_stride_argb, } } #endif +#if defined(HAS_ARGBTOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToYRow = ARGBToYRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGBToYRow = ARGBToYRow_MSA; + } + } +#endif +#if defined(HAS_ARGBTOUVROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToUVRow = ARGBToUVRow_Any_MSA; + if (IS_ALIGNED(width, 32)) { + ARGBToUVRow = ARGBToUVRow_MSA; + } + } +#endif #if defined(HAS_I422TOUYVYROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; @@ -665,6 +753,14 @@ int ARGBToI400(const uint8* src_argb, int src_stride_argb, } } #endif +#if defined(HAS_ARGBTOYROW_MSA) + if (TestCpuFlag(kCpuHasMSA)) { + ARGBToYRow = ARGBToYRow_Any_MSA; + if (IS_ALIGNED(width, 16)) { + ARGBToYRow = ARGBToYRow_MSA; + } + } +#endif for (y = 0; y < height; ++y) { ARGBToYRow(src_argb, dst_y, width); diff --git a/source/row_any.cc b/source/row_any.cc index 6fd1b565e..dbed89189 100644 --- a/source/row_any.cc +++ b/source/row_any.cc @@ -402,6 +402,9 @@ ANY11(ARGBToYJRow_Any_SSSE3, ARGBToYJRow_SSSE3, 0, 4, 1, 15) #ifdef HAS_ARGBTOYROW_NEON ANY11(ARGBToYRow_Any_NEON, ARGBToYRow_NEON, 0, 4, 1, 7) #endif +#ifdef HAS_ARGBTOYROW_MSA +ANY11(ARGBToYRow_Any_MSA, ARGBToYRow_MSA, 0, 4, 1, 15) +#endif #ifdef HAS_ARGBTOYJROW_NEON ANY11(ARGBToYJRow_Any_NEON, ARGBToYJRow_NEON, 0, 4, 1, 7) #endif @@ -456,6 +459,9 @@ ANY11(ARGB1555ToARGBRow_Any_NEON, ARGB1555ToARGBRow_NEON, 0, 2, 4, 7) #ifdef HAS_ARGB4444TOARGBROW_NEON ANY11(ARGB4444ToARGBRow_Any_NEON, ARGB4444ToARGBRow_NEON, 0, 2, 4, 7) #endif +#ifdef HAS_ARGB4444TOARGBROW_MSA +ANY11(ARGB4444ToARGBRow_Any_MSA, ARGB4444ToARGBRow_MSA, 0, 2, 4, 15) +#endif #ifdef HAS_ARGBATTENUATEROW_SSSE3 ANY11(ARGBAttenuateRow_Any_SSSE3, ARGBAttenuateRow_SSSE3, 0, 4, 4, 3) #endif @@ -807,6 +813,9 @@ ANY12S(UYVYToUVRow_Any_SSE2, UYVYToUVRow_SSE2, 1, 4, 15) #ifdef HAS_ARGBTOUVROW_NEON ANY12S(ARGBToUVRow_Any_NEON, ARGBToUVRow_NEON, 0, 4, 15) #endif +#ifdef HAS_ARGBTOUVROW_MSA +ANY12S(ARGBToUVRow_Any_MSA, ARGBToUVRow_MSA, 0, 4, 31) +#endif #ifdef HAS_ARGBTOUVJROW_NEON ANY12S(ARGBToUVJRow_Any_NEON, ARGBToUVJRow_NEON, 0, 4, 15) #endif diff --git a/source/row_msa.cc b/source/row_msa.cc index acc60520a..3a55b0b75 100644 --- a/source/row_msa.cc +++ b/source/row_msa.cc @@ -221,6 +221,195 @@ void UYVYToUV422Row_MSA(const uint8* src_uyvy, uint8* dst_u, uint8* dst_v, } } +void ARGBToYRow_MSA(const uint8* src_argb0, uint8* dst_y, int width) { + int x; + v16u8 src0, src1, src2, src3, vec0, vec1, vec2, vec3, dst0; + v8u16 reg0, reg1, reg2, reg3, reg4, reg5; + v16i8 zero = { 0 }; + v8u16 const_0x19 = (v8u16) __msa_ldi_h(0x19); + v8u16 const_0x81 = (v8u16) __msa_ldi_h(0x81); + v8u16 const_0x42 = (v8u16) __msa_ldi_h(0x42); + v8u16 const_0x1080 = (v8u16) __msa_fill_h(0x1080); + + for (x = 0; x < width; x += 16) { + src0 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 0); + src1 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 16); + src2 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 32); + src3 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 48); + vec0 = (v16u8) __msa_pckev_b((v16i8) src1, (v16i8) src0); + vec1 = (v16u8) __msa_pckev_b((v16i8) src3, (v16i8) src2); + vec2 = (v16u8) __msa_pckod_b((v16i8) src1, (v16i8) src0); + vec3 = (v16u8) __msa_pckod_b((v16i8) src3, (v16i8) src2); + reg0 = (v8u16) __msa_ilvev_b(zero, (v16i8) vec0); + reg1 = (v8u16) __msa_ilvev_b(zero, (v16i8) vec1); + reg2 = (v8u16) __msa_ilvev_b(zero, (v16i8) vec2); + reg3 = (v8u16) __msa_ilvev_b(zero, (v16i8) vec3); + reg4 = (v8u16) __msa_ilvod_b(zero, (v16i8) vec0); + reg5 = (v8u16) __msa_ilvod_b(zero, (v16i8) vec1); + reg0 *= const_0x19; + reg1 *= const_0x19; + reg2 *= const_0x81; + reg3 *= const_0x81; + reg4 *= const_0x42; + reg5 *= const_0x42; + reg0 += reg2; + reg1 += reg3; + reg0 += reg4; + reg1 += reg5; + reg0 += const_0x1080; + reg1 += const_0x1080; + reg0 = (v8u16) __msa_srai_h((v8i16) reg0, 8); + reg1 = (v8u16) __msa_srai_h((v8i16) reg1, 8); + dst0 = (v16u8) __msa_pckev_b((v16i8) reg1, (v16i8) reg0); + ST_UB(dst0, dst_y); + src_argb0 += 64; + dst_y += 16; + } +} + +void ARGBToUVRow_MSA(const uint8* src_argb0, int src_stride_argb, + uint8* dst_u, uint8* dst_v, int width) { + int x; + const uint8* src_argb0_next = src_argb0 + src_stride_argb; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + v16u8 vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + v8u16 reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8, reg9; + v16u8 dst0, dst1; + v8u16 const_0x70 = (v8u16) __msa_ldi_h(0x70); + v8u16 const_0x4A = (v8u16) __msa_ldi_h(0x4A); + v8u16 const_0x26 = (v8u16) __msa_ldi_h(0x26); + v8u16 const_0x5E = (v8u16) __msa_ldi_h(0x5E); + v8u16 const_0x12 = (v8u16) __msa_ldi_h(0x12); + v8u16 const_0x8080 = (v8u16) __msa_fill_h(0x8080); + + for (x = 0; x < width; x += 32) { + src0 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 0); + src1 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 16); + src2 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 32); + src3 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 48); + src4 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 64); + src5 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 80); + src6 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 96); + src7 = (v16u8) __msa_ld_b((v16u8*) src_argb0, 112); + vec0 = (v16u8) __msa_pckev_b((v16i8) src1, (v16i8) src0); + vec1 = (v16u8) __msa_pckev_b((v16i8) src3, (v16i8) src2); + vec2 = (v16u8) __msa_pckev_b((v16i8) src5, (v16i8) src4); + vec3 = (v16u8) __msa_pckev_b((v16i8) src7, (v16i8) src6); + vec4 = (v16u8) __msa_pckod_b((v16i8) src1, (v16i8) src0); + vec5 = (v16u8) __msa_pckod_b((v16i8) src3, (v16i8) src2); + vec6 = (v16u8) __msa_pckod_b((v16i8) src5, (v16i8) src4); + vec7 = (v16u8) __msa_pckod_b((v16i8) src7, (v16i8) src6); + vec8 = (v16u8) __msa_pckev_b((v16i8) vec1, (v16i8) vec0); + vec9 = (v16u8) __msa_pckev_b((v16i8) vec3, (v16i8) vec2); + vec4 = (v16u8) __msa_pckev_b((v16i8) vec5, (v16i8) vec4); + vec5 = (v16u8) __msa_pckev_b((v16i8) vec7, (v16i8) vec6); + vec0 = (v16u8) __msa_pckod_b((v16i8) vec1, (v16i8) vec0); + vec1 = (v16u8) __msa_pckod_b((v16i8) vec3, (v16i8) vec2); + reg0 = __msa_hadd_u_h(vec8, vec8); + reg1 = __msa_hadd_u_h(vec9, vec9); + reg2 = __msa_hadd_u_h(vec4, vec4); + reg3 = __msa_hadd_u_h(vec5, vec5); + reg4 = __msa_hadd_u_h(vec0, vec0); + reg5 = __msa_hadd_u_h(vec1, vec1); + src0 = (v16u8) __msa_ld_b((v16u8*) src_argb0_next, 0); + src1 = (v16u8) __msa_ld_b((v16u8*) src_argb0_next, 16); + src2 = (v16u8) __msa_ld_b((v16u8*) src_argb0_next, 32); + src3 = (v16u8) __msa_ld_b((v16u8*) src_argb0_next, 48); + src4 = (v16u8) __msa_ld_b((v16u8*) src_argb0_next, 64); + src5 = (v16u8) __msa_ld_b((v16u8*) src_argb0_next, 80); + src6 = (v16u8) __msa_ld_b((v16u8*) src_argb0_next, 96); + src7 = (v16u8) __msa_ld_b((v16u8*) src_argb0_next, 112); + vec0 = (v16u8) __msa_pckev_b((v16i8) src1, (v16i8) src0); + vec1 = (v16u8) __msa_pckev_b((v16i8) src3, (v16i8) src2); + vec2 = (v16u8) __msa_pckev_b((v16i8) src5, (v16i8) src4); + vec3 = (v16u8) __msa_pckev_b((v16i8) src7, (v16i8) src6); + vec4 = (v16u8) __msa_pckod_b((v16i8) src1, (v16i8) src0); + vec5 = (v16u8) __msa_pckod_b((v16i8) src3, (v16i8) src2); + vec6 = (v16u8) __msa_pckod_b((v16i8) src5, (v16i8) src4); + vec7 = (v16u8) __msa_pckod_b((v16i8) src7, (v16i8) src6); + vec8 = (v16u8) __msa_pckev_b((v16i8) vec1, (v16i8) vec0); + vec9 = (v16u8) __msa_pckev_b((v16i8) vec3, (v16i8) vec2); + vec4 = (v16u8) __msa_pckev_b((v16i8) vec5, (v16i8) vec4); + vec5 = (v16u8) __msa_pckev_b((v16i8) vec7, (v16i8) vec6); + vec0 = (v16u8) __msa_pckod_b((v16i8) vec1, (v16i8) vec0); + vec1 = (v16u8) __msa_pckod_b((v16i8) vec3, (v16i8) vec2); + reg0 += __msa_hadd_u_h(vec8, vec8); + reg1 += __msa_hadd_u_h(vec9, vec9); + reg2 += __msa_hadd_u_h(vec4, vec4); + reg3 += __msa_hadd_u_h(vec5, vec5); + reg4 += __msa_hadd_u_h(vec0, vec0); + reg5 += __msa_hadd_u_h(vec1, vec1); + reg0 = (v8u16) __msa_srai_h((v8i16) reg0, 2); + reg1 = (v8u16) __msa_srai_h((v8i16) reg1, 2); + reg2 = (v8u16) __msa_srai_h((v8i16) reg2, 2); + reg3 = (v8u16) __msa_srai_h((v8i16) reg3, 2); + reg4 = (v8u16) __msa_srai_h((v8i16) reg4, 2); + reg5 = (v8u16) __msa_srai_h((v8i16) reg5, 2); + reg6 = reg0 * const_0x70; + reg7 = reg1 * const_0x70; + reg8 = reg2 * const_0x4A; + reg9 = reg3 * const_0x4A; + reg6 += const_0x8080; + reg7 += const_0x8080; + reg8 += reg4 * const_0x26; + reg9 += reg5 * const_0x26; + reg0 *= const_0x12; + reg1 *= const_0x12; + reg2 *= const_0x5E; + reg3 *= const_0x5E; + reg4 *= const_0x70; + reg5 *= const_0x70; + reg2 += reg0; + reg3 += reg1; + reg4 += const_0x8080; + reg5 += const_0x8080; + reg6 -= reg8; + reg7 -= reg9; + reg4 -= reg2; + reg5 -= reg3; + reg6 = (v8u16) __msa_srai_h((v8i16) reg6, 8); + reg7 = (v8u16) __msa_srai_h((v8i16) reg7, 8); + reg4 = (v8u16) __msa_srai_h((v8i16) reg4, 8); + reg5 = (v8u16) __msa_srai_h((v8i16) reg5, 8); + dst0 = (v16u8) __msa_pckev_b((v16i8) reg7, (v16i8) reg6); + dst1 = (v16u8) __msa_pckev_b((v16i8) reg5, (v16i8) reg4); + ST_UB(dst0, dst_u); + ST_UB(dst1, dst_v); + src_argb0 += 128; + src_argb0_next += 128; + dst_u += 16; + dst_v += 16; + } +} + +void ARGB4444ToARGBRow_MSA(const uint8* src_argb4444, uint8* dst_argb, + int width) { + int x; + v16u8 src0, src1; + v8u16 vec0, vec1, vec2, vec3; + v16u8 dst0, dst1, dst2, dst3; + + for (x = 0; x < width; x += 16) { + src0 = (v16u8) __msa_ld_b((v16u8*) src_argb4444, 0); + src1 = (v16u8) __msa_ld_b((v16u8*) src_argb4444, 16); + vec0 = (v8u16) __msa_andi_b(src0, 0x0F); + vec1 = (v8u16) __msa_andi_b(src1, 0x0F); + vec2 = (v8u16) __msa_andi_b(src0, 0xF0); + vec3 = (v8u16) __msa_andi_b(src1, 0xF0); + vec0 |= (v8u16) __msa_slli_b((v16i8) vec0, 4); + vec1 |= (v8u16) __msa_slli_b((v16i8) vec1, 4); + vec2 |= (v8u16) __msa_srli_b((v16i8) vec2, 4); + vec3 |= (v8u16) __msa_srli_b((v16i8) vec3, 4); + dst0 = (v16u8) __msa_ilvr_b((v16i8) vec2, (v16i8) vec0); + dst1 = (v16u8) __msa_ilvl_b((v16i8) vec2, (v16i8) vec0); + dst2 = (v16u8) __msa_ilvr_b((v16i8) vec3, (v16i8) vec1); + dst3 = (v16u8) __msa_ilvl_b((v16i8) vec3, (v16i8) vec1); + ST_UB4(dst0, dst1, dst2, dst3, dst_argb, 16); + src_argb4444 += 32; + dst_argb += 64; + } +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv