[Pixman] [PATCH] build: Support building Loongson code for 2e, 2f, 3a

Matt Turner mattst88 at gmail.com
Sat Jan 26 18:54:10 PST 2013


Since binutils refuses to link objects that are compiled with different
-march flags, pixman-mmx.c is compiled with varying -march flags into
separate shared objects, which are dlopened at runtime.

AC_LINK_IFELSE is used to confirm that linking works, since for example
an object built with -march=loongson2e cannot be linked with libc.so
built with -march=loongson2f. I expect binary distributions' libcs to
be built with generic flags, and in such case all three loongson march
values can be built.

If libc is built with a particular -march=loongson* flag, the linking
test will fail and only the -march value matching the C library will be
built.

If only one -march value is built, avoid dlopen and simply build the
code into libpixman-1 like before.

Unfortunately, two internal pixman symbols are needed by pixman-mmx.c:
    _pixman_image_get_solid
    _pixman_implementation_create

They are annotated with PIXMAN_EXPORT, but only in the dlopen case.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51451
---
An alternative would be to move the code that creates the implementation
record from pixman-mmx.c to pixman-mips.c and use dlsym to get the
function pointers for the fast paths table. This seemed like a lot more
work for the benefit of not exposing two private symbols on a platform
almost no one cares about, and only on binary distributions at that.

 configure.ac                   | 135 +++++++++++++++++++++++++++++++++++------
 pixman/Makefile.am             |  60 ++++++++++++++++--
 pixman/pixman-image.c          |   3 +
 pixman/pixman-implementation.c |   3 +
 pixman/pixman-mips.c           |  60 +++++++++++++++++-
 pixman/pixman-mmx.c            |   3 +
 pixman/pixman-private.h        |   6 ++
 7 files changed, 244 insertions(+), 26 deletions(-)

diff --git a/configure.ac b/configure.ac
index 515e312..bf10344 100644
--- a/configure.ac
+++ b/configure.ac
@@ -270,21 +270,26 @@ PIXMAN_CHECK_CFLAG([-xldscope=hidden], [dnl
 dnl ===========================================================================
 dnl Check for Loongson Multimedia Instructions
 
-if test "x$LS_CFLAGS" = "x" ; then
-    LS_CFLAGS="-march=loongson2f"
+if test "x$LS2E_CFLAGS" = "x" ; then
+    LS2E_CFLAGS="-march=loongson2e"
+fi
+if test "x$LS2F_CFLAGS" = "x" ; then
+    LS2F_CFLAGS="-march=loongson2f"
+fi
+if test "x$LS3A_CFLAGS" = "x" ; then
+    LS3A_CFLAGS="-march=loongson3a"
 fi
 
-have_loongson_mmi=no
 AC_MSG_CHECKING(whether to use Loongson MMI assembler)
 
-xserver_save_CFLAGS=$CFLAGS
-CFLAGS=" $LS_CFLAGS $CFLAGS -I$srcdir"
-AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+save_CFLAGS=$CFLAGS
+CFLAGS=" $CFLAGS $LS2E_CFLAGS -I$srcdir"
+AC_LINK_IFELSE([AC_LANG_SOURCE([[
 #ifndef __mips_loongson_vector_rev
 #error "Loongson Multimedia Instructions are only available on Loongson"
 #endif
 #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
-#error "Need GCC >= 4.4 for Loongson MMI compilation"
+#error "Need GCC >= 4.4 for Loongson 2e/f MMI compilation"
 #endif
 #include "pixman/loongson-mmintrin.h"
 int main () {
@@ -295,30 +300,120 @@ int main () {
     int b = 4;
     __m64 c = _mm_srli_pi16 (a.v, b);
     return 0;
-}]])], have_loongson_mmi=yes)
-CFLAGS=$xserver_save_CFLAGS
+}]])], have_loongson2e_mmi=yes)
+CFLAGS=$save_CFLAGS
+
+save_CFLAGS=$CFLAGS
+CFLAGS=" $CFLAGS $LS2F_CFLAGS -I$srcdir"
+AC_LINK_IFELSE([AC_LANG_SOURCE([[
+#ifndef __mips_loongson_vector_rev
+#error "Loongson Multimedia Instructions are only available on Loongson"
+#endif
+#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
+#error "Need GCC >= 4.4 for Loongson 2e/f MMI compilation"
+#endif
+#include "pixman/loongson-mmintrin.h"
+int main () {
+    union {
+        __m64 v;
+        char c[8];
+    } a = { .c = {1, 2, 3, 4, 5, 6, 7, 8} };
+    int b = 4;
+    __m64 c = _mm_srli_pi16 (a.v, b);
+    return 0;
+}]])], have_loongson2f_mmi=yes)
+CFLAGS=$save_CFLAGS
+
+save_CFLAGS=$CFLAGS
+CFLAGS=" $CFLAGS $LS3A_CFLAGS -I$srcdir"
+AC_LINK_IFELSE([AC_LANG_SOURCE([[
+#ifndef __mips_loongson_vector_rev
+#error "Loongson Multimedia Instructions are only available on Loongson"
+#endif
+#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6))
+#error "Need GCC >= 4.6 for Loongson 3A MMI compilation"
+#endif
+#include "pixman/loongson-mmintrin.h"
+int main () {
+    union {
+        __m64 v;
+        char c[8];
+    } a = { .c = {1, 2, 3, 4, 5, 6, 7, 8} };
+    int b = 4;
+    __m64 c = _mm_srli_pi16 (a.v, b);
+    return 0;
+}]])], have_loongson3a_mmi=yes)
+CFLAGS=$save_CFLAGS
 
 AC_ARG_ENABLE(loongson-mmi,
    [AC_HELP_STRING([--disable-loongson-mmi],
                    [disable Loongson MMI fast paths])],
    [enable_loongson_mmi=$enableval], [enable_loongson_mmi=auto])
