51f0aa
From 418f5be91f4c843d63db0d29eee65ff46eb59202 Mon Sep 17 00:00:00 2001
51f0aa
From: Stefan Liebler <stli@linux.vnet.ibm.com>
51f0aa
Date: Thu, 27 Jul 2017 10:53:58 +0200
51f0aa
Subject: [PATCH 03/10] S390: Move utf8-utf16-z9.c to multiarch folder and use
51f0aa
 s390_libc_ifunc_expr macro.
51f0aa
51f0aa
upstream-commit df6cc7ee3b2e032c6c62cedd30b1c0fefbb43018
51f0aa
51f0aa
The utf8-utf16-z9.c iconv module is using ifunc and thus the ifunc part should
51f0aa
be in multiarch folder.  Otherwise ifunc is used even if you configure
51f0aa
with --disable-multi-arch.
51f0aa
51f0aa
This patch moves the ifunc resolvers to the new file
51f0aa
sysdeps/s390/multiarch/utf8-utf16-z9.c. The resolvers are now implemented
51f0aa
with s390_libc_ifunc_expr macro instead of using gcc attribute ifunc directly.
51f0aa
51f0aa
The ifunc versions are implemented in sysdeps/s390/utf8-utf16-z9.c.
51f0aa
Each version is only implemented if needed or supported.  Therefore there is
51f0aa
a block at beginning of the file which selects the versions which should be
51f0aa
defined depending on support for multiarch, vector-support and used minimum
51f0aa
architecture level.  This block defines HAVE_[FROM|TO]_[C|CU|VX] to 1 or 0.
51f0aa
The code below is rearranged and surrounded
51f0aa
by #if HAVE_[FROM|TO]_[C|CU|VX] == 1.  There is no functional change.
51f0aa
51f0aa
The cu instructions are z9 zarch instructions.  As the major distros are
51f0aa
already using the newer z196 as architecture level set, those instructions
51f0aa
can be used as fallback version instead of the c-code.  This behaviour is
51f0aa
decided at compile time via HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT.
51f0aa
51f0aa
ChangeLog:
51f0aa
51f0aa
	* sysdeps/s390/multiarch/utf8-utf16-z9.c: New File.
51f0aa
	* sysdeps/s390/utf8-utf16-z9.c: Move ifunc resolvers to multiarch
51f0aa
	folder and define ifunc versions depending on HAVE_[FROM|TO]_[C|CU|VX].
