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:
82953ddd61

Closes #383
This commit is contained in:
DRC
2019-12-17 14:18:35 -06:00
parent 52fef34928
commit 81b8c0eed5
20 changed files with 119 additions and 9 deletions

View File

@@ -314,15 +314,35 @@ if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED)
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 @@ if(CMAKE_COMPILER_IS_GNUCC)
" -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)

View File

@@ -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 @@ init_simd(void)
#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;