-
-if test $enable_loongson_mmi = no ; then
-   have_loongson_mmi=disabled
-fi
-
-if test $have_loongson_mmi = yes ; then
+AC_ARG_ENABLE(loongson2e-mmi,
+   [AC_HELP_STRING([--disable-loongson2e-mmi],
+                   [do not build Loongson MMI fast paths for 2e])],
+   [enable_loongson2e_mmi=$enableval], [enable_loongson2e_mmi=auto])
+AC_ARG_ENABLE(loongson2f-mmi,
+   [AC_HELP_STRING([--disable-loongson2f-mmi],
+                   [do not build Loongson MMI fast paths for 2f])],
+   [enable_loongson2f_mmi=$enableval], [enable_loongson2f_mmi=auto])
+AC_ARG_ENABLE(loongson3a-mmi,
+   [AC_HELP_STRING([--disable-loongson3a-mmi],
+                   [do not build Loongson MMI fast paths for 3a])],
+   [enable_loongson3a_mmi=$enableval], [enable_loongson3a_mmi=auto])
+
+test "x$enable_loongson2e_mmi" = xno && have_loongson2e_mmi=disabled
+test "x$enable_loongson2f_mmi" = xno && have_loongson2f_mmi=disabled
+test "x$enable_loongson3a_mmi" = xno && have_loongson3a_mmi=disabled
+
+if test "x$have_loongson2e_mmi" = xyes -o \
+        "x$have_loongson2f_mmi" = xyes -o \
+        "x$have_loongson3a_mmi" = xyes ; then
+   loongson_msg="yes:"
    AC_DEFINE(USE_LOONGSON_MMI, 1, [use Loongson Multimedia Instructions])
+   if test "x$have_loongson2e_mmi" = xyes ; then
+       loongson_msg="$loongson_msg 2e"
+       AC_DEFINE(HAVE_LOONGSON2E_MMI, 1, [use Loongson 2e Multimedia Instructions])
+   fi
+   if test "x$have_loongson2f_mmi" = xyes ; then
+       loongson_msg="$loongson_msg 2f"
+       AC_DEFINE(HAVE_LOONGSON2F_MMI, 1, [use Loongson 2f Multimedia Instructions])
+   fi
+   if test "x$have_loongson3a_mmi" = xyes ; then
+      loongson_msg="$loongson_msg 3a"
+      AC_DEFINE(HAVE_LOONGSON3A_MMI, 1, [use Loongson 3a Multimedia Instructions])
+   fi
 else