51f0aa
	(HAVE_FROM_C, HAVE_FROM_CU, HAVE_FROM_VX, HAVE_TO_C, HAVE_TO_VX,
51f0aa
	FROM_LOOP_DEFAULT, FROM_LOOP_C, FROM_LOOP_CU, FROM_LOOP_VX,
51f0aa
---
51f0aa
 sysdeps/s390/multiarch/utf8-utf16-z9.c |  48 ++++++++
51f0aa
 sysdeps/s390/utf8-utf16-z9.c           | 197 +++++++++++++++++----------------
51f0aa
 2 files changed, 150 insertions(+), 95 deletions(-)
51f0aa
 create mode 100644 sysdeps/s390/multiarch/utf8-utf16-z9.c
51f0aa
51f0aa
diff --git a/sysdeps/s390/multiarch/utf8-utf16-z9.c b/sysdeps/s390/multiarch/utf8-utf16-z9.c
51f0aa
new file mode 100644
51f0aa
index 0000000..b55ef1a
51f0aa
--- /dev/null
51f0aa
+++ b/sysdeps/s390/multiarch/utf8-utf16-z9.c
51f0aa
@@ -0,0 +1,48 @@
51f0aa
+/* Conversion between UTF-8 and UTF-16 - multiarch s390 version.
51f0aa
+
51f0aa
+   Copyright (C) 2017 Free Software Foundation, Inc.
51f0aa
+   This file is part of the GNU C Library.
51f0aa
+
51f0aa
+   The GNU C Library is free software; you can redistribute it and/or
51f0aa
+   modify it under the terms of the GNU Lesser General Public
51f0aa
+   License as published by the Free Software Foundation; either
51f0aa
+   version 2.1 of the License, or (at your option) any later version.
51f0aa
+
51f0aa
+   The GNU C Library is distributed in the hope that it will be useful,
51f0aa
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
51f0aa
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
51f0aa
+   Lesser General Public License for more details.
51f0aa
+
51f0aa
+   You should have received a copy of the GNU Lesser General Public
51f0aa
+   License along with the GNU C Library; if not, see
51f0aa
+   <http://www.gnu.org/licenses/>.  */
51f0aa
+
51f0aa
+#include <sysdeps/s390/utf8-utf16-z9.c>
51f0aa
+#include <ifunc-resolve.h>
51f0aa
+
51f0aa
+#undef FROM_LOOP
51f0aa
+#define FROM_LOOP	__from_utf8_loop
51f0aa
+#undef TO_LOOP
51f0aa
+#define TO_LOOP		__to_utf8_loop
51f0aa
+
51f0aa
+#define _SINGLE_NAME(NAME) NAME##_single
51f0aa
+#define SINGLE_NAME(NAME) _SINGLE_NAME(NAME)
51f0aa
+strong_alias (SINGLE_NAME (FROM_LOOP_DEFAULT), SINGLE_NAME (FROM_LOOP))
51f0aa
+strong_alias (SINGLE_NAME (TO_LOOP_DEFAULT), SINGLE_NAME (TO_LOOP))
51f0aa
+
51f0aa
+/* Generate ifunc'ed loop functions for FROM/TO_LOOP.  */
51f0aa
+s390_libc_ifunc_expr (FROM_LOOP_DEFAULT, FROM_LOOP,
51f0aa
+		      (HAVE_FROM_VX && (hwcap & HWCAP_S390_VX))
51f0aa
+		      ? FROM_LOOP_VX
51f0aa
+		      : (HAVE_FROM_CU && (hwcap & HWCAP_S390_ZARCH
51f0aa
+					  && hwcap & HWCAP_S390_HIGH_GPRS
51f0aa
+					  && hwcap & HWCAP_S390_ETF3EH))
51f0aa
+			? FROM_LOOP_CU
51f0aa
+			: FROM_LOOP_DEFAULT);
51f0aa
+
51f0aa
+s390_libc_ifunc_expr (TO_LOOP_DEFAULT, TO_LOOP,
51f0aa
+		      (HAVE_TO_VX && (hwcap & HWCAP_S390_VX))
51f0aa
+		      ? TO_LOOP_VX
51f0aa
+		      : TO_LOOP_DEFAULT);
51f0aa
+
51f0aa
+#include <iconv/skeleton.c>
51f0aa
diff --git a/sysdeps/s390/utf8-utf16-z9.c b/sysdeps/s390/utf8-utf16-z9.c
51f0aa
index d3dc9bd..d870a29 100644
51f0aa
--- a/sysdeps/s390/utf8-utf16-z9.c
51f0aa
+++ b/sysdeps/s390/utf8-utf16-z9.c
51f0aa
@@ -1,4 +1,4 @@
51f0aa
-/* Conversion between UTF-16 and UTF-32 BE/internal.
51f0aa
+/* Conversion between UTF-8 and UTF-16 - s390 version.
51f0aa
 
51f0aa
    This module uses the Z9-109 variants of the Convert Unicode
51f0aa
    instructions.
51f0aa
@@ -27,8 +27,35 @@
51f0aa
 #include <dlfcn.h>
51f0aa
 #include <stdint.h>
51f0aa
 #include <unistd.h>
51f0aa
-#include <dl-procinfo.h>
51f0aa
 #include <gconv.h>
51f0aa
+#include <string.h>
51f0aa
+
51f0aa
+/* Select which versions should be defined depending on support
51f0aa
+   for multiarch, vector and used minimum architecture level.  */
51f0aa
+#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT
51f0aa
+# define HAVE_FROM_C		0
51f0aa
+# define FROM_LOOP_DEFAULT	FROM_LOOP_CU
51f0aa
+#else
51f0aa
+# define HAVE_FROM_C		1
51f0aa
+# define FROM_LOOP_DEFAULT	FROM_LOOP_C
51f0aa
+#endif
51f0aa
+
51f0aa
+#define HAVE_TO_C		1
51f0aa
+#define TO_LOOP_DEFAULT		TO_LOOP_C
51f0aa
+
51f0aa
+#if defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT || defined USE_MULTIARCH
51f0aa
+# define HAVE_FROM_CU		1
51f0aa
+#else
51f0aa
+# define HAVE_FROM_CU		0
51f0aa
+#endif
51f0aa
+
51f0aa
+#if defined HAVE_S390_VX_ASM_SUPPORT && defined USE_MULTIARCH
51f0aa
+# define HAVE_FROM_VX		1
51f0aa
+# define HAVE_TO_VX		1
51f0aa
+#else
51f0aa
+# define HAVE_FROM_VX		0
51f0aa
+# define HAVE_TO_VX		0
51f0aa
+#endif
51f0aa
 
51f0aa
 #if defined HAVE_S390_VX_GCC_SUPPORT
51f0aa
 # define ASM_CLOBBER_VR(NR) , NR
51f0aa
@@ -49,8 +76,8 @@
51f0aa
 #define MAX_NEEDED_FROM		4
51f0aa
 #define MIN_NEEDED_TO		2
51f0aa
 #define MAX_NEEDED_TO		4
51f0aa
-#define FROM_LOOP		__from_utf8_loop
51f0aa
-#define TO_LOOP			__to_utf8_loop
51f0aa
+#define FROM_LOOP		FROM_LOOP_DEFAULT
51f0aa
+#define TO_LOOP			TO_LOOP_DEFAULT
51f0aa
 #define FROM_DIRECTION		(dir == from_utf8)
51f0aa
 #define ONE_DIRECTION           0
51f0aa
 
51f0aa
@@ -214,9 +241,8 @@ gconv_end (struct __gconv_step *data)
51f0aa
     STANDARD_FROM_LOOP_ERR_HANDLER (i);					\
51f0aa
   }
