[libyuv] Consolidate LoongArch LSX and LASX inline asm into *_la.cc

Merge 64-bit LoongArch LSX and LASX inline assembly implementations
from rotate_lsx.cc, rotate_lasx.cc, row_lsx.cc, row_lasx.cc, and
scale_lsx.cc into compare_la.cc, rotate_la.cc, row_la.cc, and
scale_la.cc, and remove the obsolete loongson_intrinsics.h header.

Because all LSX and LASX kernels use inline assembly rather than
compiler intrinsics, separate libyuv_lsx/libyuv_lasx build targets and
-mlsx/-mlasx compiler flags are no longer required. Guard HAS_*_LSX and
HAS_*_LASX macros with defined(__loongarch_lp64) so runtime CPU
dispatch enables LASX and LSX without requiring global -mlasx/-mlsx
flags, and wrap every function and helper in *_la.cc with its
corresponding #ifdef HAS_* guard.

Also fix bugs found during LoongArch verification:
- Replace illegal vldi/xvldi -1 immediate encodings (si13 = 0x1fff,
  which raises SIGILL at runtime) in ARGBDetectRow_LSX and
  ARGBDetectRow_LASX with vseqi.b/xvseqi.b -1.
- Set simd_size to 16 for LSX and 32 for LASX in ComputeHammingDistance
  and ComputeSumSquareError.
- Remove orphaned dead BGRAToUVRow, ABGRToUVRow, RGBAToUVRow, and
  XRGBToUVHelper functions in row_la.cc.
- Remove dead alpha shifts in ARGB1555ToYRow/UVRow_LSX/LASX and hoist
  channel masks out of the loop in RGB565ToUVRow/ARGB1555ToUVRow.

Compare SIMD ISA per *_C:
------------------------------------------------------------------------
C Function                              LSX             LASX
------------------------------------------------------------------------
ARGBDetectRow_C                         LSX             LASX
HammingDistance_C                       LSX             LASX
HashDjb2_C                              LSX             LASX
Ssim4x4Row_C                            LSX             LASX
SsimWindowRow_C                         LSX             LASX
SumSquareError_C                        LSX             LASX
------------------------------------------------------------------------
Compare: 6 (100%)                       6 (100%)        6 (100%)
------------------------------------------------------------------------

Convert SIMD ISA per *_C:
------------------------------------------------------------------------
C Function                              LSX             LASX
------------------------------------------------------------------------
AB64ToARGBRow_C                         -               -
ABGRToAR30Row_C                         -               -
AR30ToAB30Row_C                         -               -
AR30ToABGRRow_C                         -               -
AR30ToARGBRow_C                         -               -
AR64ShuffleRow_C                        LSX             LASX
AR64ToAB64Row_C                         LSX             LASX
AR64ToARGBRow_C                         -               -
ARGB1555ToARGBRow_C                     LSX             LASX
ARGB1555ToUVMatrixRow_C                 -               -
ARGB1555ToUVRow_C                       LSX             LASX
ARGB1555ToYMatrixRow_C                  -               -
ARGB1555ToYRow_C                        LSX             LASX
ARGB4444ToARGBRow_C                     LSX             LASX
ARGB4444ToUVMatrixRow_C                 -               -
ARGB4444ToUVRow_C                       -               -
ARGB4444ToYMatrixRow_C                  -               -
ARGB4444ToYRow_C                        -               -
ARGBAddRow_C                            LSX             LASX
ARGBAffineRow_C                         -               -
ARGBAlphaBlendRow_C                     LSX             LASX
ARGBAttenuateRow_C                      LSX             LASX
ARGBBlendRow_C                          LSX             LASX
ARGBColorMatrixRow_C                    LSX             LASX
ARGBColorTableRow_C                     -               -
ARGBCopyAlphaRow_C                      -               -
ARGBCopyYToAlphaRow_C                   -               -
ARGBExtractAlphaRow_C                   LSX             LASX
ARGBGrayRow_C                           LSX             LASX
ARGBLumaColorTableRow_C                 -               -
ARGBMirrorRow_C                         LSX             LASX
ARGBMultiplyRow_C                       LSX             LASX
ARGBOrRow_C                             LSX             LASX
ARGBPolynomialRow_C                     -               -
ARGBQuantizeRow_C                       LSX             LASX
ARGBSepiaRow_C                          LSX             LASX
ARGBSetRow_C                            LSX             LASX
ARGBShadeRow_C                          LSX             LASX
ARGBShuffleRow_C                        LSX             LASX
ARGBSubtractRow_C                       LSX             LASX
ARGBToAB64Row_C                         -               -
ARGBToABGRRow_C                         LSX             LASX
ARGBToAR30Row_C                         -               -
ARGBToAR64Row_C                         -               -
ARGBToARGB1555Row_C                     LSX             LASX
ARGBToARGB4444Row_C                     LSX             LASX
ARGBToBGRARow_C                         LSX             LASX
ARGBToRAWRow_C                          LSX             LASX
ARGBToRGB24Row_C                        LSX             LASX
ARGBToRGB565DitherRow_C                 LSX             LASX
ARGBToRGB565Row_C                       LSX             LASX
ARGBToRGBARow_C                         LSX             LASX
ARGBToUV444MatrixRow_C                  -               -
ARGBToUVMatrixRow_C                     -               -
ARGBToYMatrixRow_C                      LSX             LASX
ARGBUnattenuateRow_C                    -               -
AYUVToUVRow_C                           -               -
AYUVToVURow_C                           -               -
AYUVToYRow_C                            -               -
BlendPlaneRow_C                         -               -
ByteToFloatRow_C                        -               -
ComputeCumulativeSumRow_C               -               -
Convert16To8Row_C                       -               -
Convert8To16Row_C                       -               -
Convert8To8Row_C                        -               -
CopyRow_16_C                            -               -
CopyRow_C                               LSX             LASX
CumulativeSumToAverageRow_C             -               -
DetileRow_16_C                          -               -
DetileRow_C                             -               -
DetileSplitUVRow_C                      -               -
DetileToYUY2_C                          -               -
DivideRow_16_C                          -               -
GaussCol_C                              -               -
GaussCol_F32_C                          -               -
GaussRow_C                              -               -
GaussRow_F32_C                          -               -
HalfFloatRow_C                          LSX             LASX
HalfMergeUVRow_C                        -               -
HalfRow_16To8_C                         -               -
HalfRow_16_C                            -               -
HalfRow_C                               -               -
HalfWidthRow_16To8_C                    -               -
HalfWidthRow_16To8_Odd_C                -               -
I210AlphaToARGBRow_C                    -               -
I210ToAR30Row_C                         -               -
I210ToARGBRow_C                         -               -
I212ToAR30Row_C                         -               -
I212ToARGBRow_C                         -               -
I400ToARGBRow_C                         LSX             LASX
I410AlphaToARGBRow_C                    -               -
I410ToAR30Row_C                         -               -
I410ToARGBRow_C                         -               -
I422AlphaToARGBRow_C                    LSX             LASX
I422ToAR30Row_C                         -               -
I422ToARGB1555Row_C                     LSX             LASX
I422ToARGB4444Row_C                     LSX             LASX
I422ToARGBRow_C                         LSX             LASX
I422ToRGB24Row_C                        LSX             LASX
I422ToRGB565Row_C                       LSX             LASX
I422ToRGBARow_C                         LSX             LASX
I422ToUYVYRow_C                         LSX             LASX
I422ToYUY2Row_C                         LSX             LASX
I444AlphaToARGBRow_C                    -               -
I444ToARGBRow_C                         LSX             LASX
I444ToRGB24Row_C                        -               -
InterpolateRow_16_C                     -               -
InterpolateRow_C                        LSX             LASX
J400ToARGBRow_C                         LSX             LASX
MergeAR64Row_C                          -               -
MergeARGB16To8Row_C                     -               -
MergeARGBRow_C                          -               -
MergeRGBRow_C                           -               -
MergeUVRow_16_C                         -               -
MergeUVRow_C                            LSX             LASX
MergeXR30Row_C                          -               -
MergeXR64Row_C                          -               -
MergeXRGB16To8Row_C                     -               -
MergeXRGBRow_C                          -               -
MirrorRow_16_C                          LSX             LASX
MirrorRow_C                             LSX             LASX
MirrorSplitUVRow_C                      LSX             LASX
MirrorUVRow_C                           LSX             LASX
MultiplyRow_16_C                        -               -
NV12ToARGBRow_C                         LSX             LASX
NV12ToRGB24Row_C                        -               -
NV12ToRGB565Row_C                       LSX             LASX
NV21ToARGBRow_C                         LSX             LASX
NV21ToRGB24Row_C                        -               -
NV21ToYUV24Row_C                        -               -
P210ToAR30Row_C                         -               -
P210ToARGBRow_C                         -               -
P410ToAR30Row_C                         -               -
P410ToARGBRow_C                         -               -
RAWToARGBRow_C                          LSX             LASX
RAWToRGB24Row_C                         LSX             LASX
RAWToRGBARow_C                          -               -
RGB24MirrorRow_C                        -               -
RGB24ToARGBRow_C                        LSX             LASX
RGB565ToARGBRow_C                       LSX             LASX
RGB565ToUVMatrixRow_C                   -               -
RGB565ToUVRow_C                         LSX             LASX
RGB565ToYMatrixRow_C                    -               -
RGB565ToYRow_C                          LSX             LASX
RGBAToARGBRow_C                         LSX             LASX
RGBColorTableRow_C                      -               -
RGBToUV444MatrixRow_C                   -               -
RGBToUVMatrixRow_C                      -               -
RGBToYMatrixRow_C                       LSX             LASX
ScaleMaxSamples_C                       -               -
ScaleSamples_C                          -               -
ScaleSumSamples_C                       -               -
SetRow_C                                LSX             LASX
SobelRow_C                              LSX             LASX
SobelToPlaneRow_C                       LSX             LASX
SobelXRow_C                             -               -
SobelXYRow_C                            LSX             LASX
SobelYRow_C                             -               -
SplitARGBRow_C                          -               -
SplitRGBRow_C                           -               -
SplitUVRow_16_C                         -               -
SplitUVRow_C                            LSX             LASX
SplitXRGBRow_C                          -               -
SwapUVRow_C                             -               -
UYVYToARGBRow_C                         LSX             LASX
UYVYToUV422Row_C                        LSX             LASX
UYVYToUVRow_C                           LSX             LASX
UYVYToYRow_C                            LSX             LASX
UnpackMT2T_C                            -               -
YUY2ToARGBRow_C                         LSX             LASX
YUY2ToNVUVRow_C                         -               -
YUY2ToUV422Row_C                        LSX             LASX
YUY2ToUVRow_C                           LSX             LASX
YUY2ToYRow_C                            LSX             LASX
------------------------------------------------------------------------
Convert: 174 (100%)                     76 (44%)        76 (44%)
------------------------------------------------------------------------

Rotate SIMD ISA per *_C:
------------------------------------------------------------------------
C Function                              LSX             LASX
------------------------------------------------------------------------
TransposeUVWx16_C                       -               LASX
TransposeUVWx8_C                        LSX             -
TransposeWx16_C                         -               LASX
TransposeWx4_32_C                       LSX             LASX
TransposeWx8_16_C                       LSX             LASX
TransposeWx8_C                          LSX             -
TransposeWxH_32_C                       -               -
------------------------------------------------------------------------
Rotate: 7 (100%)                        4 (57%)         4 (57%)
------------------------------------------------------------------------