-   LS_CFLAGS=
+   loongson_msg="no"
 fi
 
-AC_MSG_RESULT($have_loongson_mmi)
-if test $enable_loongson_mmi = yes && test $have_loongson_mmi = no ; then
-   AC_MSG_ERROR([Loongson MMI not detected])
+AC_MSG_RESULT($loongson_msg)
+case "x$have_loongson2e_mmi$have_loongson2f_mmi$have_loongson3a_mmi" in
+   x*yes*yes*)
+      dnl If multiple Loongson architectures are selected, we have to
+      dnl dlopen() them instead of building them into pixman directly.
+      AC_SEARCH_LIBS([dlopen], [dl],
+         [have_dlopen_loongson_mmi=yes],
+         [AC_MSG_ERROR([unable to find the dlopen() function])]
+      )
+      ;;
+esac
+
+if test "x$have_dlopen_loongson_mmi" = xyes ; then
+   AC_DEFINE(DLOPEN_LOONGSON_MMI, 1, [use dlopen() to load Loongson MMI])
+   AC_SUBST(DLOPEN_LIBS, "-ldl")
 fi
 
-AM_CONDITIONAL(USE_LOONGSON_MMI, test $have_loongson_mmi = yes)
+AC_SUBST([LS2E_CFLAGS])
+AC_SUBST([LS2F_CFLAGS])
+AC_SUBST([LS3A_CFLAGS])
+AM_CONDITIONAL(DLOPEN_LOONGSON_MMI, test "x$have_dlopen_loongson_mmi" = xyes)
+AM_CONDITIONAL(USE_LOONGSON_MMI, test "x$have_loongson2e_mmi" = xyes -o \
+                                      "x$have_loongson2f_mmi" = xyes -o \
+				      "x$have_loongson3a_mmi" = xyes)
+AM_CONDITIONAL(HAVE_LOONGSON2E, test "x$have_loongson2e_mmi" = xyes)
+AM_CONDITIONAL(HAVE_LOONGSON2F, test "x$have_loongson2f_mmi" = xyes)
+AM_CONDITIONAL(HAVE_LOONGSON3A, test "x$have_loongson3a_mmi" = xyes)
 
 dnl ===========================================================================
 dnl Check for MMX
diff --git a/pixman/Makefile.am b/pixman/Makefile.am
index beebdd0..55ad460 100644
--- a/pixman/Makefile.am
+++ b/pixman/Makefile.am
@@ -114,11 +114,61 @@ endif
 
 # loongson code
 if USE_LOONGSON_MMI