51f0aa
 
51f0aa
-#define BODY_FROM_ETF3EH BODY_FROM_HW (HARDWARE_CONVERT ("cu12 %0, %1, 1"))
51f0aa
-
51f0aa
-#define HW_FROM_VX							\
51f0aa
+#if HAVE_FROM_VX == 1
51f0aa
+# define HW_FROM_VX							\
51f0aa
   {									\
51f0aa
     register const unsigned char* pInput asm ("8") = inptr;		\
51f0aa
     register size_t inlen asm ("9") = inend - inptr;			\
51f0aa
@@ -291,11 +317,42 @@ gconv_end (struct __gconv_step *data)
51f0aa
     inptr = pInput;							\
51f0aa
     outptr = pOutput;							\
51f0aa
   }
51f0aa
-#define BODY_FROM_VX BODY_FROM_HW (HW_FROM_VX)
51f0aa
+# define BODY_FROM_VX BODY_FROM_HW (HW_FROM_VX)
51f0aa
 
51f0aa
+/* Generate loop-function with hardware vector and utf-convert instructions.  */
51f0aa
+# define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
51f0aa
+# define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
51f0aa
+# define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
51f0aa
+# define MAX_NEEDED_OUTPUT	MAX_NEEDED_TO
51f0aa
+# define FROM_LOOP_VX		__from_utf8_loop_vx
51f0aa
+# define LOOPFCT		FROM_LOOP_VX
51f0aa
+# define LOOP_NEED_FLAGS
51f0aa
+# define BODY			BODY_FROM_VX
51f0aa
+# include <iconv/loop.c>
51f0aa
+#else
51f0aa
+# define FROM_LOOP_VX		NULL
51f0aa
+#endif /* HAVE_FROM_VX != 1  */
51f0aa
+
51f0aa
+#if HAVE_FROM_CU == 1
51f0aa
+# define BODY_FROM_ETF3EH BODY_FROM_HW (HARDWARE_CONVERT ("cu12 %0, %1, 1"))
51f0aa
 
51f0aa
+/* Generate loop-function with hardware utf-convert instruction.  */
51f0aa
+# define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
51f0aa
+# define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
51f0aa
+# define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
51f0aa
+# define MAX_NEEDED_OUTPUT	MAX_NEEDED_TO
51f0aa
+# define FROM_LOOP_CU		__from_utf8_loop_etf3eh
51f0aa
+# define LOOPFCT		FROM_LOOP_CU
51f0aa
+# define LOOP_NEED_FLAGS
51f0aa
+# define BODY			BODY_FROM_ETF3EH
51f0aa
+# include <iconv/loop.c>
51f0aa
+#else
51f0aa
+# define FROM_LOOP_CU		NULL
51f0aa
+#endif /* HAVE_FROM_CU != 1  */
51f0aa
+
51f0aa
+#if HAVE_FROM_C == 1
51f0aa
 /* The software implementation is based on the code in gconv_simple.c.  */
51f0aa
-#define BODY_FROM_C							\
51f0aa
+# define BODY_FROM_C							\
51f0aa
   {									\
51f0aa
     /* Next input byte.  */						\
51f0aa
     uint16_t ch = *inptr;						\
51f0aa
@@ -443,66 +500,26 @@ gconv_end (struct __gconv_step *data)
51f0aa
   }