Scale SIMD ISA per *_C:
------------------------------------------------------------------------
C Function                              LSX             LASX
------------------------------------------------------------------------
FixedDiv1_C                             -               -
FixedDiv_C                              -               -
ScaleARGBCols64_C                       -               -
ScaleARGBColsUp2_C                      -               -
ScaleARGBCols_C                         LSX             -
ScaleARGBFilterCols64_C                 -               -
ScaleARGBFilterCols_C                   LSX             -
ScaleARGBRowDown2Box_C                  LSX             -
ScaleARGBRowDown2Linear_C               LSX             -
ScaleARGBRowDown2_C                     LSX             -
ScaleARGBRowDownEvenBox_C               LSX             -
ScaleARGBRowDownEven_C                  LSX             -
ScaleAddCols0_C                         -               -
ScaleAddCols1_16_C                      -               -
ScaleAddCols1_C                         -               -
ScaleAddCols2_16_C                      -               -
ScaleAddCols2_C                         -               -
ScaleAddRow_16_C                        -               -
ScaleAddRow_C                           LSX             -
ScaleColsUp2_16_C                       -               -
ScaleColsUp2_C                          -               -
ScaleCols_16_C                          -               -
ScaleCols_C                             -               -
ScaleFilterCols64_16_C                  -               -
ScaleFilterCols64_C                     -               -
ScaleFilterCols_16_C                    -               -
ScaleFilterCols_C                       LSX             -
ScaleRowDown2Box_16_C                   -               -
ScaleRowDown2Box_C                      LSX             -
ScaleRowDown2Box_Odd_C                  -               -
ScaleRowDown2Linear_16_C                -               -
ScaleRowDown2Linear_C                   LSX             -
ScaleRowDown2_16_C                      -               -
ScaleRowDown2_C                         LSX             -
ScaleRowDown34_0_Box_16_C               -               -
ScaleRowDown34_0_Box_C                  LSX             -
ScaleRowDown34_16_C                     -               -
ScaleRowDown34_1_Box_16_C               -               -
ScaleRowDown34_1_Box_C                  LSX             -
ScaleRowDown34_C                        LSX             -
ScaleRowDown38_16_C                     -               -
ScaleRowDown38_2_Box_16_C               -               -
ScaleRowDown38_2_Box_C                  LSX             -
ScaleRowDown38_3_Box_16_C               -               -
ScaleRowDown38_3_Box_C                  LSX             -
ScaleRowDown38_C                        LSX             -
ScaleRowDown4Box_16_C                   -               -
ScaleRowDown4Box_C                      LSX             -
ScaleRowDown4_16_C                      -               -
ScaleRowDown4_C                         LSX             -
ScaleRowUp2_Bilinear_16_Any_C           -               -
ScaleRowUp2_Bilinear_16_C               -               -
ScaleRowUp2_Bilinear_Any_C              -               -
ScaleRowUp2_Bilinear_C                  -               -
ScaleRowUp2_Linear_16_Any_C             -               -
ScaleRowUp2_Linear_16_C                 -               -
ScaleRowUp2_Linear_Any_C                -               -
ScaleRowUp2_Linear_C                    -               -
ScaleUVAddCols1_16_C                    -               -
ScaleUVAddCols1_C                       -               -
ScaleUVAddCols2_16_C                    -               -
ScaleUVAddCols2_C                       -               -
ScaleUVAddCols3_16_C                    -               -
ScaleUVAddCols3_C                       LSX             -
ScaleUVCols64_16_C                      -               -
ScaleUVCols64_C                         -               -
ScaleUVColsUp2_16_C                     -               -
ScaleUVColsUp2_C                        -               -
ScaleUVCols_16_C                        -               -
ScaleUVCols_C                           -               -
ScaleUVFilterCols64_16_C                -               -
ScaleUVFilterCols64_C                   -               -
ScaleUVFilterCols_16_C                  -               -
ScaleUVFilterCols_C                     -               -
ScaleUVRowDown2Box_16_C                 -               -
ScaleUVRowDown2Box_C                    -               -
ScaleUVRowDown2Linear_16_C              -               -
ScaleUVRowDown2Linear_C                 -               -
ScaleUVRowDown2_16_C                    -               -
ScaleUVRowDown2_C                       -               -
ScaleUVRowDownEvenBox_16_C              -               -
ScaleUVRowDownEvenBox_C                 -               -
ScaleUVRowDownEven_16_C                 -               -
ScaleUVRowDownEven_C                    -               -
ScaleUVRowUp2_Bilinear_16_Any_C         -               -
ScaleUVRowUp2_Bilinear_16_C             -               -
ScaleUVRowUp2_Bilinear_Any_C            -               -
ScaleUVRowUp2_Bilinear_C                -               -
ScaleUVRowUp2_Linear_16_Any_C           -               -
ScaleUVRowUp2_Linear_16_C               -               -
ScaleUVRowUp2_Linear_Any_C              -               -
ScaleUVRowUp2_Linear_C                  -               -
------------------------------------------------------------------------
Scale: 92 (100%)                        21 (23%)        0 (0%)
------------------------------------------------------------------------

Test: qemu-loongarch64 -cpu la464 ./libyuv_unittest
Bug: none
Change-Id: I7990bc8c2524dc9434441b5379cf839012e73d5f
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8701144
Reviewed-by: richard winterton <rrwinterton@gmail.com>
Commit-Queue: Frank Barchard <fbarchard@google.com>
This commit is contained in:
Frank Barchard 2026-11-03 10:44:29 -08:00 committed by libyuv-scoped@luci-project-accounts.iam.gserviceaccount.com
parent d088b8f2bd
commit c6700f48dd
23 changed files with 4147 additions and 4163 deletions

View File