-noinst_LTLIBRARIES += libpixman-loongson-mmi.la
-libpixman_loongson_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h
-libpixman_loongson_mmi_la_CFLAGS = $(LS_CFLAGS)
-libpixman_1_la_LDFLAGS += $(LS_LDFLAGS)
-libpixman_1_la_LIBADD += libpixman-loongson-mmi.la
+if DLOPEN_LOONGSON_MMI
+libpixman_1_la_LIBADD += $(DLOPEN_LIBS)
+endif
+
+if HAVE_LOONGSON2E
+if DLOPEN_LOONGSON_MMI
+lib_LTLIBRARIES += libpixman-1-loongson2e-mmi.la
+libpixman_1_loongson2e_mmi_la_LDFLAGS = -avoid-version -module
+libpixman_1_loongson2e_mmi_la_CPPFLAGS = -DUSE_LOONGSON2E_MMI
+else
+noinst_LTLIBRARIES += libpixman-1-loongson2e-mmi.la
+libpixman_1_loongson2e_mmi_la_LDFLAGS = -avoid-version
+libpixman_1_la_LIBADD += libpixman-1-loongson2e-mmi.la
+endif
+libpixman_1_loongson2e_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h
+
+LS2E_LO = libpixman_1_loongson2e_mmi_la-pixman-mmx.lo
+$(LS2E_LO): pixman-mmx.c loongson-mmintrin.h
+	@$(MAKE) libpixman_1_loongson2e_mmi_la-pixman-mmx.lo CFLAGS="$(CFLAGS) $(LS2E_CFLAGS)" LS2E_LO=dummy-libpixman_1_loongson2e_mmi_la-pixman-mmx.lo
+endif
+
+if HAVE_LOONGSON2F
+if DLOPEN_LOONGSON_MMI
+lib_LTLIBRARIES += libpixman-1-loongson2f-mmi.la
+libpixman_1_loongson2f_mmi_la_LDFLAGS = -avoid-version -module
+libpixman_1_loongson2f_mmi_la_CPPFLAGS = -DUSE_LOONGSON2F_MMI
+else
+noinst_LTLIBRARIES += libpixman-1-loongson2f-mmi.la
+libpixman_1_loongson2f_mmi_la_LDFLAGS = -avoid-version
+libpixman_1_la_LIBADD += libpixman-1-loongson2f-mmi.la
+endif
+libpixman_1_loongson2f_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h
+
+LS2F_LO = libpixman_1_loongson2f_mmi_la-pixman-mmx.lo
+$(LS2F_LO): pixman-mmx.c loongson-mmintrin.h
+	@$(MAKE) libpixman_1_loongson2f_mmi_la-pixman-mmx.lo CFLAGS="$(CFLAGS) $(LS2F_CFLAGS)" LS2F_LO=dummy-libpixman_1_loongson2f_mmi_la-pixman-mmx.lo
+endif
+
+if HAVE_LOONGSON3A
+if DLOPEN_LOONGSON_MMI
+lib_LTLIBRARIES += libpixman-1-loongson3a-mmi.la
+libpixman_1_loongson3a_mmi_la_LDFLAGS = -avoid-version -module
+libpixman_1_loongson3a_mmi_la_CPPFLAGS = -DUSE_LOONGSON3A_MMI
+else
+noinst_LTLIBRARIES += libpixman-1-loongson3a-mmi.la
+libpixman_1_loongson3a_mmi_la_LDFLAGS = -avoid-version
+libpixman_1_la_LIBADD += libpixman-1-loongson3a-mmi.la
+endif
+libpixman_1_loongson3a_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h
+
+LS3A_LO = libpixman_1_loongson3a_mmi_la-pixman-mmx.lo
+$(LS3A_LO): pixman-mmx.c loongson-mmintrin.h
+	@$(MAKE) libpixman_1_loongson3a_mmi_la-pixman-mmx.lo CFLAGS="$(CFLAGS) $(LS3A_CFLAGS)" LS3A_LO=dummy-libpixman_1_loongson3a_mmi_la-pixman-mmx.lo
+endif
+
 endif
 
 .c.s : $(libpixmaninclude_HEADERS)
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 65041b4..3db070d 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -891,6 +891,9 @@ pixman_image_get_format (pixman_image_t *image)
     return PIXMAN_null;
 }
 