51f0aa
 
51f0aa
 /* Generate loop-function with software implementation.  */
51f0aa
-#define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
51f0aa
-#define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
51f0aa
-#define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
51f0aa
-#define MAX_NEEDED_OUTPUT	MAX_NEEDED_TO
51f0aa
-#define LOOPFCT			__from_utf8_loop_c
51f0aa
-#define LOOP_NEED_FLAGS
51f0aa
-#define BODY			BODY_FROM_C
51f0aa
-#include <iconv/loop.c>
51f0aa
-
51f0aa
-/* Generate loop-function with hardware utf-convert instruction.  */
51f0aa
-#define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
51f0aa
-#define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
51f0aa
-#define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
51f0aa
-#define MAX_NEEDED_OUTPUT	MAX_NEEDED_TO
51f0aa
-#define LOOPFCT			__from_utf8_loop_etf3eh
51f0aa
-#define LOOP_NEED_FLAGS
51f0aa
-#define BODY			BODY_FROM_ETF3EH
51f0aa
-#include <iconv/loop.c>
51f0aa
-
51f0aa
-#if defined HAVE_S390_VX_ASM_SUPPORT
51f0aa
-/* Generate loop-function with hardware vector and utf-convert instructions.  */
51f0aa
 # define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
51f0aa
 # define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
51f0aa
 # define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
51f0aa
 # define MAX_NEEDED_OUTPUT	MAX_NEEDED_TO
51f0aa
-# define LOOPFCT		__from_utf8_loop_vx
51f0aa
+# define FROM_LOOP_C		__from_utf8_loop_c
51f0aa
+# define LOOPFCT		FROM_LOOP_C
51f0aa
 # define LOOP_NEED_FLAGS
51f0aa
-# define BODY			BODY_FROM_VX
51f0aa
+# define BODY			BODY_FROM_C
51f0aa
 # include <iconv/loop.c>
51f0aa
-#endif
51f0aa
-
51f0aa
-
51f0aa
-/* Generate ifunc'ed loop function.  */
51f0aa
-__typeof(__from_utf8_loop_c)
51f0aa
-__attribute__ ((ifunc ("__from_utf8_loop_resolver")))
51f0aa
-__from_utf8_loop;
51f0aa
-
51f0aa
-static void *
51f0aa
-__from_utf8_loop_resolver (unsigned long int dl_hwcap)
51f0aa
-{
51f0aa
-#if defined HAVE_S390_VX_ASM_SUPPORT
51f0aa
-  if (dl_hwcap & HWCAP_S390_VX)
51f0aa
-    return __from_utf8_loop_vx;
51f0aa
-  else
51f0aa
-#endif
51f0aa
-  if (dl_hwcap & HWCAP_S390_ZARCH && dl_hwcap & HWCAP_S390_HIGH_GPRS
51f0aa
-      && dl_hwcap & HWCAP_S390_ETF3EH)
51f0aa
-    return __from_utf8_loop_etf3eh;
51f0aa
-  else
51f0aa
-    return __from_utf8_loop_c;
51f0aa
-}
51f0aa
-
51f0aa
-strong_alias (__from_utf8_loop_c_single, __from_utf8_loop_single)
51f0aa
+#else
51f0aa
+# define FROM_LOOP_C		NULL
51f0aa
+#endif /* HAVE_FROM_C != 1  */
51f0aa
 
51f0aa
 /* Conversion from UTF-16 to UTF-8.  */
51f0aa
 
51f0aa
+#if HAVE_TO_C == 1
51f0aa
 /* The software routine is based on the functionality of the S/390
51f0aa
    hardware instruction (cu21) as described in the Principles of
51f0aa
    Operation.  */
51f0aa
-#define BODY_TO_C							\
51f0aa
+# define BODY_TO_C							\
51f0aa
   {									\
51f0aa
     uint16_t c = get16 (inptr);						\
51f0aa
 									\
51f0aa
@@ -601,7 +618,22 @@ strong_alias (__from_utf8_loop_c_single, __from_utf8_loop_single)
51f0aa
     inptr += 2;								\
51f0aa
   }
51f0aa
 