@ -35,6 +35,7 @@ cc_library {
"source/compare_common.cc",
"source/compare_gcc.cc",
"source/compare_hvx.cc",
"source/compare_la.cc",
"source/compare_neon.cc",
"source/compare_neon64.cc",
"source/convert.cc",
@ -54,6 +55,7 @@ cc_library {
"source/rotate_common.cc",
"source/rotate_gcc.cc",
"source/rotate_hvx.cc",
"source/rotate_la.cc",
"source/rotate_neon.cc",
"source/rotate_neon64.cc",
"source/rotate_rvv.cc",
@ -63,6 +65,7 @@ cc_library {
"source/row_common.cc",
"source/row_gcc.cc",
"source/row_hvx.cc",
"source/row_la.cc",
"source/row_neon.cc",
"source/row_neon64.cc",
"source/row_rvv.cc",
@ -74,6 +77,7 @@ cc_library {
"source/scale_common.cc",
"source/scale_gcc.cc",
"source/scale_hvx.cc",
"source/scale_la.cc",
"source/scale_neon.cc",
"source/scale_neon64.cc",
"source/scale_rgb.cc",

View File

@ -13,6 +13,7 @@ LOCAL_SRC_FILES := \
source/compare_common.cc \
source/compare_gcc.cc \
source/compare_hvx.cc \
source/compare_la.cc \
source/compare_neon.cc \
source/compare_neon64.cc \
source/compare_win.cc \
@ -30,6 +31,7 @@ LOCAL_SRC_FILES := \
source/rotate_common.cc \
source/rotate_gcc.cc \
source/rotate_hvx.cc \
source/rotate_la.cc \
source/rotate_neon.cc \
source/rotate_neon64.cc \
source/rotate_rvv.cc \
@ -38,6 +40,7 @@ LOCAL_SRC_FILES := \
source/row_common.cc \
source/row_gcc.cc \
source/row_hvx.cc \
source/row_la.cc \
source/row_neon.cc \
source/row_neon64.cc \
source/row_rvv.cc \
@ -48,6 +51,7 @@ LOCAL_SRC_FILES := \
source/scale_common.cc \
source/scale_gcc.cc \
source/scale_hvx.cc \
source/scale_la.cc \
source/scale_neon.cc \
source/scale_neon64.cc \
source/scale_rgb.cc \

View File

@ -98,14 +98,6 @@ group("libyuv") {
deps += [ ":libyuv_rvv" ]
}
if (libyuv_use_lsx) {
deps += [ ":libyuv_lsx" ]
}
if (libyuv_use_lasx) {
deps += [ ":libyuv_lasx" ]
}
if (!is_ios && !libyuv_disable_jpeg) {
# Make sure that clients of libyuv link with libjpeg. This can't go in
# libyuv_internal because in Windows x64 builds that will generate a clang
@ -129,7 +121,6 @@ static_library("libyuv_internal") {
"include/libyuv/convert_from_argb.h",
"include/libyuv/cpu_id.h",
"include/libyuv/cpu_support.h",
"include/libyuv/loongson_intrinsics.h",
"include/libyuv/mjpeg_decoder.h",
"include/libyuv/planar_functions.h",
"include/libyuv/rotate.h",
@ -150,6 +141,7 @@ static_library("libyuv_internal") {
"source/compare_common.cc",
"source/compare_gcc.cc",
"source/compare_hvx.cc",
"source/compare_la.cc",
"source/compare_wasm.cc",
"source/compare_win.cc",
"source/convert.cc",
@ -169,12 +161,14 @@ static_library("libyuv_internal") {
"source/rotate_common.cc",
"source/rotate_gcc.cc",
"source/rotate_hvx.cc",
"source/rotate_la.cc",
"source/rotate_wasm.cc",
"source/rotate_win.cc",
"source/row_any.cc",
"source/row_common.cc",
"source/row_gcc.cc",
"source/row_hvx.cc",
"source/row_la.cc",
"source/row_wasm.cc",
"source/row_win.cc",
"source/scale.cc",
@ -183,6 +177,7 @@ static_library("libyuv_internal") {
"source/scale_common.cc",
"source/scale_gcc.cc",
"source/scale_hvx.cc",
"source/scale_la.cc",
"source/scale_rgb.cc",
"source/scale_uv.cc",
"source/scale_wasm.cc",
@ -328,45 +323,6 @@ if (libyuv_use_rvv && !libyuv_disable_rvv) {
}
}
if (libyuv_use_lsx) {
static_library("libyuv_lsx") {
sources = [
# LSX Source Files
"source/rotate_lsx.cc",
"source/row_lsx.cc",
"source/scale_lsx.cc",
]
cflags_cc = [
"-mlsx",
"-Wno-c++11-narrowing",
]
deps = [ ":libyuv_internal" ]
public_configs = [ ":libyuv_config" ]
}
}
if (libyuv_use_lasx) {
static_library("libyuv_lasx") {
sources = [
# LASX Source Files
"source/rotate_lasx.cc",
"source/row_lasx.cc",
]
cflags_cc = [
"-mlasx",
"-Wno-c++11-narrowing",
]
deps = [ ":libyuv_internal" ]
public_configs = [ ":libyuv_config" ]
}
}
if (libyuv_include_tests) {
config("libyuv_unittest_warnings_config") {
if (!is_win) {

View File

@ -25,6 +25,7 @@ set ( ly_common_source_files
${ly_src_dir}/compare_common.cc
${ly_src_dir}/compare_gcc.cc
${ly_src_dir}/compare_hvx.cc
${ly_src_dir}/compare_la.cc
${ly_src_dir}/compare_wasm.cc
${ly_src_dir}/compare_win.cc
${ly_src_dir}/convert.cc
@ -44,6 +45,7 @@ set ( ly_common_source_files
${ly_src_dir}/rotate_common.cc
${ly_src_dir}/rotate_gcc.cc
${ly_src_dir}/rotate_hvx.cc
${ly_src_dir}/rotate_la.cc
${ly_src_dir}/rotate_rvv.cc
${ly_src_dir}/rotate_wasm.cc
${ly_src_dir}/rotate_win.cc
@ -51,6 +53,7 @@ set ( ly_common_source_files
${ly_src_dir}/row_common.cc
${ly_src_dir}/row_gcc.cc
${ly_src_dir}/row_hvx.cc
${ly_src_dir}/row_la.cc
${ly_src_dir}/row_rvv.cc
${ly_src_dir}/row_wasm.cc
${ly_src_dir}/row_win.cc
@ -60,6 +63,7 @@ set ( ly_common_source_files
${ly_src_dir}/scale_common.cc
${ly_src_dir}/scale_gcc.cc
${ly_src_dir}/scale_hvx.cc
${ly_src_dir}/scale_la.cc
${ly_src_dir}/scale_rgb.cc
${ly_src_dir}/scale_rvv.cc
${ly_src_dir}/scale_uv.cc
@ -198,7 +202,6 @@ endif()
if(LOONGARCH64)
include(CheckCXXSourceCompiles)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-narrowing")
check_cxx_source_compiles("
int main(int argc, char **argv) {
__asm__ volatile (
@ -213,23 +216,11 @@ if(LOONGARCH64)
);
return 0; }" SUPPORTS_LASX)
if(SUPPORTS_LSX)
# These kernels use only LSX (128-bit) instructions and must not be
# compiled with -mlasx, which would let the compiler emit 256-bit LASX
# code (e.g. for stack-array copies) and crash on LSX-only CPUs.
add_library(${ly_lib_name}_lsx OBJECT
${ly_src_dir}/rotate_lsx.cc
${ly_src_dir}/row_lsx.cc
${ly_src_dir}/scale_lsx.cc)
target_compile_options(${ly_lib_name}_lsx PRIVATE -mlsx)
list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_lsx>)
if(NOT SUPPORTS_LSX)
add_definitions(-DLIBYUV_DISABLE_LSX)
endif()
if(SUPPORTS_LASX)
add_library(${ly_lib_name}_lasx OBJECT
${ly_src_dir}/rotate_lasx.cc
${ly_src_dir}/row_lasx.cc)
target_compile_options(${ly_lib_name}_lasx PRIVATE -mlasx)
list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_lasx>)
if(NOT SUPPORTS_LASX)
add_definitions(-DLIBYUV_DISABLE_LASX)
endif()
endif()

View File

@ -43,7 +43,8 @@ and compiler compatibility.
for SiFive X280.
* **row_hvx.cc**: Qualcomm Hexagon Vector Extensions (HVX). Implemented using
intrinsics.
* **row_lsx.cc / row_lasx.cc**: Loongarch MIPS-like extensions.
* **row_la.cc**: 64-bit LoongArch LSX and LASX extensions (written in inline
assembly).
### Utility and Fallbacks

View File

@ -1,6 +1,6 @@
Name: libyuv
URL: https://chromium.googlesource.com/libyuv/libyuv/
Version: 1977
Version: 1978
Revision: DEPS
License: BSD-3-Clause
License File: LICENSE

View File

@ -132,7 +132,7 @@ extern "C" {
#endif
// The following are available for LoongArch LSX:
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_lp64)
#define HAS_HAMMINGDISTANCE_LSX
#define HAS_SUMSQUAREERROR_LSX
#define HAS_HASHDJB2_LSX
@ -142,7 +142,7 @@ extern "C" {
#endif
// The following are available for LoongArch LASX:
#if !defined(LIBYUV_DISABLE_LASX) && defined(__loongarch_asx)
#if !defined(LIBYUV_DISABLE_LASX) && defined(__loongarch_lp64)
#define HAS_HAMMINGDISTANCE_LASX
#define HAS_SUMSQUAREERROR_LASX
#define HAS_HASHDJB2_LASX

View File

@ -1,14 +0,0 @@
/*
* Copyright 2022 The LibYuv Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef INCLUDE_LIBYUV_LOONGSON_INTRINSICS_H_
#define INCLUDE_LIBYUV_LOONGSON_INTRINSICS_H_
#endif // INCLUDE_LIBYUV_LOONGSON_INTRINSICS_H_

View File

@ -113,14 +113,14 @@ extern "C" {
#define HAS_TRANSPOSEWXH_32_SME
#endif
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_lp64)
#define HAS_TRANSPOSEWX8_LSX
#define HAS_TRANSPOSEUVWX8_LSX
#define HAS_TRANSPOSEWX8_16_LSX
#define HAS_TRANSPOSEWX4_32_LSX
#endif
#if !defined(LIBYUV_DISABLE_LASX) && defined(__loongarch_asx)
#if !defined(LIBYUV_DISABLE_LASX) && defined(__loongarch_lp64)
#define HAS_TRANSPOSEWX16_LASX
#define HAS_TRANSPOSEUVWX16_LASX
#define HAS_TRANSPOSEWX16_16_LASX

View File

@ -1027,7 +1027,7 @@ extern "C" {
#define HAS_SCALESUMSAMPLES_NEON
#endif
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_lp64)
#define HAS_ARGB1555TOARGBROW_LSX
#define HAS_ARGB1555TOUVROW_LSX
#define HAS_ARGB1555TOYROW_LSX
@ -1039,38 +1039,41 @@ extern "C" {
#define HAS_ARGBCOLORMATRIXROW_LSX
#define HAS_ARGBEXTRACTALPHAROW_LSX
#define HAS_ARGBGRAYROW_LSX
#define HAS_ARGBMIRRORROW_LSX
#define HAS_ARGBMULTIPLYROW_LSX
#define HAS_ARGBORROW_LSX
#define HAS_ARGBQUANTIZEROW_LSX
#define HAS_ARGBSEPIAROW_LSX
#define HAS_ARGBSETROW_LSX
#define HAS_ARGBSHADEROW_LSX
#define HAS_ARGBSHUFFLEROW_LSX
#define HAS_ARGBSUBTRACTROW_LSX
#define HAS_ARGBQUANTIZEROW_LSX
#define HAS_ARGBSETROW_LSX
#define HAS_ARGBTOARGB1555ROW_LSX
#define HAS_ARGBTOARGB4444ROW_LSX
#define HAS_ARGBTORAWROW_LSX
#define HAS_ARGBTORGB24ROW_LSX
#define HAS_ARGBTORGB565ROW_LSX
#define HAS_ARGBTORGB565DITHERROW_LSX
#define HAS_ARGBMIRRORROW_LSX
#define HAS_ARGBMULTIPLYROW_LSX
#define HAS_ARGBTORGB565ROW_LSX
#define HAS_ARGBTOYMATRIXROW_LSX
#define HAS_COPYROW_LSX
#define HAS_HALFFLOATROW_LSX
#define HAS_I400TOARGBROW_LSX
#define HAS_I444TOARGBROW_LSX
#define HAS_INTERPOLATEROW_LSX
#define HAS_I422ALPHATOARGBROW_LSX
#define HAS_I422TOARGB1555ROW_LSX
#define HAS_I422TOARGB4444ROW_LSX
#define HAS_I422TOARGBROW_LSX
#define HAS_I422TORGB24ROW_LSX
#define HAS_I422TORGB565ROW_LSX
#define HAS_I422TORGBAROW_LSX
#define HAS_I422TOUYVYROW_LSX
#define HAS_I422TOYUY2ROW_LSX
#define HAS_I444TOARGBROW_LSX
#define HAS_INTERPOLATEROW_LSX
#define HAS_J400TOARGBROW_LSX
#define HAS_MERGEUVROW_LSX
#define HAS_MIRRORROW_LSX
#define HAS_MIRRORUVROW_LSX
#define HAS_MIRRORSPLITUVROW_LSX
#define HAS_MIRRORUVROW_LSX
#define HAS_NV12TOARGBROW_LSX
#define HAS_NV12TORGB565ROW_LSX
#define HAS_NV21TOARGBROW_LSX
@ -1082,6 +1085,7 @@ extern "C" {
#define HAS_RGB565TOARGBROW_LSX
#define HAS_RGB565TOUVROW_LSX
#define HAS_RGB565TOYROW_LSX
#define HAS_RGBTOYMATRIXROW_LSX
#define HAS_SETROW_LSX
#define HAS_SOBELROW_LSX
#define HAS_SOBELTOPLANEROW_LSX
@ -1092,19 +1096,12 @@ extern "C" {
#define HAS_UYVYTOUVROW_LSX
#define HAS_UYVYTOYROW_LSX
#define HAS_YUY2TOARGBROW_LSX
#define HAS_YUY2TOUVROW_LSX
#define HAS_YUY2TOUV422ROW_LSX
#define HAS_YUY2TOUVROW_LSX
#define HAS_YUY2TOYROW_LSX
#define HAS_ARGBTOYMATRIXROW_LSX
#define HAS_COPYROW_LSX
#define HAS_RGBTOYMATRIXROW_LSX
#endif
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)
#define HAS_I422TOARGBROW_LSX
#endif
#if !defined(LIBYUV_DISABLE_LASX) && defined(__loongarch_asx)
#if !defined(LIBYUV_DISABLE_LASX) && defined(__loongarch_lp64)
#define HAS_ARGB1555TOARGBROW_LASX
#define HAS_ARGB1555TOUVROW_LASX
#define HAS_ARGB1555TOYROW_LASX

View File

@ -151,7 +151,7 @@ extern "C" {
#define HAS_SCALEUVROWDOWN2_SME
#endif
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_lp64)
#define HAS_SCALEARGBROWDOWN2_LSX
#define HAS_SCALEARGBROWDOWNEVEN_LSX
#define HAS_SCALEROWDOWN2_LSX

View File

@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_
#define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 1977
#define LIBYUV_VERSION 1978
#endif // INCLUDE_LIBYUV_VERSION_H_

View File

@ -7,7 +7,6 @@
# be found in the AUTHORS file in the root of the source tree.
import("//build/config/arm.gni")
import("//build/config/loongarch64.gni")
import("//build/config/mips.gni")
import("//build_overrides/build.gni")
@ -28,7 +27,7 @@ declare_args() {
(current_cpu == "mips64el" || current_cpu == "mipsel") && mips_use_msa
libyuv_use_mmi =
(current_cpu == "mips64el" || current_cpu == "mipsel") && mips_use_mmi
libyuv_use_lsx = current_cpu == "loong64" && loongarch64_use_lsx
libyuv_use_lasx = current_cpu == "loong64" && loongarch64_use_lasx
libyuv_use_lsx = current_cpu == "loong64"
libyuv_use_lasx = current_cpu == "loong64"
libyuv_use_rvv = current_cpu == "riscv64" || current_cpu == "riscv32"
}

View File

@ -20,7 +20,6 @@
'include/libyuv/convert_from_argb.h',
'include/libyuv/cpu_id.h',
'include/libyuv/cpu_support.h',
'include/libyuv/loongson_intrinsics.h',
'include/libyuv/mjpeg_decoder.h',
'include/libyuv/planar_functions.h',
'include/libyuv/rotate.h',
@ -41,6 +40,7 @@
'source/compare_common.cc',
'source/compare_gcc.cc',
'source/compare_hvx.cc',
'source/compare_la.cc',
'source/compare_neon.cc',
'source/compare_neon64.cc',
'source/compare_win.cc',
@ -61,8 +61,7 @@
'source/rotate_common.cc',
'source/rotate_gcc.cc',
'source/rotate_hvx.cc',
'source/rotate_lasx.cc',
'source/rotate_lsx.cc',
'source/rotate_la.cc',
'source/rotate_neon.cc',
'source/rotate_neon64.cc',
'source/rotate_rvv.cc',
@ -71,8 +70,7 @@
'source/row_common.cc',
'source/row_gcc.cc',
'source/row_hvx.cc',
'source/row_lasx.cc',
'source/row_lsx.cc',
'source/row_la.cc',
'source/row_neon.cc',
'source/row_neon64.cc',
'source/row_rvv.cc',
@ -83,7 +81,7 @@
'source/scale_common.cc',
'source/scale_gcc.cc',
'source/scale_hvx.cc',
'source/scale_lsx.cc',
'source/scale_la.cc',
'source/scale_neon.cc',
'source/scale_neon64.cc',
'source/scale_rgb.cc',

View File

@ -14,6 +14,7 @@ LOCAL_OBJ_FILES := \
source/compare_common.o \
source/compare_gcc.o \
source/compare_hvx.o \
source/compare_la.o \
source/compare_neon.o \
source/compare_neon64.o \
source/compare_win.o \
@ -34,8 +35,7 @@ LOCAL_OBJ_FILES := \
source/rotate_common.o \
source/rotate_gcc.o \
source/rotate_hvx.o \
source/rotate_lasx.o \
source/rotate_lsx.o \
source/rotate_la.o \
source/rotate_neon.o \
source/rotate_neon64.o \
source/rotate_rvv.o \
@ -46,8 +46,7 @@ LOCAL_OBJ_FILES := \
source/row_common.o \
source/row_gcc.o \
source/row_hvx.o \
source/row_lasx.o \
source/row_lsx.o \
source/row_la.o \
source/row_neon.o \
source/row_neon64.o \
source/row_rvv.o \
@ -60,7 +59,7 @@ LOCAL_OBJ_FILES := \
source/scale_common.o \
source/scale_gcc.o \
source/scale_hvx.o \
source/scale_lsx.o \
source/scale_la.o \
source/scale_neon.o \
source/scale_neon64.o \
source/scale_rgb.o \

View File

@ -238,11 +238,13 @@ uint64_t ComputeHammingDistance(const uint8_t* src_a,
#if defined(HAS_HAMMINGDISTANCE_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
HammingDistance = HammingDistance_LSX;
simd_size = 16;
}
#endif
#if defined(HAS_HAMMINGDISTANCE_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
HammingDistance = HammingDistance_LASX;
simd_size = 32;
}
#endif
#if defined(HAS_HAMMINGDISTANCE_WASMSIMD)
@ -346,11 +348,13 @@ uint64_t ComputeSumSquareError(const uint8_t* src_a,
#if defined(HAS_SUMSQUAREERROR_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
SumSquareError = SumSquareError_LSX;
simd_size = 16;
}
#endif
#if defined(HAS_SUMSQUAREERROR_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
SumSquareError = SumSquareError_LASX;
simd_size = 32;
}
#endif
#if defined(HAS_SUMSQUAREERROR_WASMSIMD)

652
source/compare_la.cc Normal file
View File

@ -0,0 +1,652 @@
/*
* Copyright 2022 The LibYuv Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "libyuv/compare_row.h"
#include "libyuv/row.h"
#include "libyuv/video_common.h"
// Note: every register written by an inline asm block (vector, general
// purpose, mask/predicate, "cc" for flags and "memory" for stores) must be
// listed in its clobber list, even when the ABI treats it as caller-saved.
// With LTO/LTCG the compiler may keep values live in any register across the
// asm statement, and other OS ABIs (e.g. Windows) differ in which registers
// are callee-saved. List "memory" first, then "cc", then registers.
#if (!defined(LIBYUV_DISABLE_LSX) || !defined(LIBYUV_DISABLE_LASX)) && \
defined(__loongarch_lp64)
#ifdef __cplusplus
namespace libyuv {
extern "C" {
#endif
#if defined(HAS_HASHDJB2_LSX) || defined(HAS_HASHDJB2_LASX)
static const ulvec32 kDjb2Multiplicands[] = {
{0x0c3525e1, 0xa3476dc1, 0x3b4039a1, 0x4f5f0981, 0x30f35d61, 0x855cb541,
0x040a9121, 0x747c7101},
{0xec41d4e1, 0x4cfa3cc1, 0x025528a1, 0x00121881, 0x00008c61, 0x00000441,
0x00000021, 0x00000001},
};
#endif // defined(HAS_HASHDJB2_LSX) || defined(HAS_HASHDJB2_LASX)
#ifdef HAS_HAMMINGDISTANCE_LSX
uint32_t HammingDistance_LSX(const uint8_t* src_a,
const uint8_t* src_b,
int count) {
uint32_t diff;
asm volatile(
"vxor.v $vr4, $vr4, $vr4\n\t"
"1:\n\t"
"vld $vr0, %[sa], 0\n\t"
"vld $vr1, %[sb], 0\n\t"
"vxor.v $vr0, $vr0, $vr1\n\t"
"vpcnt.b $vr0, $vr0\n\t"
"vhaddw.hu.bu $vr0, $vr0, $vr0\n\t"
"vhaddw.wu.hu $vr0, $vr0, $vr0\n\t"
"vadd.w $vr4, $vr4, $vr0\n\t"
"addi.d %[sa], %[sa], 16\n\t"
"addi.d %[sb], %[sb], 16\n\t"
"addi.d %[cnt], %[cnt], -16\n\t"
"bnez %[cnt], 1b\n\t"
"vhaddw.du.wu $vr4, $vr4, $vr4\n\t"
"vhaddw.qu.du $vr4, $vr4, $vr4\n\t"
"vpickve2gr.wu %[diff], $vr4, 0\n\t"
: [sa] "+r"(src_a), [sb] "+r"(src_b), [cnt] "+r"(count), [diff] "=r"(diff)
:
: "memory", "$vr0", "$vr1", "$vr4");
return diff;
}
#endif // HAS_HAMMINGDISTANCE_LSX
#ifdef HAS_SUMSQUAREERROR_LSX
uint32_t SumSquareError_LSX(const uint8_t* src_a,
const uint8_t* src_b,
int count) {
uint32_t sse;
asm volatile(
"vxor.v $vr4, $vr4, $vr4\n\t"
"1:\n\t"
"vld $vr0, %[sa], 0\n\t"
"vld $vr1, %[sb], 0\n\t"
"vabsd.bu $vr0, $vr0, $vr1\n\t"
"vmulwev.h.bu $vr2, $vr0, $vr0\n\t"
"vmulwod.h.bu $vr3, $vr0, $vr0\n\t"
"vhaddw.wu.hu $vr2, $vr2, $vr2\n\t"
"vhaddw.wu.hu $vr3, $vr3, $vr3\n\t"
"vadd.w $vr4, $vr4, $vr2\n\t"
"vadd.w $vr4, $vr4, $vr3\n\t"
"addi.d %[sa], %[sa], 16\n\t"
"addi.d %[sb], %[sb], 16\n\t"
"addi.d %[cnt], %[cnt], -16\n\t"
"bnez %[cnt], 1b\n\t"
"vhaddw.du.wu $vr4, $vr4, $vr4\n\t"
"vhaddw.qu.du $vr4, $vr4, $vr4\n\t"
"vpickve2gr.wu %[sse], $vr4, 0\n\t"
: [sa] "+r"(src_a), [sb] "+r"(src_b), [cnt] "+r"(count), [sse] "=r"(sse)
:
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4");
return sse;
}
#endif // HAS_SUMSQUAREERROR_LSX
#ifdef HAS_HASHDJB2_LSX
uint32_t HashDjb2_LSX(const uint8_t* src, int count, uint32_t seed) {
uint32_t hash = seed;
uint32_t tmp;
uint32_t c16 = 0x92d9e201u;
asm volatile(
"vld $vr4, %[muls], 0\n\t"
"vld $vr5, %[muls], 16\n\t"
"vld $vr6, %[muls], 32\n\t"
"vld $vr7, %[muls], 48\n\t"
"1:\n\t"
"vld $vr0, %[src], 0\n\t"
"vsllwil.hu.bu $vr1, $vr0, 0\n\t"
"vexth.hu.bu $vr2, $vr0\n\t"
"vsllwil.wu.hu $vr0, $vr1, 0\n\t"
"vexth.wu.hu $vr1, $vr1\n\t"
"vsllwil.wu.hu $vr3, $vr2, 0\n\t"
"vexth.wu.hu $vr2, $vr2\n\t"
"vmul.w $vr0, $vr0, $vr4\n\t"
"vmadd.w $vr0, $vr1, $vr5\n\t"
"vmadd.w $vr0, $vr3, $vr6\n\t"
"vmadd.w $vr0, $vr2, $vr7\n\t"
"vhaddw.du.wu $vr0, $vr0, $vr0\n\t"
"vhaddw.qu.du $vr0, $vr0, $vr0\n\t"
"vpickve2gr.wu %[tmp], $vr0, 0\n\t"
"mul.w %[hash], %[hash], %[c16]\n\t"
"add.w %[hash], %[hash], %[tmp]\n\t"
"addi.d %[src], %[src], 16\n\t"
"addi.d %[cnt], %[cnt], -16\n\t"
"bnez %[cnt], 1b\n\t"
: [src] "+r"(src), [cnt] "+r"(count), [hash] "+r"(hash), [tmp] "=&r"(tmp)
: [muls] "r"(kDjb2Multiplicands), [c16] "r"(c16)
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7");
return hash;
}
#endif // HAS_HASHDJB2_LSX
#ifdef HAS_SSIM4X4ROW_LSX
void Ssim4x4Row_LSX(const uint8_t* src_a,
int stride_a,
const uint8_t* src_b,
int stride_b,
uint32_t* dst,
int width) {
const uint8_t* pa;
const uint8_t* pb;
int r;
asm volatile(
"1:\n\t"
"move %[pa], %[sa]\n\t"
"move %[pb], %[sb]\n\t"
"li.d %[r], 4\n\t"
"vxor.v $vr8, $vr8, $vr8\n\t"
"vxor.v $vr9, $vr9, $vr9\n\t"
"vxor.v $vr10, $vr10, $vr10\n\t"
"vxor.v $vr11, $vr11, $vr11\n\t"
"2:\n\t"
"vld $vr0, %[pa], 0\n\t"
"vld $vr1, %[pb], 0\n\t"
"add.d %[pa], %[pa], %[sta]\n\t"
"add.d %[pb], %[pb], %[stb]\n\t"
"vhaddw.hu.bu $vr2, $vr0, $vr0\n\t"
"vhaddw.hu.bu $vr3, $vr1, $vr1\n\t"
"vadd.h $vr8, $vr8, $vr2\n\t"
"vadd.h $vr9, $vr9, $vr3\n\t"
"vmulwev.h.bu $vr2, $vr0, $vr1\n\t"
"vmulwod.h.bu $vr3, $vr0, $vr1\n\t"
"vhaddw.wu.hu $vr2, $vr2, $vr2\n\t"
"vhaddw.wu.hu $vr3, $vr3, $vr3\n\t"
"vadd.w $vr11, $vr11, $vr2\n\t"
"vadd.w $vr11, $vr11, $vr3\n\t"
"vmulwev.h.bu $vr2, $vr0, $vr0\n\t"
"vmulwod.h.bu $vr3, $vr0, $vr0\n\t"
"vmulwev.h.bu $vr4, $vr1, $vr1\n\t"
"vmulwod.h.bu $vr5, $vr1, $vr1\n\t"
"vhaddw.wu.hu $vr2, $vr2, $vr2\n\t"
"vhaddw.wu.hu $vr3, $vr3, $vr3\n\t"
"vhaddw.wu.hu $vr4, $vr4, $vr4\n\t"
"vhaddw.wu.hu $vr5, $vr5, $vr5\n\t"
"vadd.w $vr2, $vr2, $vr3\n\t"
"vadd.w $vr4, $vr4, $vr5\n\t"
"vadd.w $vr10, $vr10, $vr2\n\t"
"vadd.w $vr10, $vr10, $vr4\n\t"
"addi.d %[r], %[r], -1\n\t"
"bnez %[r], 2b\n\t"
"vhaddw.wu.hu $vr8, $vr8, $vr8\n\t"
"vhaddw.wu.hu $vr9, $vr9, $vr9\n\t"
"vilvl.w $vr0, $vr9, $vr8\n\t"
"vilvh.w $vr1, $vr9, $vr8\n\t"
"vilvl.w $vr2, $vr11, $vr10\n\t"
"vilvh.w $vr3, $vr11, $vr10\n\t"
"vilvl.d $vr4, $vr2, $vr0\n\t"
"vilvh.d $vr5, $vr2, $vr0\n\t"
"vilvl.d $vr6, $vr3, $vr1\n\t"
"vilvh.d $vr7, $vr3, $vr1\n\t"
"vst $vr4, %[dst], 0\n\t"
"vst $vr5, %[dst], 16\n\t"
"vst $vr6, %[dst], 32\n\t"
"vst $vr7, %[dst], 48\n\t"
"addi.d %[sa], %[sa], 16\n\t"
"addi.d %[sb], %[sb], 16\n\t"
"addi.d %[dst], %[dst], 64\n\t"
"addi.d %[cnt], %[cnt], -16\n\t"
"bnez %[cnt], 1b\n\t"
: [sa] "+r"(src_a), [sb] "+r"(src_b), [dst] "+r"(dst), [cnt] "+r"(width),
[pa] "=&r"(pa), [pb] "=&r"(pb), [r] "=&r"(r)
: [sta] "r"((ptrdiff_t)stride_a), [stb] "r"((ptrdiff_t)stride_b)
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9", "$vr10", "$vr11");
}
#endif // HAS_SSIM4X4ROW_LSX
#ifdef HAS_SSIMWINDOWROW_LSX
float SsimWindowRow_LSX(const uint32_t* row0,
const uint32_t* row1,
int num_windows) {
const uint32_t* row0_next = row0 + 4;
const uint32_t* row1_next = row1 + 4;
float total;
uint32_t c1 = 26634;
uint32_t c2 = 239708;
uint32_t c0 = 0;
asm volatile(
"vreplgr2vr.w $vr6, %[c0]\n\t"
"vreplgr2vr.w $vr4, %[c1]\n\t"
"vreplgr2vr.w $vr5, %[c2]\n\t"
"1:\n\t"
"vld $vr0, %[r0], 0\n\t"
"vld $vr1, %[r0n], 0\n\t"
"vld $vr2, %[r1], 0\n\t"
"vld $vr3, %[r1n], 0\n\t"
"vadd.w $vr0, $vr0, $vr1\n\t"
"vadd.w $vr2, $vr2, $vr3\n\t"
"vadd.w $vr0, $vr0, $vr2\n\t"
"vshuf4i.w $vr1, $vr0, 0x00\n\t"
"vshuf4i.w $vr2, $vr0, 0x55\n\t"
"vshuf4i.w $vr3, $vr0, 0xaa\n\t"
"vshuf4i.w $vr0, $vr0, 0xff\n\t"
"vmul.w $vr7, $vr1, $vr2\n\t"
"vslli.w $vr7, $vr7, 1\n\t"
"vmul.w $vr1, $vr1, $vr1\n\t"
"vmadd.w $vr1, $vr2, $vr2\n\t"
"vslli.w $vr0, $vr0, 7\n\t"
"vsub.w $vr0, $vr0, $vr7\n\t"
"vadd.w $vr7, $vr7, $vr4\n\t"
"vadd.w $vr0, $vr0, $vr5\n\t"
"vslli.w $vr3, $vr3, 6\n\t"
"vsub.w $vr3, $vr3, $vr1\n\t"
"vadd.w $vr1, $vr1, $vr4\n\t"
"vadd.w $vr3, $vr3, $vr5\n\t"
"vffint.s.w $vr7, $vr7\n\t"
"vffint.s.w $vr0, $vr0\n\t"
"vffint.s.w $vr1, $vr1\n\t"
"vffint.s.w $vr3, $vr3\n\t"
"vfmul.s $vr7, $vr7, $vr0\n\t"
"vfmul.s $vr1, $vr1, $vr3\n\t"
"vfdiv.s $vr7, $vr7, $vr1\n\t"
"vfadd.s $vr6, $vr6, $vr7\n\t"
"addi.d %[r0], %[r0], 16\n\t"
"addi.d %[r0n], %[r0n], 16\n\t"
"addi.d %[r1], %[r1], 16\n\t"
"addi.d %[r1n], %[r1n], 16\n\t"
"addi.d %[cnt], %[cnt], -1\n\t"
"bnez %[cnt], 1b\n\t"
"vstelm.w $vr6, %[tot], 0, 0\n\t"
: [r0] "+r"(row0), [r0n] "+r"(row0_next), [r1] "+r"(row1),
[r1n] "+r"(row1_next), [cnt] "+r"(num_windows)
: [c0] "r"(c0), [c1] "r"(c1), [c2] "r"(c2), [tot] "r"(&total)
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7");
return total;
}
#endif // HAS_SSIMWINDOWROW_LSX
#ifdef HAS_ARGBDETECTROW_LSX
uint32_t ARGBDetectRow_LSX(const uint8_t* argb, int width) {
uint32_t diff = 0;
uint32_t rgb_mask = 0x00ffff00u;
asm volatile(
"vreplgr2vr.w $vr2, %[rgb_mask]\n\t"
"addi.d %[w], %[w], -4\n\t"
"bltz %[w], 2f\n\t"
"1:\n\t"
"vld $vr0, %[argb], 0\n\t"
"addi.d %[argb], %[argb], 16\n\t"
"vor.v $vr0, $vr0, $vr2\n\t"
"vseqi.b $vr0, $vr0, -1\n\t"
"vmskltz.b $vr0, $vr0\n\t"
"vpickve2gr.hu %[diff], $vr0, 0\n\t"
"nor %[diff], %[diff], $zero\n\t"
"bstrpick.w %[diff], %[diff], 15, 0\n\t"
"bnez %[diff], 4f\n\t"
"addi.d %[w], %[w], -4\n\t"
"bgez %[w], 1b\n\t"
"2:\n\t"
"addi.d %[w], %[w], 4\n\t"
"beqz %[w], 4f\n\t"
"3:\n\t"
"vldrepl.w $vr0, %[argb], 0\n\t"
"addi.d %[argb], %[argb], 4\n\t"
"vor.v $vr0, $vr0, $vr2\n\t"
"vseqi.b $vr0, $vr0, -1\n\t"
"vmskltz.b $vr0, $vr0\n\t"
"vpickve2gr.hu %[diff], $vr0, 0\n\t"
"nor %[diff], %[diff], $zero\n\t"
"bstrpick.w %[diff], %[diff], 15, 0\n\t"
"bnez %[diff], 4f\n\t"
"addi.d %[w], %[w], -1\n\t"
"bnez %[w], 3b\n\t"
"4:\n\t"
: [argb] "+r"(argb), [w] "+r"(width), [diff] "+r"(diff)
: [rgb_mask] "r"(rgb_mask)
: "memory", "$vr0", "$vr2");
if (diff) {
return (__builtin_ctz(diff) & 3) == 0 ? FOURCC_BGRA : FOURCC_ARGB;
}
return 0;
}
#endif // HAS_ARGBDETECTROW_LSX
#ifdef HAS_HAMMINGDISTANCE_LASX
uint32_t HammingDistance_LASX(const uint8_t* src_a,
const uint8_t* src_b,
int count) {
uint32_t diff;
asm volatile(
"xvxor.v $xr4, $xr4, $xr4\n\t"
"1:\n\t"
"xvld $xr0, %[sa], 0\n\t"
"xvld $xr1, %[sb], 0\n\t"
"xvxor.v $xr0, $xr0, $xr1\n\t"
"xvpcnt.b $xr0, $xr0\n\t"
"xvhaddw.hu.bu $xr0, $xr0, $xr0\n\t"
"xvhaddw.wu.hu $xr0, $xr0, $xr0\n\t"
"xvadd.w $xr4, $xr4, $xr0\n\t"
"addi.d %[sa], %[sa], 32\n\t"
"addi.d %[sb], %[sb], 32\n\t"
"addi.d %[cnt], %[cnt], -32\n\t"
"bnez %[cnt], 1b\n\t"
"xvhaddw.du.wu $xr4, $xr4, $xr4\n\t"
"xvhaddw.qu.du $xr4, $xr4, $xr4\n\t"
"xvpermi.q $xr0, $xr4, 0x01\n\t"
"vadd.w $vr4, $vr4, $vr0\n\t"
"vpickve2gr.wu %[diff], $vr4, 0\n\t"
: [sa] "+r"(src_a), [sb] "+r"(src_b), [cnt] "+r"(count), [diff] "=r"(diff)
:
: "memory", "$xr0", "$xr1", "$xr4");
return diff;
}
#endif // HAS_HAMMINGDISTANCE_LASX
#ifdef HAS_SUMSQUAREERROR_LASX
uint32_t SumSquareError_LASX(const uint8_t* src_a,
const uint8_t* src_b,
int count) {
uint32_t sse;
asm volatile(
"xvxor.v $xr4, $xr4, $xr4\n\t"
"1:\n\t"
"xvld $xr0, %[sa], 0\n\t"
"xvld $xr1, %[sb], 0\n\t"
"xvabsd.bu $xr0, $xr0, $xr1\n\t"
"xvmulwev.h.bu $xr2, $xr0, $xr0\n\t"
"xvmulwod.h.bu $xr3, $xr0, $xr0\n\t"
"xvhaddw.wu.hu $xr2, $xr2, $xr2\n\t"
"xvhaddw.wu.hu $xr3, $xr3, $xr3\n\t"
"xvadd.w $xr4, $xr4, $xr2\n\t"
"xvadd.w $xr4, $xr4, $xr3\n\t"
"addi.d %[sa], %[sa], 32\n\t"
"addi.d %[sb], %[sb], 32\n\t"
"addi.d %[cnt], %[cnt], -32\n\t"
"bnez %[cnt], 1b\n\t"
"xvhaddw.du.wu $xr4, $xr4, $xr4\n\t"
"xvhaddw.qu.du $xr4, $xr4, $xr4\n\t"
"xvpermi.q $xr0, $xr4, 0x01\n\t"
"vadd.w $vr4, $vr4, $vr0\n\t"
"vpickve2gr.wu %[sse], $vr4, 0\n\t"
: [sa] "+r"(src_a), [sb] "+r"(src_b), [cnt] "+r"(count), [sse] "=r"(sse)
:
: "memory", "$xr0", "$xr1", "$xr2", "$xr3", "$xr4");
return sse;
}
#endif // HAS_SUMSQUAREERROR_LASX
#ifdef HAS_HASHDJB2_LASX
uint32_t HashDjb2_LASX(const uint8_t* src, int count, uint32_t seed) {
uint32_t hash = seed;
uint32_t tmp;
uint32_t c16 = 0x92d9e201u;
asm volatile(
"xvld $xr4, %[muls], 0\n\t"
"xvld $xr5, %[muls], 32\n\t"
"1:\n\t"
"vld $vr0, %[src], 0\n\t"
"vbsrl.v $vr1, $vr0, 8\n\t"
"vext2xv.wu.bu $xr0, $xr0\n\t"
"vext2xv.wu.bu $xr1, $xr1\n\t"
"xvmul.w $xr0, $xr0, $xr4\n\t"
"xvmadd.w $xr0, $xr1, $xr5\n\t"
"xvhaddw.du.wu $xr0, $xr0, $xr0\n\t"
"xvhaddw.qu.du $xr0, $xr0, $xr0\n\t"
"xvpermi.q $xr1, $xr0, 0x01\n\t"
"vadd.w $vr0, $vr0, $vr1\n\t"
"vpickve2gr.wu %[tmp], $vr0, 0\n\t"
"mul.w %[hash], %[hash], %[c16]\n\t"
"add.w %[hash], %[hash], %[tmp]\n\t"
"addi.d %[src], %[src], 16\n\t"
"addi.d %[cnt], %[cnt], -16\n\t"
"bnez %[cnt], 1b\n\t"
: [src] "+r"(src), [cnt] "+r"(count), [hash] "+r"(hash), [tmp] "=&r"(tmp)
: [muls] "r"(kDjb2Multiplicands), [c16] "r"(c16)
: "memory", "$xr0", "$xr1", "$xr4", "$xr5");
return hash;
}
#endif // HAS_HASHDJB2_LASX
#ifdef HAS_SSIM4X4ROW_LASX
void Ssim4x4Row_LASX(const uint8_t* src_a,
int stride_a,
const uint8_t* src_b,
int stride_b,
uint32_t* dst,
int width) {
const uint8_t* pa;
const uint8_t* pb;
int r;
asm volatile(
"1:\n\t"
"move %[pa], %[sa]\n\t"
"move %[pb], %[sb]\n\t"
"li.d %[r], 4\n\t"
"xvxor.v $xr8, $xr8, $xr8\n\t"
"xvxor.v $xr9, $xr9, $xr9\n\t"
"xvxor.v $xr10, $xr10, $xr10\n\t"
"xvxor.v $xr11, $xr11, $xr11\n\t"
"2:\n\t"
"xvld $xr0, %[pa], 0\n\t"
"xvld $xr1, %[pb], 0\n\t"
"add.d %[pa], %[pa], %[sta]\n\t"
"add.d %[pb], %[pb], %[stb]\n\t"
"xvhaddw.hu.bu $xr2, $xr0, $xr0\n\t"
"xvhaddw.hu.bu $xr3, $xr1, $xr1\n\t"
"xvadd.h $xr8, $xr8, $xr2\n\t"
"xvadd.h $xr9, $xr9, $xr3\n\t"
"xvmulwev.h.bu $xr2, $xr0, $xr1\n\t"
"xvmulwod.h.bu $xr3, $xr0, $xr1\n\t"
"xvhaddw.wu.hu $xr2, $xr2, $xr2\n\t"
"xvhaddw.wu.hu $xr3, $xr3, $xr3\n\t"
"xvadd.w $xr11, $xr11, $xr2\n\t"
"xvadd.w $xr11, $xr11, $xr3\n\t"
"xvmulwev.h.bu $xr2, $xr0, $xr0\n\t"
"xvmulwod.h.bu $xr3, $xr0, $xr0\n\t"
"xvmulwev.h.bu $xr4, $xr1, $xr1\n\t"
"xvmulwod.h.bu $xr5, $xr1, $xr1\n\t"
"xvhaddw.wu.hu $xr2, $xr2, $xr2\n\t"
"xvhaddw.wu.hu $xr3, $xr3, $xr3\n\t"
"xvhaddw.wu.hu $xr4, $xr4, $xr4\n\t"
"xvhaddw.wu.hu $xr5, $xr5, $xr5\n\t"
"xvadd.w $xr2, $xr2, $xr3\n\t"
"xvadd.w $xr4, $xr4, $xr5\n\t"
"xvadd.w $xr10, $xr10, $xr2\n\t"
"xvadd.w $xr10, $xr10, $xr4\n\t"
"addi.d %[r], %[r], -1\n\t"
"bnez %[r], 2b\n\t"
"xvhaddw.wu.hu $xr8, $xr8, $xr8\n\t"
"xvhaddw.wu.hu $xr9, $xr9, $xr9\n\t"
"xvilvl.w $xr0, $xr9, $xr8\n\t"
"xvilvh.w $xr1, $xr9, $xr8\n\t"
"xvilvl.w $xr2, $xr11, $xr10\n\t"
"xvilvh.w $xr3, $xr11, $xr10\n\t"
"xvilvl.d $xr4, $xr2, $xr0\n\t"
"xvilvh.d $xr5, $xr2, $xr0\n\t"
"xvilvl.d $xr6, $xr3, $xr1\n\t"
"xvilvh.d $xr7, $xr3, $xr1\n\t"
"xvor.v $xr0, $xr5, $xr5\n\t"
"xvpermi.q $xr0, $xr4, 0x20\n\t"
"xvpermi.q $xr5, $xr4, 0x31\n\t"
"xvor.v $xr1, $xr7, $xr7\n\t"
"xvpermi.q $xr1, $xr6, 0x20\n\t"
"xvpermi.q $xr7, $xr6, 0x31\n\t"
"xvst $xr0, %[dst], 0\n\t"
"xvst $xr1, %[dst], 32\n\t"
"xvst $xr5, %[dst], 64\n\t"
"xvst $xr7, %[dst], 96\n\t"
"addi.d %[sa], %[sa], 32\n\t"
"addi.d %[sb], %[sb], 32\n\t"
"addi.d %[dst], %[dst], 128\n\t"
"addi.d %[cnt], %[cnt], -32\n\t"
"bnez %[cnt], 1b\n\t"
: [sa] "+r"(src_a), [sb] "+r"(src_b), [dst] "+r"(dst), [cnt] "+r"(width),
[pa] "=&r"(pa), [pb] "=&r"(pb), [r] "=&r"(r)
: [sta] "r"((ptrdiff_t)stride_a), [stb] "r"((ptrdiff_t)stride_b)
: "memory", "$xr0", "$xr1", "$xr2", "$xr3", "$xr4", "$xr5", "$xr6",
"$xr7", "$xr8", "$xr9", "$xr10", "$xr11");
}
#endif // HAS_SSIM4X4ROW_LASX
#ifdef HAS_SSIMWINDOWROW_LASX
float SsimWindowRow_LASX(const uint32_t* row0,
const uint32_t* row1,
int num_windows) {
const uint32_t* row0_next = row0 + 4;
const uint32_t* row1_next = row1 + 4;
float total;
uint32_t c1 = 26634;
uint32_t c2 = 239708;
uint32_t c0 = 0;
asm volatile(
"xvreplgr2vr.w $xr6, %[c0]\n\t"
"xvreplgr2vr.w $xr4, %[c1]\n\t"
"xvreplgr2vr.w $xr5, %[c2]\n\t"
"addi.d %[cnt], %[cnt], -2\n\t"
"bltz %[cnt], 2f\n\t"
"1:\n\t"
"xvld $xr0, %[r0], 0\n\t"
"xvld $xr1, %[r0n], 0\n\t"
"xvld $xr2, %[r1], 0\n\t"
"xvld $xr3, %[r1n], 0\n\t"
"xvadd.w $xr0, $xr0, $xr1\n\t"
"xvadd.w $xr2, $xr2, $xr3\n\t"
"xvadd.w $xr0, $xr0, $xr2\n\t"
"xvshuf4i.w $xr1, $xr0, 0x00\n\t"
"xvshuf4i.w $xr2, $xr0, 0x55\n\t"
"xvshuf4i.w $xr3, $xr0, 0xaa\n\t"
"xvshuf4i.w $xr0, $xr0, 0xff\n\t"
"xvmul.w $xr7, $xr1, $xr2\n\t"
"xvslli.w $xr7, $xr7, 1\n\t"
"xvmul.w $xr1, $xr1, $xr1\n\t"
"xvmadd.w $xr1, $xr2, $xr2\n\t"
"xvslli.w $xr0, $xr0, 7\n\t"
"xvsub.w $xr0, $xr0, $xr7\n\t"
"xvadd.w $xr7, $xr7, $xr4\n\t"
"xvadd.w $xr0, $xr0, $xr5\n\t"
"xvslli.w $xr3, $xr3, 6\n\t"
"xvsub.w $xr3, $xr3, $xr1\n\t"
"xvadd.w $xr1, $xr1, $xr4\n\t"
"xvadd.w $xr3, $xr3, $xr5\n\t"
"xvffint.s.w $xr7, $xr7\n\t"
"xvffint.s.w $xr0, $xr0\n\t"
"xvffint.s.w $xr1, $xr1\n\t"
"xvffint.s.w $xr3, $xr3\n\t"
"xvfmul.s $xr7, $xr7, $xr0\n\t"
"xvfmul.s $xr1, $xr1, $xr3\n\t"
"xvfdiv.s $xr7, $xr7, $xr1\n\t"
"xvfadd.s $xr6, $xr6, $xr7\n\t"
"addi.d %[r0], %[r0], 32\n\t"
"addi.d %[r0n], %[r0n], 32\n\t"
"addi.d %[r1], %[r1], 32\n\t"
"addi.d %[r1n], %[r1n], 32\n\t"
"addi.d %[cnt], %[cnt], -2\n\t"
"bgez %[cnt], 1b\n\t"
"xvpermi.q $xr0, $xr6, 0x01\n\t"
"vfadd.s $vr6, $vr6, $vr0\n\t"
"2:\n\t"
"addi.d %[cnt], %[cnt], 2\n\t"
"beqz %[cnt], 3f\n\t"
"vld $vr0, %[r0], 0\n\t"
"vld $vr1, %[r0n], 0\n\t"
"vld $vr2, %[r1], 0\n\t"
"vld $vr3, %[r1n], 0\n\t"
"vadd.w $vr0, $vr0, $vr1\n\t"
"vadd.w $vr2, $vr2, $vr3\n\t"
"vadd.w $vr0, $vr0, $vr2\n\t"
"vshuf4i.w $vr1, $vr0, 0x00\n\t"
"vshuf4i.w $vr2, $vr0, 0x55\n\t"
"vshuf4i.w $vr3, $vr0, 0xaa\n\t"
"vshuf4i.w $vr0, $vr0, 0xff\n\t"
"vmul.w $vr7, $vr1, $vr2\n\t"
"vslli.w $vr7, $vr7, 1\n\t"
"vmul.w $vr1, $vr1, $vr1\n\t"
"vmadd.w $vr1, $vr2, $vr2\n\t"
"vslli.w $vr0, $vr0, 7\n\t"
"vsub.w $vr0, $vr0, $vr7\n\t"
"vadd.w $vr7, $vr7, $vr4\n\t"
"vadd.w $vr0, $vr0, $vr5\n\t"
"vslli.w $vr3, $vr3, 6\n\t"
"vsub.w $vr3, $vr3, $vr1\n\t"
"vadd.w $vr1, $vr1, $vr4\n\t"
"vadd.w $vr3, $vr3, $vr5\n\t"
"vffint.s.w $vr7, $vr7\n\t"
"vffint.s.w $vr0, $vr0\n\t"
"vffint.s.w $vr1, $vr1\n\t"
"vffint.s.w $vr3, $vr3\n\t"
"vfmul.s $vr7, $vr7, $vr0\n\t"
"vfmul.s $vr1, $vr1, $vr3\n\t"
"vfdiv.s $vr7, $vr7, $vr1\n\t"
"vfadd.s $vr6, $vr6, $vr7\n\t"
"3:\n\t"
"vstelm.w $vr6, %[tot], 0, 0\n\t"
: [r0] "+r"(row0), [r0n] "+r"(row0_next), [r1] "+r"(row1),
[r1n] "+r"(row1_next), [cnt] "+r"(num_windows)
: [c0] "r"(c0), [c1] "r"(c1), [c2] "r"(c2), [tot] "r"(&total)
: "memory", "$xr0", "$xr1", "$xr2", "$xr3", "$xr4", "$xr5", "$xr6",
"$xr7");
return total;
}
#endif // HAS_SSIMWINDOWROW_LASX
#ifdef HAS_ARGBDETECTROW_LASX
uint32_t ARGBDetectRow_LASX(const uint8_t* argb, int width) {
uint32_t diff = 0;
uint32_t tmp;
uint32_t rgb_mask = 0x00ffff00u;
asm volatile(
"xvreplgr2vr.w $xr2, %[rgb_mask]\n\t"
"addi.d %[w], %[w], -8\n\t"
"bltz %[w], 2f\n\t"
"1:\n\t"
"xvld $xr0, %[argb], 0\n\t"
"addi.d %[argb], %[argb], 32\n\t"
"xvor.v $xr0, $xr0, $xr2\n\t"
"xvseqi.b $xr0, $xr0, -1\n\t"
"xvmskltz.b $xr0, $xr0\n\t"
"xvpickve2gr.wu %[diff], $xr0, 0\n\t"
"xvpickve2gr.wu %[tmp], $xr0, 4\n\t"
"bstrins.w %[diff], %[tmp], 31, 16\n\t"
"nor %[diff], %[diff], $zero\n\t"
"bnez %[diff], 4f\n\t"
"addi.d %[w], %[w], -8\n\t"
"bgez %[w], 1b\n\t"
"2:\n\t"
"addi.d %[w], %[w], 8\n\t"
"beqz %[w], 4f\n\t"
"3:\n\t"
"vldrepl.w $vr0, %[argb], 0\n\t"
"addi.d %[argb], %[argb], 4\n\t"
"vor.v $vr0, $vr0, $vr2\n\t"
"vseqi.b $vr0, $vr0, -1\n\t"
"vmskltz.b $vr0, $vr0\n\t"
"vpickve2gr.hu %[diff], $vr0, 0\n\t"
"nor %[diff], %[diff], $zero\n\t"
"bstrpick.w %[diff], %[diff], 15, 0\n\t"
"bnez %[diff], 4f\n\t"
"addi.d %[w], %[w], -1\n\t"
"bnez %[w], 3b\n\t"
"4:\n\t"
: [argb] "+r"(argb), [w] "+r"(width), [diff] "+r"(diff), [tmp] "=&r"(tmp)
: [rgb_mask] "r"(rgb_mask)
: "memory", "$xr0", "$xr2");
if (diff) {
return (__builtin_ctz(diff) & 3) == 0 ? FOURCC_BGRA : FOURCC_ARGB;
}
return 0;
}
#endif // HAS_ARGBDETECTROW_LASX
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
#endif
#endif // (!defined(LIBYUV_DISABLE_LSX) || !defined(LIBYUV_DISABLE_LASX)) &&
// defined(__loongarch_lp64)

View File

@ -1,5 +1,5 @@
/*
* Copyright 2026 The LibYuv Project Authors. All rights reserved.
* Copyright 2022 The LibYuv Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
@ -9,14 +9,383 @@
*/
#include "libyuv/rotate_row.h"
#include "libyuv/row.h"
#if !defined(LIBYUV_DISABLE_LASX) && defined(__loongarch_asx)
#if (!defined(LIBYUV_DISABLE_LSX) || !defined(LIBYUV_DISABLE_LASX)) && \
defined(__loongarch_lp64)
#ifdef __cplusplus
namespace libyuv {
extern "C" {
#endif
#ifdef HAS_TRANSPOSEWX8_LSX
void TransposeWx8_LSX(const uint8_t* src,
int src_stride,
uint8_t* dst,
int dst_stride,
int width) {
const ptrdiff_t s = src_stride;
const ptrdiff_t d = dst_stride;
const uint8_t* t;
asm volatile(
"srli.w %[w], %[w], 4 \n"
"beqz %[w], 2f \n"
"1: \n"
"move %[t], %[src] \n"
"vld $vr0, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr1, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr2, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr3, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr4, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr5, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr6, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr7, %[t], 0 \n"
"addi.d %[src], %[src], 16 \n"
"vilvl.b $vr8, $vr1, $vr0 \n"
"vilvh.b $vr9, $vr1, $vr0 \n"
"vilvl.b $vr10, $vr3, $vr2 \n"
"vilvh.b $vr11, $vr3, $vr2 \n"
"vilvl.b $vr12, $vr5, $vr4 \n"
"vilvh.b $vr13, $vr5, $vr4 \n"
"vilvl.b $vr14, $vr7, $vr6 \n"
"vilvh.b $vr15, $vr7, $vr6 \n"
"vilvl.h $vr0, $vr10, $vr8 \n"
"vilvh.h $vr1, $vr10, $vr8 \n"
"vilvl.h $vr2, $vr11, $vr9 \n"
"vilvh.h $vr3, $vr11, $vr9 \n"
"vilvl.h $vr4, $vr14, $vr12 \n"
"vilvh.h $vr5, $vr14, $vr12 \n"
"vilvl.h $vr6, $vr15, $vr13 \n"
"vilvh.h $vr7, $vr15, $vr13 \n"
"vilvl.w $vr8, $vr4, $vr0 \n"
"vilvh.w $vr9, $vr4, $vr0 \n"
"vilvl.w $vr10, $vr5, $vr1 \n"
"vilvh.w $vr11, $vr5, $vr1 \n"
"vilvl.w $vr12, $vr6, $vr2 \n"
"vilvh.w $vr13, $vr6, $vr2 \n"
"vilvl.w $vr14, $vr7, $vr3 \n"
"vilvh.w $vr15, $vr7, $vr3 \n"
"vstelm.d $vr8, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr8, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr9, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr9, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr10, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr10, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr11, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr11, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr12, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr12, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr13, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr13, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr14, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr14, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr15, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr15, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"addi.w %[w], %[w], -1 \n"
"bnez %[w], 1b \n"
"2: \n"
: [src] "+r"(src), // %[src]
[dst] "+r"(dst), // %[dst]
[w] "+r"(width), // %[w]
[t] "=&r"(t) // %[t]
: [s] "r"(s), // %[s]
[d] "r"(d) // %[d]
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14",
"$vr15");
}
#endif // HAS_TRANSPOSEWX8_LSX
#ifdef HAS_TRANSPOSEUVWX8_LSX
void TransposeUVWx8_LSX(const uint8_t* src,
int src_stride,
uint8_t* dst_a,
int dst_stride_a,
uint8_t* dst_b,
int dst_stride_b,
int width) {
const ptrdiff_t s = src_stride;
const ptrdiff_t da = dst_stride_a;
const ptrdiff_t db = dst_stride_b;
const uint8_t* t;
asm volatile(
"srli.w %[w], %[w], 3 \n"
"beqz %[w], 2f \n"
"1: \n"
"move %[t], %[src] \n"
"vld $vr0, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr1, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr2, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr3, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr4, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr5, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr6, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr7, %[t], 0 \n"
"addi.d %[src], %[src], 16 \n"
"vilvl.b $vr8, $vr1, $vr0 \n"
"vilvh.b $vr9, $vr1, $vr0 \n"
"vilvl.b $vr10, $vr3, $vr2 \n"
"vilvh.b $vr11, $vr3, $vr2 \n"
"vilvl.b $vr12, $vr5, $vr4 \n"
"vilvh.b $vr13, $vr5, $vr4 \n"
"vilvl.b $vr14, $vr7, $vr6 \n"
"vilvh.b $vr15, $vr7, $vr6 \n"
"vilvl.h $vr0, $vr10, $vr8 \n"
"vilvh.h $vr1, $vr10, $vr8 \n"
"vilvl.h $vr2, $vr11, $vr9 \n"
"vilvh.h $vr3, $vr11, $vr9 \n"
"vilvl.h $vr4, $vr14, $vr12 \n"
"vilvh.h $vr5, $vr14, $vr12 \n"
"vilvl.h $vr6, $vr15, $vr13 \n"
"vilvh.h $vr7, $vr15, $vr13 \n"
"vilvl.w $vr8, $vr4, $vr0 \n"
"vilvh.w $vr9, $vr4, $vr0 \n"
"vilvl.w $vr10, $vr5, $vr1 \n"
"vilvh.w $vr11, $vr5, $vr1 \n"
"vilvl.w $vr12, $vr6, $vr2 \n"
"vilvh.w $vr13, $vr6, $vr2 \n"
"vilvl.w $vr14, $vr7, $vr3 \n"
"vilvh.w $vr15, $vr7, $vr3 \n"
"vstelm.d $vr8, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr8, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr9, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr9, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr10, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr10, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr11, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr11, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr12, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr12, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr13, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr13, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr14, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr14, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr15, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr15, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"addi.w %[w], %[w], -1 \n"
"bnez %[w], 1b \n"
"2: \n"
: [src] "+r"(src), // %[src]
[dst_a] "+r"(dst_a), // %[dst_a]
[dst_b] "+r"(dst_b), // %[dst_b]
[w] "+r"(width), // %[w]
[t] "=&r"(t) // %[t]
: [s] "r"(s), // %[s]
[da] "r"(da), // %[da]
[db] "r"(db) // %[db]
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14",
"$vr15");
}
#endif // HAS_TRANSPOSEUVWX8_LSX
#ifdef HAS_TRANSPOSEWX4_32_LSX
void TransposeWx4_32_LSX(const uint8_t* src,
int src_stride,
uint8_t* dst,
int dst_stride,
int width) {
const ptrdiff_t s = src_stride;
const ptrdiff_t s2 = s * 2;
const ptrdiff_t s3 = s + s2;
const ptrdiff_t s4 = s * 4;
uint8_t* dst0 = dst;
uint8_t* dst1 = dst0 + dst_stride;
uint8_t* dst2 = dst1 + dst_stride;
uint8_t* dst3 = dst2 + dst_stride;
asm volatile(
"srli.w %[w], %[w], 2 \n"
"beqz %[w], 2f \n"
"1: \n"
"vld $vr0, %[src], 0 \n"
"vldx $vr1, %[src], %[s] \n"
"vldx $vr2, %[src], %[s2] \n"
"vldx $vr3, %[src], %[s3] \n"
"add.d %[src], %[src], %[s4] \n"
"vilvl.w $vr4, $vr1, $vr0 \n"
"vilvh.w $vr5, $vr1, $vr0 \n"
"vilvl.w $vr6, $vr3, $vr2 \n"
"vilvh.w $vr7, $vr3, $vr2 \n"
"vilvl.d $vr0, $vr6, $vr4 \n"
"vilvh.d $vr1, $vr6, $vr4 \n"
"vilvl.d $vr2, $vr7, $vr5 \n"
"vilvh.d $vr3, $vr7, $vr5 \n"
"vst $vr0, %[dst0], 0 \n"
"vst $vr1, %[dst1], 0 \n"
"vst $vr2, %[dst2], 0 \n"
"vst $vr3, %[dst3], 0 \n"
"addi.d %[dst0], %[dst0], 16 \n"
"addi.d %[dst1], %[dst1], 16 \n"
"addi.d %[dst2], %[dst2], 16 \n"
"addi.d %[dst3], %[dst3], 16 \n"
"addi.w %[w], %[w], -1 \n"
"bnez %[w], 1b \n"
"2: \n"
: [src] "+r"(src), // %[src]
[dst0] "+r"(dst0), // %[dst0]
[dst1] "+r"(dst1), // %[dst1]
[dst2] "+r"(dst2), // %[dst2]
[dst3] "+r"(dst3), // %[dst3]
[w] "+r"(width) // %[w]
: [s] "r"(s), // %[s]
[s2] "r"(s2), // %[s2]
[s3] "r"(s3), // %[s3]
[s4] "r"(s4) // %[s4]
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7");
}
#endif // HAS_TRANSPOSEWX4_32_LSX
#ifdef HAS_TRANSPOSEWX8_16_LSX
void TransposeWx8_16_LSX(const uint16_t* src,
int src_stride,
uint16_t* dst,
int dst_stride,
int width) {
const ptrdiff_t s = (ptrdiff_t)src_stride * 2;
const ptrdiff_t d = (ptrdiff_t)dst_stride * 2;
const uint8_t* src_b = (const uint8_t*)src;
uint8_t* dst_b = (uint8_t*)dst;
const uint8_t* t;
asm volatile(
"srli.w %[w], %[w], 3 \n"
"beqz %[w], 2f \n"
"1: \n"
"move %[t], %[src] \n"
"vld $vr0, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr1, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr2, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr3, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr4, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr5, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr6, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr7, %[t], 0 \n"
"addi.d %[src], %[src], 16 \n"
"vilvl.h $vr8, $vr1, $vr0 \n"
"vilvh.h $vr9, $vr1, $vr0 \n"
"vilvl.h $vr10, $vr3, $vr2 \n"
"vilvh.h $vr11, $vr3, $vr2 \n"
"vilvl.h $vr12, $vr5, $vr4 \n"
"vilvh.h $vr13, $vr5, $vr4 \n"
"vilvl.h $vr14, $vr7, $vr6 \n"
"vilvh.h $vr15, $vr7, $vr6 \n"
"vilvl.w $vr0, $vr10, $vr8 \n"
"vilvh.w $vr1, $vr10, $vr8 \n"
"vilvl.w $vr2, $vr11, $vr9 \n"
"vilvh.w $vr3, $vr11, $vr9 \n"
"vilvl.w $vr4, $vr14, $vr12 \n"
"vilvh.w $vr5, $vr14, $vr12 \n"
"vilvl.w $vr6, $vr15, $vr13 \n"
"vilvh.w $vr7, $vr15, $vr13 \n"
"vilvl.d $vr8, $vr4, $vr0 \n"
"vilvh.d $vr9, $vr4, $vr0 \n"
"vilvl.d $vr10, $vr5, $vr1 \n"
"vilvh.d $vr11, $vr5, $vr1 \n"
"vilvl.d $vr12, $vr6, $vr2 \n"
"vilvh.d $vr13, $vr6, $vr2 \n"
"vilvl.d $vr14, $vr7, $vr3 \n"
"vilvh.d $vr15, $vr7, $vr3 \n"
"vst $vr8, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr9, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr10, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr11, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr12, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr13, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr14, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr15, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"addi.w %[w], %[w], -1 \n"
"bnez %[w], 1b \n"
"2: \n"
: [src] "+r"(src_b), // %[src]
[dst] "+r"(dst_b), // %[dst]
[w] "+r"(width), // %[w]
[t] "=&r"(t) // %[t]
: [s] "r"(s), // %[s]
[d] "r"(d) // %[d]
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14",
"$vr15");
}
#endif // HAS_TRANSPOSEWX8_16_LSX
#ifdef HAS_TRANSPOSEWX16_LASX
void TransposeWx16_LASX(const uint8_t* src,
int src_stride,
uint8_t* dst,
@ -161,7 +530,9 @@ void TransposeWx16_LASX(const uint8_t* src,
"$xr7", "$xr8", "$xr9", "$xr10", "$xr11", "$xr12", "$xr13", "$xr14",
"$xr15");
}
#endif // HAS_TRANSPOSEWX16_LASX
#ifdef HAS_TRANSPOSEUVWX16_LASX
void TransposeUVWx16_LASX(const uint8_t* src,
int src_stride,
uint8_t* dst_a,
@ -311,7 +682,9 @@ void TransposeUVWx16_LASX(const uint8_t* src,
"$xr7", "$xr8", "$xr9", "$xr10", "$xr11", "$xr12", "$xr13", "$xr14",
"$xr15");
}
#endif // HAS_TRANSPOSEUVWX16_LASX
#ifdef HAS_TRANSPOSEWX4_32_LASX
void TransposeWx4_32_LASX(const uint8_t* src,
int src_stride,
uint8_t* dst,
@ -382,7 +755,9 @@ void TransposeWx4_32_LASX(const uint8_t* src,
: "memory", "$xr0", "$xr1", "$xr2", "$xr3", "$xr4", "$xr5", "$xr6",
"$xr7");
}
#endif // HAS_TRANSPOSEWX4_32_LASX
#ifdef HAS_TRANSPOSEWX16_16_LASX
void TransposeWx16_16_LASX(const uint16_t* src,
int src_stride,
uint16_t* dst,
@ -497,10 +872,12 @@ void TransposeWx16_16_LASX(const uint16_t* src,
"$xr7", "$xr8", "$xr9", "$xr10", "$xr11", "$xr12", "$xr13", "$xr14",
"$xr15");
}
#endif // HAS_TRANSPOSEWX16_16_LASX
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
#endif
#endif // !defined(LIBYUV_DISABLE_LASX) && defined(__loongarch_asx)
#endif // (!defined(LIBYUV_DISABLE_LSX) || !defined(LIBYUV_DISABLE_LASX)) &&
// defined(__loongarch_lp64)

View File

@ -1,383 +0,0 @@
/*
* Copyright 2022 The LibYuv Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "libyuv/rotate_row.h"
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)
#ifdef __cplusplus
namespace libyuv {
extern "C" {
#endif
void TransposeWx8_LSX(const uint8_t* src,
int src_stride,
uint8_t* dst,
int dst_stride,
int width) {
const ptrdiff_t s = src_stride;
const ptrdiff_t d = dst_stride;
const uint8_t* t;
asm volatile(
"srli.w %[w], %[w], 4 \n"
"beqz %[w], 2f \n"
"1: \n"
"move %[t], %[src] \n"
"vld $vr0, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr1, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr2, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr3, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr4, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr5, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr6, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr7, %[t], 0 \n"
"addi.d %[src], %[src], 16 \n"
"vilvl.b $vr8, $vr1, $vr0 \n"
"vilvh.b $vr9, $vr1, $vr0 \n"
"vilvl.b $vr10, $vr3, $vr2 \n"
"vilvh.b $vr11, $vr3, $vr2 \n"
"vilvl.b $vr12, $vr5, $vr4 \n"
"vilvh.b $vr13, $vr5, $vr4 \n"
"vilvl.b $vr14, $vr7, $vr6 \n"
"vilvh.b $vr15, $vr7, $vr6 \n"
"vilvl.h $vr0, $vr10, $vr8 \n"
"vilvh.h $vr1, $vr10, $vr8 \n"
"vilvl.h $vr2, $vr11, $vr9 \n"
"vilvh.h $vr3, $vr11, $vr9 \n"
"vilvl.h $vr4, $vr14, $vr12 \n"
"vilvh.h $vr5, $vr14, $vr12 \n"
"vilvl.h $vr6, $vr15, $vr13 \n"
"vilvh.h $vr7, $vr15, $vr13 \n"
"vilvl.w $vr8, $vr4, $vr0 \n"
"vilvh.w $vr9, $vr4, $vr0 \n"
"vilvl.w $vr10, $vr5, $vr1 \n"
"vilvh.w $vr11, $vr5, $vr1 \n"
"vilvl.w $vr12, $vr6, $vr2 \n"
"vilvh.w $vr13, $vr6, $vr2 \n"
"vilvl.w $vr14, $vr7, $vr3 \n"
"vilvh.w $vr15, $vr7, $vr3 \n"
"vstelm.d $vr8, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr8, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr9, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr9, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr10, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr10, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr11, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr11, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr12, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr12, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr13, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr13, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr14, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr14, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr15, %[dst], 0, 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vstelm.d $vr15, %[dst], 0, 1 \n"
"add.d %[dst], %[dst], %[d] \n"
"addi.w %[w], %[w], -1 \n"
"bnez %[w], 1b \n"
"2: \n"
: [src] "+r"(src), // %[src]
[dst] "+r"(dst), // %[dst]
[w] "+r"(width), // %[w]
[t] "=&r"(t) // %[t]
: [s] "r"(s), // %[s]
[d] "r"(d) // %[d]
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14",
"$vr15");
}
void TransposeUVWx8_LSX(const uint8_t* src,
int src_stride,
uint8_t* dst_a,
int dst_stride_a,
uint8_t* dst_b,
int dst_stride_b,
int width) {
const ptrdiff_t s = src_stride;
const ptrdiff_t da = dst_stride_a;
const ptrdiff_t db = dst_stride_b;
const uint8_t* t;
asm volatile(
"srli.w %[w], %[w], 3 \n"
"beqz %[w], 2f \n"
"1: \n"
"move %[t], %[src] \n"
"vld $vr0, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr1, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr2, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr3, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr4, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr5, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr6, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr7, %[t], 0 \n"
"addi.d %[src], %[src], 16 \n"
"vilvl.b $vr8, $vr1, $vr0 \n"
"vilvh.b $vr9, $vr1, $vr0 \n"
"vilvl.b $vr10, $vr3, $vr2 \n"
"vilvh.b $vr11, $vr3, $vr2 \n"
"vilvl.b $vr12, $vr5, $vr4 \n"
"vilvh.b $vr13, $vr5, $vr4 \n"
"vilvl.b $vr14, $vr7, $vr6 \n"
"vilvh.b $vr15, $vr7, $vr6 \n"
"vilvl.h $vr0, $vr10, $vr8 \n"
"vilvh.h $vr1, $vr10, $vr8 \n"
"vilvl.h $vr2, $vr11, $vr9 \n"
"vilvh.h $vr3, $vr11, $vr9 \n"
"vilvl.h $vr4, $vr14, $vr12 \n"
"vilvh.h $vr5, $vr14, $vr12 \n"
"vilvl.h $vr6, $vr15, $vr13 \n"
"vilvh.h $vr7, $vr15, $vr13 \n"
"vilvl.w $vr8, $vr4, $vr0 \n"
"vilvh.w $vr9, $vr4, $vr0 \n"
"vilvl.w $vr10, $vr5, $vr1 \n"
"vilvh.w $vr11, $vr5, $vr1 \n"
"vilvl.w $vr12, $vr6, $vr2 \n"
"vilvh.w $vr13, $vr6, $vr2 \n"
"vilvl.w $vr14, $vr7, $vr3 \n"
"vilvh.w $vr15, $vr7, $vr3 \n"
"vstelm.d $vr8, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr8, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr9, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr9, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr10, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr10, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr11, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr11, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr12, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr12, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr13, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr13, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr14, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr14, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"vstelm.d $vr15, %[dst_a], 0, 0 \n"
"add.d %[dst_a], %[dst_a], %[da] \n"
"vstelm.d $vr15, %[dst_b], 0, 1 \n"
"add.d %[dst_b], %[dst_b], %[db] \n"
"addi.w %[w], %[w], -1 \n"
"bnez %[w], 1b \n"
"2: \n"
: [src] "+r"(src), // %[src]
[dst_a] "+r"(dst_a), // %[dst_a]
[dst_b] "+r"(dst_b), // %[dst_b]
[w] "+r"(width), // %[w]
[t] "=&r"(t) // %[t]
: [s] "r"(s), // %[s]
[da] "r"(da), // %[da]
[db] "r"(db) // %[db]
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14",
"$vr15");
}
void TransposeWx4_32_LSX(const uint8_t* src,
int src_stride,
uint8_t* dst,
int dst_stride,
int width) {
const ptrdiff_t s = src_stride;
const ptrdiff_t s2 = s * 2;
const ptrdiff_t s3 = s + s2;
const ptrdiff_t s4 = s * 4;
uint8_t* dst0 = dst;
uint8_t* dst1 = dst0 + dst_stride;
uint8_t* dst2 = dst1 + dst_stride;
uint8_t* dst3 = dst2 + dst_stride;
asm volatile(
"srli.w %[w], %[w], 2 \n"
"beqz %[w], 2f \n"
"1: \n"
"vld $vr0, %[src], 0 \n"
"vldx $vr1, %[src], %[s] \n"
"vldx $vr2, %[src], %[s2] \n"
"vldx $vr3, %[src], %[s3] \n"
"add.d %[src], %[src], %[s4] \n"
"vilvl.w $vr4, $vr1, $vr0 \n"
"vilvh.w $vr5, $vr1, $vr0 \n"
"vilvl.w $vr6, $vr3, $vr2 \n"
"vilvh.w $vr7, $vr3, $vr2 \n"
"vilvl.d $vr0, $vr6, $vr4 \n"
"vilvh.d $vr1, $vr6, $vr4 \n"
"vilvl.d $vr2, $vr7, $vr5 \n"
"vilvh.d $vr3, $vr7, $vr5 \n"
"vst $vr0, %[dst0], 0 \n"
"vst $vr1, %[dst1], 0 \n"
"vst $vr2, %[dst2], 0 \n"
"vst $vr3, %[dst3], 0 \n"
"addi.d %[dst0], %[dst0], 16 \n"
"addi.d %[dst1], %[dst1], 16 \n"
"addi.d %[dst2], %[dst2], 16 \n"
"addi.d %[dst3], %[dst3], 16 \n"
"addi.w %[w], %[w], -1 \n"
"bnez %[w], 1b \n"
"2: \n"
: [src] "+r"(src), // %[src]
[dst0] "+r"(dst0), // %[dst0]
[dst1] "+r"(dst1), // %[dst1]
[dst2] "+r"(dst2), // %[dst2]
[dst3] "+r"(dst3), // %[dst3]
[w] "+r"(width) // %[w]
: [s] "r"(s), // %[s]
[s2] "r"(s2), // %[s2]
[s3] "r"(s3), // %[s3]
[s4] "r"(s4) // %[s4]
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7");
}
void TransposeWx8_16_LSX(const uint16_t* src,
int src_stride,
uint16_t* dst,
int dst_stride,
int width) {
const ptrdiff_t s = (ptrdiff_t)src_stride * 2;
const ptrdiff_t d = (ptrdiff_t)dst_stride * 2;
const uint8_t* src_b = (const uint8_t*)src;
uint8_t* dst_b = (uint8_t*)dst;
const uint8_t* t;
asm volatile(
"srli.w %[w], %[w], 3 \n"
"beqz %[w], 2f \n"
"1: \n"
"move %[t], %[src] \n"
"vld $vr0, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr1, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr2, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr3, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr4, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr5, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr6, %[t], 0 \n"
"add.d %[t], %[t], %[s] \n"
"vld $vr7, %[t], 0 \n"
"addi.d %[src], %[src], 16 \n"
"vilvl.h $vr8, $vr1, $vr0 \n"
"vilvh.h $vr9, $vr1, $vr0 \n"
"vilvl.h $vr10, $vr3, $vr2 \n"
"vilvh.h $vr11, $vr3, $vr2 \n"
"vilvl.h $vr12, $vr5, $vr4 \n"
"vilvh.h $vr13, $vr5, $vr4 \n"
"vilvl.h $vr14, $vr7, $vr6 \n"
"vilvh.h $vr15, $vr7, $vr6 \n"
"vilvl.w $vr0, $vr10, $vr8 \n"
"vilvh.w $vr1, $vr10, $vr8 \n"
"vilvl.w $vr2, $vr11, $vr9 \n"
"vilvh.w $vr3, $vr11, $vr9 \n"
"vilvl.w $vr4, $vr14, $vr12 \n"
"vilvh.w $vr5, $vr14, $vr12 \n"
"vilvl.w $vr6, $vr15, $vr13 \n"
"vilvh.w $vr7, $vr15, $vr13 \n"
"vilvl.d $vr8, $vr4, $vr0 \n"
"vilvh.d $vr9, $vr4, $vr0 \n"
"vilvl.d $vr10, $vr5, $vr1 \n"
"vilvh.d $vr11, $vr5, $vr1 \n"
"vilvl.d $vr12, $vr6, $vr2 \n"
"vilvh.d $vr13, $vr6, $vr2 \n"
"vilvl.d $vr14, $vr7, $vr3 \n"
"vilvh.d $vr15, $vr7, $vr3 \n"
"vst $vr8, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr9, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr10, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr11, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr12, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr13, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr14, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"vst $vr15, %[dst], 0 \n"
"add.d %[dst], %[dst], %[d] \n"
"addi.w %[w], %[w], -1 \n"
"bnez %[w], 1b \n"
"2: \n"
: [src] "+r"(src_b), // %[src]
[dst] "+r"(dst_b), // %[dst]
[w] "+r"(width), // %[w]
[t] "=&r"(t) // %[t]
: [s] "r"(s), // %[s]
[d] "r"(d) // %[d]
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14",
"$vr15");
}
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
#endif
#endif // !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,34 +8,18 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include <assert.h>
#include "libyuv/row.h"
#include "libyuv/scale_row.h"
#if !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)
#if (!defined(LIBYUV_DISABLE_LSX) || !defined(LIBYUV_DISABLE_LASX)) && \
defined(__loongarch_lp64)
#ifdef __cplusplus
namespace libyuv {
extern "C" {
#endif
static const uint64_t kScale38Shuf[2] = {0x13100e0b08060300ULL,
0x000000001e1b1816ULL};
static const uint64_t kScale38BoxShuf[2] = {0x0a08160604120200ULL,
0x000000001e0e0c1aULL};
static const uint64_t kScale34Shuf[2] = {0x0908070504030100ULL,
0x000000000f0d0c0bULL};
static const uint64_t kScale34BoxLo[2] = {0x0504030202010100ULL,
0x0000000007060605ULL};
static const uint64_t kScale34BoxHi[2] = {0x0d0c0b0a0a090908ULL,
0x000000000f0e0e0dULL};
static const uint64_t kScale34BoxWt[2] = {0x0103030102020103ULL,
0x0000000003010202ULL};
static const uint64_t kScale34Pack12[2] = {0x0908050403020100ULL,
0x000000000d0c0b0aULL};
static const uint64_t kRamp0123[2] = {0x0000000100000000ULL,
0x0000000300000002ULL};
#ifdef HAS_SCALEARGBROWDOWN2_LSX
void ScaleARGBRowDown2_LSX(const uint8_t* src_argb,
ptrdiff_t src_stride,
uint8_t* dst_argb,
@ -129,7 +113,9 @@ void ScaleARGBRowDown2Box_LSX(const uint8_t* src_argb,
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7");
}
#endif // HAS_SCALEARGBROWDOWN2_LSX
#ifdef HAS_SCALEARGBROWDOWNEVEN_LSX
void ScaleARGBRowDownEven_LSX(const uint8_t* src_argb,
ptrdiff_t src_stride,
int32_t src_stepx,
@ -235,7 +221,9 @@ void ScaleARGBRowDownEvenBox_LSX(const uint8_t* src_argb,
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7");
}
#endif // HAS_SCALEARGBROWDOWNEVEN_LSX
#ifdef HAS_SCALEROWDOWN2_LSX
void ScaleRowDown2_LSX(const uint8_t* src_ptr,
ptrdiff_t src_stride,
uint8_t* dst,
@ -323,7 +311,9 @@ void ScaleRowDown2Box_LSX(const uint8_t* src_ptr,
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7");
}
#endif // HAS_SCALEROWDOWN2_LSX
#ifdef HAS_SCALEROWDOWN4_LSX
void ScaleRowDown4_LSX(const uint8_t* src_ptr,
ptrdiff_t src_stride,
uint8_t* dst,
@ -406,6 +396,13 @@ void ScaleRowDown4Box_LSX(const uint8_t* src_ptr,
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7");
}
#endif // HAS_SCALEROWDOWN4_LSX
#ifdef HAS_SCALEROWDOWN38_LSX
static const uint64_t kScale38Shuf[2] = {0x13100e0b08060300ULL,
0x000000001e1b1816ULL};
static const uint64_t kScale38BoxShuf[2] = {0x0a08160604120200ULL,
0x000000001e0e0c1aULL};
void ScaleRowDown38_LSX(const uint8_t* src_ptr,
ptrdiff_t src_stride,
@ -553,7 +550,9 @@ void ScaleRowDown38_3_Box_LSX(const uint8_t* src_ptr,
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9", "$vr10", "$vr11");
}
#endif // HAS_SCALEROWDOWN38_LSX
#ifdef HAS_SCALEADDROW_LSX
void ScaleAddRow_LSX(const uint8_t* src_ptr, uint16_t* dst_ptr, int src_width) {
asm volatile(
"srli.w %[w], %[w], 4 \n"
@ -580,7 +579,9 @@ void ScaleAddRow_LSX(const uint8_t* src_ptr, uint16_t* dst_ptr, int src_width) {
:
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5");
}
#endif // HAS_SCALEADDROW_LSX
#ifdef HAS_SCALEUVADDCOLS3_LSX
static const uint8_t kScaleUVAddCols3Shuf[] = {
0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 4, 5, 6, 7,
4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 8, 9, 10, 11,
@ -641,7 +642,15 @@ void ScaleUVAddCols3_LSX(int dst_width,
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9", "$vr10", "$vr11", "$vr12", "$vr13");
}
#endif // HAS_SCALEUVADDCOLS3_LSX
#if defined(HAS_SCALEFILTERCOLS_LSX) || defined(HAS_SCALEARGBCOLS_LSX) || \
defined(HAS_SCALEARGBFILTERCOLS_LSX)
static const uint64_t kRamp0123[2] = {0x0000000100000000ULL,
0x0000000300000002ULL};
#endif
#ifdef HAS_SCALEFILTERCOLS_LSX
void ScaleFilterCols_LSX(uint8_t* dst_ptr,
const uint8_t* src_ptr,
int dst_width,
@ -706,7 +715,9 @@ void ScaleFilterCols_LSX(uint8_t* dst_ptr,
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7");
}
#endif // HAS_SCALEFILTERCOLS_LSX
#ifdef HAS_SCALEARGBCOLS_LSX
void ScaleARGBCols_LSX(uint8_t* dst_argb,
const uint8_t* src_argb,
int dst_width,
@ -757,7 +768,9 @@ void ScaleARGBCols_LSX(uint8_t* dst_argb,
[ramp] "r"(kRamp0123) // %[ramp]
: "memory", "$vr0", "$vr1", "$vr2", "$vr3");
}
#endif // HAS_SCALEARGBCOLS_LSX
#ifdef HAS_SCALEARGBFILTERCOLS_LSX
void ScaleARGBFilterCols_LSX(uint8_t* dst_argb,
const uint8_t* src_argb,
int dst_width,
@ -826,6 +839,19 @@ void ScaleARGBFilterCols_LSX(uint8_t* dst_argb,
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8");
}
#endif // HAS_SCALEARGBFILTERCOLS_LSX
#ifdef HAS_SCALEROWDOWN34_LSX
static const uint64_t kScale34Shuf[2] = {0x0908070504030100ULL,
0x000000000f0d0c0bULL};
static const uint64_t kScale34BoxLo[2] = {0x0504030202010100ULL,
0x0000000007060605ULL};
static const uint64_t kScale34BoxHi[2] = {0x0d0c0b0a0a090908ULL,
0x000000000f0e0e0dULL};
static const uint64_t kScale34BoxWt[2] = {0x0103030102020103ULL,
0x0000000003010202ULL};
static const uint64_t kScale34Pack12[2] = {0x0908050403020100ULL,
0x000000000d0c0b0aULL};
void ScaleRowDown34_LSX(const uint8_t* src_ptr,
ptrdiff_t src_stride,
@ -966,10 +992,12 @@ void ScaleRowDown34_1_Box_LSX(const uint8_t* src_ptr,
: "memory", "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6",
"$vr7", "$vr8", "$vr9");
}
#endif // HAS_SCALEROWDOWN34_LSX
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
#endif
#endif // !defined(LIBYUV_DISABLE_LSX) && defined(__loongarch_sx)
#endif // (!defined(LIBYUV_DISABLE_LSX) || !defined(LIBYUV_DISABLE_LASX)) &&
// defined(__loongarch_lp64)

View File

@ -338,11 +338,19 @@ TEST_F(LibYUVCompareTest, BenchmarkHammingDistance_Opt) {
#elif defined(HAS_HAMMINGDISTANCE_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
h1 = HammingDistance_LASX(src_a, src_b, kMaxWidth);
} else {
#if defined(HAS_HAMMINGDISTANCE_LSX)
} else if (TestCpuFlag(kCpuHasLSX)) {
h1 = HammingDistance_LSX(src_a, src_b, kMaxWidth);
#endif
} else {
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
}
#elif defined(HAS_HAMMINGDISTANCE_LSX)
h1 = HammingDistance_LSX(src_a, src_b, kMaxWidth);
if (TestCpuFlag(kCpuHasLSX)) {
h1 = HammingDistance_LSX(src_a, src_b, kMaxWidth);
} else {
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
}
#elif defined(HAS_HAMMINGDISTANCE_WASMSIMD)
h1 = HammingDistance_WASMSIMD(src_a, src_b, kMaxWidth);
#elif defined(HAS_HAMMINGDISTANCE_HVX)
@ -493,11 +501,19 @@ TEST_F(LibYUVCompareTest, TestHammingDistance_Opt) {
#elif defined(HAS_HAMMINGDISTANCE_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
h1 = HammingDistance_LASX(src_a, src_b, kMaxWidth);
} else {
#if defined(HAS_HAMMINGDISTANCE_LSX)
} else if (TestCpuFlag(kCpuHasLSX)) {
h1 = HammingDistance_LSX(src_a, src_b, kMaxWidth);
#endif
} else {
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
}
#elif defined(HAS_HAMMINGDISTANCE_LSX)
h1 = HammingDistance_LSX(src_a, src_b, kMaxWidth);
if (TestCpuFlag(kCpuHasLSX)) {
h1 = HammingDistance_LSX(src_a, src_b, kMaxWidth);
} else {
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
}
#elif defined(HAS_HAMMINGDISTANCE_WASMSIMD)
h1 = HammingDistance_WASMSIMD(src_a, src_b, kMaxWidth);
#elif defined(HAS_HAMMINGDISTANCE_HVX)