+#ifdef DLOPEN_LOONGSON_MMI
+PIXMAN_EXPORT
+#endif
 uint32_t
 _pixman_image_get_solid (pixman_implementation_t *imp,
 			 pixman_image_t *         image,
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index ec467a6..171488b 100644
--- a/pixman/pixman-implementation.c
+++ b/pixman/pixman-implementation.c
@@ -27,6 +27,9 @@
 #include <stdlib.h>
 #include "pixman-private.h"
 
+#ifdef DLOPEN_LOONGSON_MMI
+PIXMAN_EXPORT
+#endif
 pixman_implementation_t *
 _pixman_implementation_create (pixman_implementation_t *fallback,
 			       const pixman_fast_path_t *fast_paths)
diff --git a/pixman/pixman-mips.c b/pixman/pixman-mips.c
index 3048813..77bef5c 100644
--- a/pixman/pixman-mips.c
+++ b/pixman/pixman-mips.c
@@ -27,6 +27,10 @@
 
 #if defined(USE_MIPS_DSPR2) || defined(USE_LOONGSON_MMI)
 
+#ifdef DLOPEN_LOONGSON_MMI
+#include <dlfcn.h>
+#endif
+
 #include <string.h>
 #include <stdlib.h>
 
@@ -69,10 +73,64 @@ pixman_implementation_t *
 _pixman_mips_get_implementations (pixman_implementation_t *imp)
 {
 #ifdef USE_LOONGSON_MMI
+    void *mmi_handle = NULL;
+#ifdef DLOPEN_LOONGSON_MMI
+    pixman_implementation_t *(*_pixman_implementation_create_mmx) (pixman_implementation_t *);
+#endif
     /* I really don't know if some Loongson CPUs don't have MMI. */
-    if (!_pixman_disabled ("loongson-mmi") && have_feature ("Loongson"))
+#ifdef HAVE_LOONGSON2E_MMI
+    if (!mmi_handle && !_pixman_disabled ("loongson-mmi")
+	&& have_feature ("Loongson") && have_feature ("-2e"))
+    {
+#ifdef DLOPEN_LOONGSON_MMI
+	mmi_handle = dlopen("libpixman-1-loongson2e-mmi.so", RTLD_LAZY | RTLD_LOCAL);
+#else
+	imp = _pixman_implementation_create_mmx (imp);
+#endif
+    }
+#endif
+#ifdef HAVE_LOONGSON2F_MMI
+    if (!mmi_handle && !_pixman_disabled ("loongson-mmi")
+	&& have_feature ("Loongson") && have_feature ("-2f"))
+    {
+#ifdef DLOPEN_LOONGSON_MMI
+	mmi_handle = dlopen("libpixman-1-loongson2f-mmi.so", RTLD_LAZY | RTLD_LOCAL);
+#else
+	imp = _pixman_implementation_create_mmx (imp);
+#endif
+    }
+#endif
+#ifdef HAVE_LOONGSON3A_MMI
+    if (!mmi_handle && !_pixman_disabled ("loongson-mmi")
+	&& have_feature ("Loongson-3A"))
+    {
+#ifdef DLOPEN_LOONGSON_MMI
+	mmi_handle = dlopen("libpixman-1-loongson3a-mmi.so", RTLD_LAZY | RTLD_LOCAL);
+#else
 	imp = _pixman_implementation_create_mmx (imp);
 #endif
+    }
+#endif
+
+#ifdef DLOPEN_LOONGSON_MMI
+    if (mmi_handle)
+    {
+	_pixman_implementation_create_mmx = dlsym(mmi_handle, "_pixman_implementation_create_mmx");
+	if (_pixman_implementation_create_mmx)
+	{
+	    imp = _pixman_implementation_create_mmx (imp);
+	}
+	else
+	{
+	    puts(dlerror());
+	}
+    }
+    else
+    {
+	puts(dlerror());
+    }
+#endif
+#endif
 
 #ifdef USE_MIPS_DSPR2
     if (!_pixman_disabled ("mips-dspr2"))
diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c
index ca2ac83..280e9c4 100644
--- a/pixman/pixman-mmx.c
+++ b/pixman/pixman-mmx.c
@@ -4044,6 +4044,9 @@ static const pixman_fast_path_t mmx_fast_paths[] =
     { PIXMAN_OP_NONE },
 };
 
+#ifdef DLOPEN_LOONGSON_MMI
+PIXMAN_EXPORT
+#endif
 pixman_implementation_t *
 _pixman_implementation_create_mmx (pixman_implementation_t *fallback)
 {
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index e5ab873..af8e8d1 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -488,11 +488,17 @@ struct pixman_implementation_t
     pixman_combine_float_func_t	combine_float_ca[PIXMAN_N_OPERATORS];
 };
 
+#ifdef DLOPEN_LOONGSON_MMI
+PIXMAN_EXPORT
+#endif
 uint32_t
 _pixman_image_get_solid (pixman_implementation_t *imp,
 			 pixman_image_t *         image,
                          pixman_format_code_t     format);
 
+#ifdef DLOPEN_LOONGSON_MMI
+PIXMAN_EXPORT
+#endif
 pixman_implementation_t *
 _pixman_implementation_create (pixman_implementation_t *fallback,
 			       const pixman_fast_path_t *fast_paths);
-- 
1.8.1.1



More information about the Pixman mailing list