51f0aa
-#define BODY_TO_VX							\
51f0aa
+/* Generate loop-function with software implementation.  */
51f0aa
+# define MIN_NEEDED_INPUT	MIN_NEEDED_TO
51f0aa
+# define MAX_NEEDED_INPUT	MAX_NEEDED_TO
51f0aa
+# define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
51f0aa
+# define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
51f0aa
+# define TO_LOOP_C		__to_utf8_loop_c
51f0aa
+# define LOOPFCT		TO_LOOP_C
51f0aa
+# define BODY                   BODY_TO_C
51f0aa
+# define LOOP_NEED_FLAGS
51f0aa
+# include <iconv/loop.c>
51f0aa
+#else
51f0aa
+# define TO_LOOP_C		NULL
51f0aa
+#endif /* HAVE_TO_C != 1  */
51f0aa
+
51f0aa
+#if HAVE_TO_VX == 1
51f0aa
+# define BODY_TO_VX							\
51f0aa
   {									\
51f0aa
     size_t inlen  = inend - inptr;					\
51f0aa
     size_t outlen  = outend - outptr;					\
51f0aa
@@ -771,48 +803,23 @@ strong_alias (__from_utf8_loop_c_single, __from_utf8_loop_single)
51f0aa
     STANDARD_TO_LOOP_ERR_HANDLER (2);					\
51f0aa
   }
51f0aa
 
51f0aa
-/* Generate loop-function with software implementation.  */
51f0aa
-#define MIN_NEEDED_INPUT	MIN_NEEDED_TO
51f0aa
-#define MAX_NEEDED_INPUT	MAX_NEEDED_TO
51f0aa
-#define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
51f0aa
-#define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
51f0aa
-#if defined HAVE_S390_VX_ASM_SUPPORT
51f0aa
-# define LOOPFCT		__to_utf8_loop_c
51f0aa
-# define BODY                   BODY_TO_C
51f0aa
-# define LOOP_NEED_FLAGS
51f0aa
-# include <iconv/loop.c>
51f0aa
-
51f0aa
-/* Generate loop-function with software implementation.  */
51f0aa
+/* Generate loop-function with vector implementation.  */
51f0aa
 # define MIN_NEEDED_INPUT	MIN_NEEDED_TO
51f0aa
 # define MAX_NEEDED_INPUT	MAX_NEEDED_TO
51f0aa
 # define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
51f0aa
 # define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
51f0aa
-# define LOOPFCT		__to_utf8_loop_vx
51f0aa
+# define TO_LOOP_VX		__to_utf8_loop_vx
51f0aa
+# define LOOPFCT		TO_LOOP_VX
51f0aa
 # define BODY                   BODY_TO_VX
51f0aa
 # define LOOP_NEED_FLAGS
51f0aa
 # include <iconv/loop.c>
51f0aa
-
51f0aa
-/* Generate ifunc'ed loop function.  */
51f0aa
-__typeof(__to_utf8_loop_c)
51f0aa
-__attribute__ ((ifunc ("__to_utf8_loop_resolver")))
51f0aa
-__to_utf8_loop;
51f0aa
-
51f0aa
-static void *
51f0aa
-__to_utf8_loop_resolver (unsigned long int dl_hwcap)
51f0aa
-{
51f0aa
-  if (dl_hwcap & HWCAP_S390_VX)
51f0aa
-    return __to_utf8_loop_vx;
51f0aa
-  else
51f0aa
-    return __to_utf8_loop_c;
51f0aa
-}
51f0aa
-
51f0aa
-strong_alias (__to_utf8_loop_c_single, __to_utf8_loop_single)
51f0aa
-
51f0aa
 #else
51f0aa
-# define LOOPFCT		TO_LOOP
51f0aa
-# define BODY                   BODY_TO_C
51f0aa
-# define LOOP_NEED_FLAGS
51f0aa
-# include <iconv/loop.c>
51f0aa
-#endif /* !HAVE_S390_VX_ASM_SUPPORT  */
51f0aa
-
51f0aa
-#include <iconv/skeleton.c>
51f0aa
+# define TO_LOOP_VX		NULL
51f0aa
+#endif /* HAVE_TO_VX != 1  */
51f0aa
+
51f0aa
+/* This file also exists in sysdeps/s390/multiarch/ which
51f0aa
+   generates ifunc resolvers for FROM/TO_LOOP functions
51f0aa
+   and includes iconv/skeleton.c afterwards.  */
51f0aa
+#if ! defined USE_MULTIARCH
51f0aa
+# include <iconv/skeleton.c>
51f0aa
+#endif
51f0aa
-- 
51f0aa
1.8.3.1
51f0aa