From 17f63e53f83e6cef3490d5edc8a24d5b22bbabe1 Mon Sep 17 00:00:00 2001 From: yuanhecai Date: Tue, 31 May 2022 19:10:05 +0800 Subject: [PATCH] Add loongarch support LSX and LASX are enabled by default if compiler supports them. --- configure | 127 ++++++++++++++++++++++++++++++++++++++ configure.ac | 64 +++++++++++++++++++ include/SDL_config.h.in | 2 + include/SDL_cpuinfo.h | 30 +++++++++ src/cpuinfo/SDL_cpuinfo.c | 45 ++++++++++++++ 5 files changed, 268 insertions(+) diff --git a/configure b/configure index 7032f7c71..121593e16 100755 --- a/configure +++ b/configure @@ -838,6 +838,8 @@ enable_3dnow enable_sse enable_sse2 enable_sse3 +enable_lsx +enable_lasx enable_altivec enable_oss enable_alsa @@ -1620,6 +1622,8 @@ Optional Features: --enable-sse use SSE assembly routines [default=yes] --enable-sse2 use SSE2 assembly routines [default=maybe] --enable-sse3 use SSE3 assembly routines [default=maybe] + --enable-lsx use LSX assembly routines [default=yes] + --enable-lasx use LASX assembly routines [default=yes] --enable-altivec use Altivec assembly routines [default=yes] --enable-oss support the OSS audio API [default=maybe] --enable-alsa support the ALSA audio API [default=yes] @@ -18769,6 +18773,129 @@ $as_echo "#define HAVE_IMMINTRIN_H 1" >>confdefs.h fi + # Check whether --enable-lsx was given. +if test "${enable_lsx+set}" = set; then : + enableval=$enable_lsx; +else + enable_lsx=yes +fi + + if test x$enable_lsx = xyes; then + save_CFLAGS="$CFLAGS" + have_gcc_lsx=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -mlsx option" >&5 +$as_echo_n "checking for GCC -mlsx option... " >&6; } + lsx_CFLAGS="-mlsx" + CFLAGS="$save_CFLAGS $lsx_CFLAGS" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #ifndef __loongarch_sx + #error Assembler CPP flag not enabled + #endif + +int +main () +{ + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + have_gcc_lsx=yes + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_lsx" >&5 +$as_echo "$have_gcc_lsx" >&6; } + CFLAGS="$save_CFLAGS" + + if test x$have_gcc_lsx = xyes; then + EXTRA_CFLAGS="$EXTRA_CFLAGS $lsx_CFLAGS" + SUMMARY_math="${SUMMARY_math} lsx" + fi + fi + + ac_fn_c_check_header_mongrel "$LINENO" "lsxintrin.h" "ac_cv_header_lsxintrin_h" "$ac_includes_default" +if test "x$ac_cv_header_lsxintrin_h" = xyes; then : + have_lsx_h_hdr=yes +else + have_lsx_h_hdr=no +fi + + + if test x$have_lsx_h_hdr = xyes; then + +$as_echo "#define HAVE_LSXINTRIN_H 1" >>confdefs.h + + fi + + + # Check whether --enable-lasx was given. +if test "${enable_lasx+set}" = set; then : + enableval=$enable_lasx; +else + enable_LASX=yes +fi + + if test x$enable_LASX = xyes; then + save_CFLAGS="$CFLAGS" + have_gcc_lasx=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -mlasx option" >&5 +$as_echo_n "checking for GCC -mlasx option... " >&6; } + lasx_CFLAGS="-mlasx" + CFLAGS="$save_CFLAGS $lasx_CFLAGS" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #ifndef __loongarch_asx + #error Assembler CPP flag not enabled + #endif + +int +main () +{ + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + have_gcc_lasx=yes + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_lasx" >&5 +$as_echo "$have_gcc_lasx" >&6; } + CFLAGS="$save_CFLAGS" + + if test x$have_gcc_lasx = xyes; then + EXTRA_CFLAGS="$EXTRA_CFLAGS $lasx_CFLAGS" + SUMMARY_math="${SUMMARY_math} lasx" + fi + fi + + ac_fn_c_check_header_mongrel "$LINENO" "lasxintrin.h" "ac_cv_header_lasxintrin_h" "$ac_includes_default" +if test "x$ac_cv_header_lasxintrin_h" = xyes; then : + have_lasx_h_hdr=yes +else + have_lasx_h_hdr=no +fi + + + if test x$have_lasx_h_hdr = xyes; then + +$as_echo "#define HAVE_LASXINTRIN_H 1" >>confdefs.h + + fi + # Check whether --enable-altivec was given. if test "${enable_altivec+set}" = set; then : enableval=$enable_altivec; diff --git a/configure.ac b/configure.ac index 8bba0af0c..421ea98ce 100644 --- a/configure.ac +++ b/configure.ac @@ -852,6 +852,70 @@ dnl Check for various instruction support fi fi + AC_ARG_ENABLE(lsx, +[AC_HELP_STRING([--enable-lsx], [use LSX assembly routines [default=yes]])], + , enable_lsx=yes) + if test x$enable_lsx = xyes; then + save_CFLAGS="$CFLAGS" + have_gcc_lsx=no + AC_MSG_CHECKING(for GCC -mlsx option) + lsx_CFLAGS="-mlsx" + CFLAGS="$save_CFLAGS $lsx_CFLAGS" + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #ifndef __loongarch_sx + #error Assembler CPP flag not enabled + #endif + ]], [])], [have_gcc_lsx=yes], []) + AC_MSG_RESULT($have_gcc_lsx) + CFLAGS="$save_CFLAGS" + + if test x$have_gcc_lsx = xyes; then + EXTRA_CFLAGS="$EXTRA_CFLAGS $lsx_CFLAGS" + SUMMARY_math="${SUMMARY_math} lsx" + fi + fi + + AC_MSG_CHECKING(for lsxintrin.h) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]])], + [have_lsxintrin_h_hdr=yes],[have_lsxintrin_h_hdr=no]) + AC_MSG_RESULT($have_lsxintrin_h_hdr) + if test x$have_lsxintrin_h_hdr = xyes; then + AC_DEFINE(HAVE_LSXINTRIN_H, 1, [ ]) + fi + + AC_ARG_ENABLE(lasx, +[AC_HELP_STRING([--enable-lasx], [use LASX assembly routines [default=yes]])], + , enable_LASX=yes) + if test x$enable_LASX = xyes; then + save_CFLAGS="$CFLAGS" + have_gcc_lasx=no + AC_MSG_CHECKING(for GCC -mlasx option) + lasx_CFLAGS="-mlasx" + CFLAGS="$save_CFLAGS $lasx_CFLAGS" + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #ifndef __loongarch_asx + #error Assembler CPP flag not enabled + #endif + ]], [])], [have_gcc_lasx=yes], []) + AC_MSG_RESULT($have_gcc_lasx) + CFLAGS="$save_CFLAGS" + + if test x$have_gcc_lasx = xyes; then + EXTRA_CFLAGS="$EXTRA_CFLAGS $lasx_CFLAGS" + SUMMARY_math="${SUMMARY_math} lasx" + fi + fi + + AC_MSG_CHECKING(for lasxintrin.h) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]])], + [have_lasxintrin_h_hdr=yes],[have_lasxintrin_h_hdr=no]) + AC_MSG_RESULT($have_lasxintrin_h_hdr) + if test x$have_lasxintrin_h_hdr = xyes; then + AC_DEFINE(HAVE_LASXINTRIN_H, 1, [ ]) + fi + dnl See if the OSS audio interface is supported CheckOSS() { diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index cd322ce87..9a80d45b7 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -229,6 +229,8 @@ #undef HAVE_LIBUDEV_H #undef HAVE_LIBSAMPLERATE_H #undef HAVE_LIBDECOR_H +#undef HAVE_LSXINTRIN_H +#undef HAVE_LASXINTRIN_H #undef HAVE_DDRAW_H #undef HAVE_DINPUT_H diff --git a/include/SDL_cpuinfo.h b/include/SDL_cpuinfo.h index 55050da26..e1069ed6c 100644 --- a/include/SDL_cpuinfo.h +++ b/include/SDL_cpuinfo.h @@ -98,6 +98,14 @@ _m_prefetch(void *__P) #if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H) #include #endif +#if defined(__loongarch_sx) && !defined(SDL_DISABLE_LSX_H) +#include +#define __LSX__ +#endif +#if defined(__loongarch_asx) && !defined(SDL_DISABLE_LASX_H) +#include +#define __LASX__ +#endif #if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H) #include #else @@ -433,6 +441,28 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasARMSIMD(void); */ extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void); +/** + * Determine whether the CPU has LSX (LOONGARCH SIMD) features. + * + * This always returns false on CPUs that aren't using LOONGARCH instruction sets. + * + * \returns SDL_TRUE if the CPU has LOONGARCH LSX features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.23. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasLSX(void); + +/** + * Determine whether the CPU has LASX (LOONGARCH SIMD) features. + * + * This always returns false on CPUs that aren't using LOONGARCH instruction sets. + * + * \returns SDL_TRUE if the CPU has LOONGARCH LASX features or SDL_FALSE if not. + * + * \since This function is available since SDL 2.0.23. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasLASX(void); + /** * Get the amount of RAM configured in the system. * diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index aa994357a..9f2101cf2 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -112,6 +112,12 @@ #define CPU_HAS_NEON (1 << 11) #define CPU_HAS_AVX512F (1 << 12) #define CPU_HAS_ARM_SIMD (1 << 13) +#define CPU_HAS_LSX (1 << 14) +#define CPU_HAS_LASX (1 << 15) + +#define CPU_CFG2 0x2 +#define CPU_CFG2_LSX (1 << 6) +#define CPU_CFG2_LASX (1 << 7) #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ && !__OpenBSD__ && !__FreeBSD__ /* This is the brute force way of detecting instruction sets... @@ -508,6 +514,23 @@ CPU_haveNEON(void) #endif } +static int +CPU_readCPUCFG(void) +{ + uint32_t cfg2 = 0; +#if defined __loongarch__ + __asm__ volatile( + "cpucfg %0, %1 \n\t" + : "+&r"(cfg2) + : "r"(CPU_CFG2) + ); +#endif + return cfg2; +} + +#define CPU_haveLSX() (CPU_readCPUCFG() & CPU_CFG2_LSX) +#define CPU_haveLASX() (CPU_readCPUCFG() & CPU_CFG2_LASX) + #if defined(__e2k__) inline int CPU_have3DNow(void) @@ -885,6 +908,14 @@ SDL_GetCPUFeatures(void) SDL_CPUFeatures |= CPU_HAS_NEON; SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); } + if (CPU_haveLSX()) { + SDL_CPUFeatures |= CPU_HAS_LSX; + SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); + } + if (CPU_haveLASX()) { + SDL_CPUFeatures |= CPU_HAS_LASX; + SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 32); + } } return SDL_CPUFeatures; } @@ -974,6 +1005,18 @@ SDL_HasNEON(void) return CPU_FEATURE_AVAILABLE(CPU_HAS_NEON); } +SDL_bool +SDL_HasLSX(void) +{ + return CPU_FEATURE_AVAILABLE(CPU_HAS_LSX); +} + +SDL_bool +SDL_HasLASX(void) +{ + return CPU_FEATURE_AVAILABLE(CPU_HAS_LASX); +} + static int SDL_SystemRAM = 0; int @@ -1170,6 +1213,8 @@ main() printf("AVX-512F: %d\n", SDL_HasAVX512F()); printf("ARM SIMD: %d\n", SDL_HasARMSIMD()); printf("NEON: %d\n", SDL_HasNEON()); + printf("LSX: %d\n", SDL_HasLSX()); + printf("LASX: %d\n", SDL_HasLASX()); printf("RAM: %d MB\n", SDL_GetSystemRAM()); return 0; }