From 17f63e53f83e6cef3490d5edc8a24d5b22bbabe1 Mon Sep 17 00:00:00 2001
From: yuanhecai <[EMAIL REDACTED]>
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 7032f7c718a..121593e1681 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 8bba0af0c4c..421ea98ce91 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 <lsxintrin.h>]])],
+ [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 <lasxintrin.h>]])],
+ [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 cd322ce879e..9a80d45b7c0 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 55050da26dc..e1069ed6c63 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 <mm3dnow.h>
#endif
+#if defined(__loongarch_sx) && !defined(SDL_DISABLE_LSX_H)
+#include <lsxintrin.h>
+#define __LSX__
+#endif
+#if defined(__loongarch_asx) && !defined(SDL_DISABLE_LASX_H)
+#include <lasxintrin.h>
+#define __LASX__
+#endif
#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H)
#include <immintrin.h>
#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 aa994357aa4..9f2101cf21a 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;
}