diff options
Diffstat (limited to 'sysdeps/s390/utf8-utf32-z9.c')
-rw-r--r-- | sysdeps/s390/utf8-utf32-z9.c | 215 |
1 files changed, 112 insertions, 103 deletions
diff --git a/sysdeps/s390/utf8-utf32-z9.c b/sysdeps/s390/utf8-utf32-z9.c index 6d8be42..57572fa 100644 --- a/sysdeps/s390/utf8-utf32-z9.c +++ b/sysdeps/s390/utf8-utf32-z9.c @@ -27,8 +27,35 @@ #include <dlfcn.h> #include <stdint.h> #include <unistd.h> -#include <dl-procinfo.h> #include <gconv.h> +#include <string.h> + +/* Select which versions should be defined depending on support + for multiarch, vector and used minimum architecture level. */ +#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT +# define HAVE_FROM_C 0 +# define FROM_LOOP_DEFAULT FROM_LOOP_CU +#else +# define HAVE_FROM_C 1 +# define FROM_LOOP_DEFAULT FROM_LOOP_C +#endif + +#define HAVE_TO_C 1 +#define TO_LOOP_DEFAULT TO_LOOP_C + +#if defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT || defined USE_MULTIARCH +# define HAVE_FROM_CU 1 +#else +# define HAVE_FROM_CU 0 +#endif + +#if defined HAVE_S390_VX_ASM_SUPPORT && defined USE_MULTIARCH +# define HAVE_FROM_VX 1 +# define HAVE_TO_VX 1 +#else +# define HAVE_FROM_VX 0 +# define HAVE_TO_VX 0 +#endif #if defined HAVE_S390_VX_GCC_SUPPORT # define ASM_CLOBBER_VR(NR) , NR @@ -48,8 +75,8 @@ #define MIN_NEEDED_FROM 1 #define MAX_NEEDED_FROM 6 #define MIN_NEEDED_TO 4 -#define FROM_LOOP __from_utf8_loop -#define TO_LOOP __to_utf8_loop +#define FROM_LOOP FROM_LOOP_DEFAULT +#define TO_LOOP TO_LOOP_DEFAULT #define FROM_DIRECTION (dir == from_utf8) #define ONE_DIRECTION 0 @@ -303,12 +330,9 @@ gconv_end (struct __gconv_step *data) STANDARD_FROM_LOOP_ERR_HANDLER (i); \ } -/* This hardware routine uses the Convert UTF8 to UTF32 (cu14) instruction. */ -#define BODY_FROM_ETF3EH BODY_FROM_HW (HARDWARE_CONVERT ("cu14 %0, %1, 1")) - - +#if HAVE_FROM_C == 1 /* The software routine is copied from gconv_simple.c. */ -#define BODY_FROM_C \ +# define BODY_FROM_C \ { \ /* Next input byte. */ \ uint32_t ch = *inptr; \ @@ -408,7 +432,50 @@ gconv_end (struct __gconv_step *data) outptr += sizeof (uint32_t); \ } -#define HW_FROM_VX \ +/* These definitions apply to the UTF-8 to UTF-32 direction. The + software implementation for UTF-8 still supports multibyte + characters up to 6 bytes whereas the hardware variant does not. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define FROM_LOOP_C __from_utf8_loop_c +# define LOOPFCT FROM_LOOP_C + +# define LOOP_NEED_FLAGS + +# define STORE_REST STORE_REST_COMMON +# define UNPACK_BYTES UNPACK_BYTES_COMMON +# define CLEAR_STATE CLEAR_STATE_COMMON +# define BODY BODY_FROM_C +# include <iconv/loop.c> +#else +# define FROM_LOOP_C NULL +#endif /* HAVE_FROM_C != 1 */ + +#if HAVE_FROM_CU == 1 +/* This hardware routine uses the Convert UTF8 to UTF32 (cu14) instruction. */ +# define BODY_FROM_ETF3EH BODY_FROM_HW (HARDWARE_CONVERT ("cu14 %0, %1, 1")) + +/* Generate loop-function with hardware utf-convert instruction. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_FROM +# define MAX_NEEDED_INPUT MAX_NEEDED_FROM +# define MIN_NEEDED_OUTPUT MIN_NEEDED_TO +# define FROM_LOOP_CU __from_utf8_loop_etf3eh +# define LOOPFCT FROM_LOOP_CU + +# define LOOP_NEED_FLAGS + +# define STORE_REST STORE_REST_COMMON +# define UNPACK_BYTES UNPACK_BYTES_COMMON +# define CLEAR_STATE CLEAR_STATE_COMMON +# define BODY BODY_FROM_ETF3EH +# include <iconv/loop.c> +#else +# define FROM_LOOP_CU NULL +#endif /* HAVE_FROM_CU != 1 */ + +#if HAVE_FROM_VX == 1 +# define HW_FROM_VX \ { \ register const unsigned char* pInput asm ("8") = inptr; \ register size_t inlen asm ("9") = inend - inptr; \ @@ -500,45 +567,14 @@ gconv_end (struct __gconv_step *data) inptr = pInput; \ outptr = pOutput; \ } -#define BODY_FROM_VX BODY_FROM_HW (HW_FROM_VX) +# define BODY_FROM_VX BODY_FROM_HW (HW_FROM_VX) -/* These definitions apply to the UTF-8 to UTF-32 direction. The - software implementation for UTF-8 still supports multibyte - characters up to 6 bytes whereas the hardware variant does not. */ -#define MIN_NEEDED_INPUT MIN_NEEDED_FROM -#define MAX_NEEDED_INPUT MAX_NEEDED_FROM -#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO -#define LOOPFCT __from_utf8_loop_c - -#define LOOP_NEED_FLAGS - -#define STORE_REST STORE_REST_COMMON -#define UNPACK_BYTES UNPACK_BYTES_COMMON -#define CLEAR_STATE CLEAR_STATE_COMMON -#define BODY BODY_FROM_C -#include <iconv/loop.c> - - -/* Generate loop-function with hardware utf-convert instruction. */ -#define MIN_NEEDED_INPUT MIN_NEEDED_FROM -#define MAX_NEEDED_INPUT MAX_NEEDED_FROM -#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO -#define LOOPFCT __from_utf8_loop_etf3eh - -#define LOOP_NEED_FLAGS - -#define STORE_REST STORE_REST_COMMON -#define UNPACK_BYTES UNPACK_BYTES_COMMON -#define CLEAR_STATE CLEAR_STATE_COMMON -#define BODY BODY_FROM_ETF3EH -#include <iconv/loop.c> - -#if defined HAVE_S390_VX_ASM_SUPPORT -/* Generate loop-function with hardware vector instructions. */ +/* Generate loop-function with hardware vector and utf-convert instructions. */ # define MIN_NEEDED_INPUT MIN_NEEDED_FROM # define MAX_NEEDED_INPUT MAX_NEEDED_FROM # define MIN_NEEDED_OUTPUT MIN_NEEDED_TO -# define LOOPFCT __from_utf8_loop_vx +# define FROM_LOOP_VX __from_utf8_loop_vx +# define LOOPFCT FROM_LOOP_VX # define LOOP_NEED_FLAGS @@ -547,33 +583,13 @@ gconv_end (struct __gconv_step *data) # define CLEAR_STATE CLEAR_STATE_COMMON # define BODY BODY_FROM_VX # include <iconv/loop.c> -#endif - - -/* Generate ifunc'ed loop function. */ -__typeof(__from_utf8_loop_c) -__attribute__ ((ifunc ("__from_utf8_loop_resolver"))) -__from_utf8_loop; - -static void * -__from_utf8_loop_resolver (unsigned long int dl_hwcap) -{ -#if defined HAVE_S390_VX_ASM_SUPPORT - if (dl_hwcap & HWCAP_S390_VX) - return __from_utf8_loop_vx; - else -#endif - if (dl_hwcap & HWCAP_S390_ZARCH && dl_hwcap & HWCAP_S390_HIGH_GPRS - && dl_hwcap & HWCAP_S390_ETF3EH) - return __from_utf8_loop_etf3eh; - else - return __from_utf8_loop_c; -} - -strong_alias (__from_utf8_loop_c_single, __from_utf8_loop_single) +#else +# define FROM_LOOP_VX NULL +#endif /* HAVE_FROM_VX != 1 */ +#if HAVE_TO_C == 1 /* The software routine mimics the S/390 cu41 instruction. */ -#define BODY_TO_C \ +# define BODY_TO_C \ { \ uint32_t wc = *((const uint32_t *) inptr); \ \ @@ -657,8 +673,22 @@ strong_alias (__from_utf8_loop_c_single, __from_utf8_loop_single) inptr += 4; \ } +/* Generate loop-function with software routing. */ +# define MIN_NEEDED_INPUT MIN_NEEDED_TO +# define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM +# define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM +# define TO_LOOP_C __to_utf8_loop_c +# define LOOPFCT TO_LOOP_C +# define BODY BODY_TO_C +# define LOOP_NEED_FLAGS +# include <iconv/loop.c> +#else +# define TO_LOOP_C NULL +#endif /* HAVE_TO_C != 1 */ + +#if HAVE_TO_VX == 1 /* The hardware routine uses the S/390 vector instructions. */ -#define BODY_TO_VX \ +# define BODY_TO_VX \ { \ size_t inlen = inend - inptr; \ size_t outlen = outend - outptr; \ @@ -820,43 +850,22 @@ strong_alias (__from_utf8_loop_c_single, __from_utf8_loop_single) STANDARD_TO_LOOP_ERR_HANDLER (4); \ } -/* Generate loop-function with software routing. */ -#define MIN_NEEDED_INPUT MIN_NEEDED_TO -#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM -#define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM -#define LOOPFCT __to_utf8_loop_c -#define BODY BODY_TO_C -#define LOOP_NEED_FLAGS -#include <iconv/loop.c> - -#if defined HAVE_S390_VX_ASM_SUPPORT -/* Generate loop-function with hardware vector and utf-convert instructions. */ +/* Generate loop-function with hardware vector instructions. */ # define MIN_NEEDED_INPUT MIN_NEEDED_TO # define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM # define MAX_NEEDED_OUTPUT MAX_NEEDED_FROM -# define LOOPFCT __to_utf8_loop_vx +# define TO_LOOP_VX __to_utf8_loop_vx +# define LOOPFCT TO_LOOP_VX # define BODY BODY_TO_VX # define LOOP_NEED_FLAGS # include <iconv/loop.c> +#else +# define TO_LOOP_VX NULL +#endif /* HAVE_TO_VX != 1 */ + +/* This file also exists in sysdeps/s390/multiarch/ which + generates ifunc resolvers for FROM/TO_LOOP functions + and includes iconv/skeleton.c afterwards. */ +#if ! defined USE_MULTIARCH +# include <iconv/skeleton.c> #endif - -/* Generate ifunc'ed loop function. */ -__typeof(__to_utf8_loop_c) -__attribute__ ((ifunc ("__to_utf8_loop_resolver"))) -__to_utf8_loop; - -static void * -__to_utf8_loop_resolver (unsigned long int dl_hwcap) -{ -#if defined HAVE_S390_VX_ASM_SUPPORT - if (dl_hwcap & HWCAP_S390_VX) - return __to_utf8_loop_vx; - else -#endif - return __to_utf8_loop_c; -} - -strong_alias (__to_utf8_loop_c_single, __to_utf8_loop_single) - - -#include <iconv/skeleton.c> |