Loongson MMI: Merge with MIPS64/add auto-detection
Modern Loongson processors are MIPS64-compatible, and MMI instructions
are now supported in the mainline of GCC. Thus, this commit adds
compile-time and run-time auto-detection of MMI instructions and moves
the MMI SIMD extensions for libjpeg-turbo from simd/loongson/ to
simd/mips64/. That will allow MMI and MSA instructions to co-exist
in the same build once #377 has been integrated.
Based on:
https://github.com/FlyGoat/libjpeg-turbo/commit/82953ddd61549428f58066f7eff0d60ce7429865
Closes #383
diff --git a/simd/CMakeLists.txt b/simd/CMakeLists.txt
index 10ae7c9..d63457e 100755
--- a/simd/CMakeLists.txt
+++ b/simd/CMakeLists.txt
@@ -314,15 +314,35 @@
endif()
###############################################################################
-# Loongson (Intrinsics)
+# MIPS64 (Intrinsics)
###############################################################################
-elseif(CPU_TYPE STREQUAL "loongson")
+elseif(CPU_TYPE STREQUAL "loongson" OR CPU_TYPE MATCHES "mips64*")
-set(SIMD_SOURCES loongson/jccolor-mmi.c loongson/jcgray-mmi.c
- loongson/jcsample-mmi.c loongson/jdcolor-mmi.c loongson/jdsample-mmi.c
- loongson/jdmerge-mmi.c loongson/jfdctfst-mmi.c loongson/jfdctint-mmi.c
- loongson/jidctfst-mmi.c loongson/jidctint-mmi.c loongson/jquanti-mmi.c)
+set(CMAKE_REQUIRED_FLAGS -Wa,-mloongson-mmi,-mloongson-ext)
+
+check_c_source_compiles("
+ int main(void) {
+ int c = 0, a = 0, b = 0;
+ asm (
+ \"paddb %0, %1, %2\"
+ : \"=f\" (c)
+ : \"f\" (a), \"f\" (b)
+ );
+ return c;
+ }" HAVE_MMI)
+
+unset(CMAKE_REQUIRED_FLAGS)
+
+if(NOT HAVE_MMI)
+ simd_fail("SIMD extensions not available for this CPU")
+ return()
+endif()
+
+set(SIMD_SOURCES mips64/jccolor-mmi.c mips64/jcgray-mmi.c mips64/jcsample-mmi.c
+ mips64/jdcolor-mmi.c mips64/jdmerge-mmi.c mips64/jdsample-mmi.c
+ mips64/jfdctfst-mmi.c mips64/jfdctint-mmi.c mips64/jidctfst-mmi.c
+ mips64/jidctint-mmi.c mips64/jquanti-mmi.c)
if(CMAKE_COMPILER_IS_GNUCC)
foreach(file ${SIMD_SOURCES})
@@ -330,8 +350,12 @@
" -fno-strict-aliasing")
endforeach()
endif()
+foreach(file ${SIMD_SOURCES})
+ set_property(SOURCE ${file} APPEND_STRING PROPERTY COMPILE_FLAGS
+ " -Wa,-mloongson-mmi,-mloongson-ext")
+endforeach()
-add_library(simd OBJECT ${SIMD_SOURCES} loongson/jsimd.c)
+add_library(simd OBJECT ${SIMD_SOURCES} mips64/jsimd.c)
if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED)
set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1)
diff --git a/simd/loongson/jccolext-mmi.c b/simd/mips64/jccolext-mmi.c
similarity index 100%
rename from simd/loongson/jccolext-mmi.c
rename to simd/mips64/jccolext-mmi.c
diff --git a/simd/loongson/jccolor-mmi.c b/simd/mips64/jccolor-mmi.c
similarity index 100%
rename from simd/loongson/jccolor-mmi.c
rename to simd/mips64/jccolor-mmi.c
diff --git a/simd/loongson/jcgray-mmi.c b/simd/mips64/jcgray-mmi.c
similarity index 100%
rename from simd/loongson/jcgray-mmi.c
rename to simd/mips64/jcgray-mmi.c
diff --git a/simd/loongson/jcgryext-mmi.c b/simd/mips64/jcgryext-mmi.c
similarity index 100%
rename from simd/loongson/jcgryext-mmi.c
rename to simd/mips64/jcgryext-mmi.c
diff --git a/simd/loongson/jcsample-mmi.c b/simd/mips64/jcsample-mmi.c
similarity index 100%
rename from simd/loongson/jcsample-mmi.c
rename to simd/mips64/jcsample-mmi.c
diff --git a/simd/loongson/jcsample.h b/simd/mips64/jcsample.h
similarity index 100%
rename from simd/loongson/jcsample.h
rename to simd/mips64/jcsample.h
diff --git a/simd/loongson/jdcolext-mmi.c b/simd/mips64/jdcolext-mmi.c
similarity index 100%
rename from simd/loongson/jdcolext-mmi.c
rename to simd/mips64/jdcolext-mmi.c
diff --git a/simd/loongson/jdcolor-mmi.c b/simd/mips64/jdcolor-mmi.c
similarity index 100%
rename from simd/loongson/jdcolor-mmi.c
rename to simd/mips64/jdcolor-mmi.c
diff --git a/simd/loongson/jdmerge-mmi.c b/simd/mips64/jdmerge-mmi.c
similarity index 100%
rename from simd/loongson/jdmerge-mmi.c
rename to simd/mips64/jdmerge-mmi.c
diff --git a/simd/loongson/jdmrgext-mmi.c b/simd/mips64/jdmrgext-mmi.c
similarity index 100%
rename from simd/loongson/jdmrgext-mmi.c
rename to simd/mips64/jdmrgext-mmi.c
diff --git a/simd/loongson/jdsample-mmi.c b/simd/mips64/jdsample-mmi.c
similarity index 100%
rename from simd/loongson/jdsample-mmi.c
rename to simd/mips64/jdsample-mmi.c
diff --git a/simd/loongson/jfdctfst-mmi.c b/simd/mips64/jfdctfst-mmi.c
similarity index 100%
rename from simd/loongson/jfdctfst-mmi.c
rename to simd/mips64/jfdctfst-mmi.c
diff --git a/simd/loongson/jfdctint-mmi.c b/simd/mips64/jfdctint-mmi.c
similarity index 100%
rename from simd/loongson/jfdctint-mmi.c
rename to simd/mips64/jfdctint-mmi.c
diff --git a/simd/loongson/jidctfst-mmi.c b/simd/mips64/jidctfst-mmi.c
similarity index 100%
rename from simd/loongson/jidctfst-mmi.c
rename to simd/mips64/jidctfst-mmi.c
diff --git a/simd/loongson/jidctint-mmi.c b/simd/mips64/jidctint-mmi.c
similarity index 100%
rename from simd/loongson/jidctint-mmi.c
rename to simd/mips64/jidctint-mmi.c
diff --git a/simd/loongson/jquanti-mmi.c b/simd/mips64/jquanti-mmi.c
similarity index 100%
rename from simd/loongson/jquanti-mmi.c
rename to simd/mips64/jquanti-mmi.c
diff --git a/simd/loongson/jsimd.c b/simd/mips64/jsimd.c
similarity index 89%
rename from simd/loongson/jsimd.c
rename to simd/mips64/jsimd.c
index f7bc472..e8f1af5 100644
--- a/simd/loongson/jsimd.c
+++ b/simd/mips64/jsimd.c
@@ -1,5 +1,5 @@
/*
- * jsimd_loongson.c
+ * jsimd_mips64.c
*
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2009-2011, 2014, 2016, 2018, D. R. Commander.
@@ -13,7 +13,7 @@
*
* This file contains the interface between the "normal" portions
* of the library and the SIMD implementations when running on a
- * Loongson architecture.
+ * 64-bit MIPS architecture.
*/
#define JPEG_INTERNALS
@@ -24,8 +24,76 @@
#include "../../jsimddct.h"
#include "../jsimd.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
static unsigned int simd_support = ~0;
+#if defined(__linux__)
+
+#define SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT (1024 * 1024)
+
+LOCAL(int)
+check_feature(char *buffer, char *feature)
+{
+ char *p;
+
+ if (*feature == 0)
+ return 0;
+ if (strncmp(buffer, "ASEs implemented", 16) != 0)
+ return 0;
+ buffer += 16;
+ while (isspace(*buffer))
+ buffer++;
+
+ /* Check if 'feature' is present in the buffer as a separate word */
+ while ((p = strstr(buffer, feature))) {
+ if (p > buffer && !isspace(*(p - 1))) {
+ buffer++;
+ continue;
+ }
+ p += strlen(feature);
+ if (*p != 0 && !isspace(*p)) {
+ buffer++;
+ continue;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+LOCAL(int)
+parse_proc_cpuinfo(int bufsize)
+{
+ char *buffer = (char *)malloc(bufsize);
+ FILE *fd;
+
+ simd_support = 0;
+
+ if (!buffer)
+ return 0;
+
+ fd = fopen("/proc/cpuinfo", "r");
+ if (fd) {
+ while (fgets(buffer, bufsize, fd)) {
+ if (!strchr(buffer, '\n') && !feof(fd)) {
+ /* "impossible" happened - insufficient size of the buffer! */
+ fclose(fd);
+ free(buffer);
+ return 0;
+ }
+ if (check_feature(buffer, "loongson-mmi"))
+ simd_support |= JSIMD_MMI;
+ }
+ fclose(fd);
+ }
+ free(buffer);
+ return 1;
+}
+
+#endif
+
/*
* Check what SIMD accelerations are supported.
*
@@ -37,14 +105,32 @@
#ifndef NO_GETENV
char *env = NULL;
#endif
+#if defined(__linux__)
+ int bufsize = 1024; /* an initial guess for the line buffer size limit */
+#endif
if (simd_support != ~0U)
return;
+ simd_support = 0;
+
+#if defined(__linux__)
+ while (!parse_proc_cpuinfo(bufsize)) {
+ bufsize *= 2;
+ if (bufsize > SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT)
+ break;
+ }
+#elif defined(__mips_loongson_vector_rev)
+ /* Only enable MMI by default on non-Linux platforms when the compiler flags
+ * support it. */
simd_support |= JSIMD_MMI;
+#endif
#ifndef NO_GETENV
/* Force different settings through environment variables */
+ env = getenv("JSIMD_FORCEMMI");
+ if ((env != NULL) && (strcmp(env, "1") == 0))
+ simd_support = JSIMD_MMI;
env = getenv("JSIMD_FORCENONE");
if ((env != NULL) && (strcmp(env, "1") == 0))
simd_support = 0;
diff --git a/simd/loongson/jsimd_mmi.h b/simd/mips64/jsimd_mmi.h
similarity index 100%
rename from simd/loongson/jsimd_mmi.h
rename to simd/mips64/jsimd_mmi.h
diff --git a/simd/loongson/loongson-mmintrin.h b/simd/mips64/loongson-mmintrin.h
similarity index 100%
rename from simd/loongson/loongson-mmintrin.h
rename to simd/mips64/loongson-mmintrin.h