Blame sysdeps/s390/multiarch/8bit-generic.c

Packit 6c4009
/* Generic conversion to and from 8bit charsets - S390 version.
Packit 6c4009
   Copyright (C) 2016-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#if defined HAVE_S390_VX_ASM_SUPPORT
Packit 6c4009
Packit 6c4009
# if defined HAVE_S390_VX_GCC_SUPPORT
Packit 6c4009
#  define ASM_CLOBBER_VR(NR) , NR
Packit 6c4009
# else
Packit 6c4009
#  define ASM_CLOBBER_VR(NR)
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
/* Generate the conversion loop routines without vector instructions as
Packit 6c4009
   fallback, if vector instructions aren't available at runtime.  */
Packit 6c4009
# define IGNORE_ICONV_SKELETON
Packit 6c4009
# define from_generic __from_generic_c
Packit 6c4009
# define to_generic __to_generic_c
Packit 6c4009
# include "iconvdata/8bit-generic.c"
Packit 6c4009
# undef IGNORE_ICONV_SKELETON
Packit 6c4009
# undef from_generic
Packit 6c4009
# undef to_generic
Packit 6c4009
Packit 6c4009
/* Generate the converion routines with vector instructions. The vector
Packit 6c4009
   routines can only be used with charsets where the maximum UCS4 value
Packit 6c4009
   fits in 1 byte size. Then the hardware translate-instruction is used
Packit 6c4009
   to translate between multiple generic characters and "1 byte UCS4"
Packit 6c4009
   characters at once. The vector instructions are used to convert between
Packit 6c4009
   the "1 byte UCS4" and UCS4.  */
Packit 6c4009
# include <ifunc-resolve.h>
Packit 6c4009
Packit 6c4009
# undef FROM_LOOP
Packit 6c4009
# undef TO_LOOP
Packit 6c4009
# define FROM_LOOP		__from_generic_vx
Packit 6c4009
# define TO_LOOP		__to_generic_vx
Packit 6c4009
Packit 6c4009
# define MIN_NEEDED_FROM	1
Packit 6c4009
# define MIN_NEEDED_TO		4
Packit 6c4009
# define ONE_DIRECTION		0
Packit 6c4009
Packit 6c4009
/* First define the conversion function from the 8bit charset to UCS4.  */
Packit 6c4009
# define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
Packit 6c4009
# define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
Packit 6c4009
# define LOOPFCT		FROM_LOOP
Packit 6c4009
# define BODY_FROM_ORIG \
Packit 6c4009
  {									      \
Packit 6c4009
    uint32_t ch = to_ucs4[*inptr];					      \
Packit 6c4009
									      \
Packit 6c4009
    if (HAS_HOLES && __builtin_expect (ch == L'\0', 0) && *inptr != '\0')     \
Packit 6c4009
      {									      \
Packit 6c4009
	/* This is an illegal character.  */				      \
Packit 6c4009
	STANDARD_FROM_LOOP_ERR_HANDLER (1);				      \
Packit 6c4009
      }									      \
Packit 6c4009
									      \
Packit 6c4009
    put32 (outptr, ch);							      \
Packit 6c4009
    outptr += 4;							      \
Packit 6c4009
    ++inptr;								      \
Packit 6c4009
  }
Packit 6c4009
Packit 6c4009
# define BODY								\
Packit 6c4009
  {									\
Packit 6c4009
    if (__builtin_expect (inend - inptr < 16, 1)			\
Packit 6c4009
	|| outend - outptr < 64)					\
Packit 6c4009
      /* Convert remaining bytes with c code.  */			\
Packit 6c4009
      BODY_FROM_ORIG							\
Packit 6c4009
    else								\
Packit 6c4009
       {								\
Packit 6c4009
	 /* Convert 16 ... 256 bytes at once with tr-instruction.  */	\
Packit 6c4009
	 size_t index;							\
Packit 6c4009
	 char buf[256];							\
Packit 6c4009
	 size_t loop_count = (inend - inptr) / 16;			\
Packit 6c4009
	 if (loop_count > (outend - outptr) / 64)			\
Packit 6c4009
	   loop_count = (outend - outptr) / 64;				\
Packit 6c4009
	 if (loop_count > 16)						\
Packit 6c4009
	   loop_count = 16;						\
Packit 6c4009
	 __asm__ volatile (".machine push\n\t"				\
Packit 6c4009
			   ".machine \"z13\"\n\t"			\
Packit 6c4009
			   ".machinemode \"zarch_nohighgprs\"\n\t"	\
Packit 6c4009
			   "    sllk %[R_I],%[R_LI],4\n\t"		\
Packit 6c4009
			   "    ahi %[R_I],-1\n\t"			\
Packit 6c4009
			   /* Execute mvc and tr with correct len.  */	\
Packit 6c4009
			   "    exrl %[R_I],21f\n\t"			\
Packit 6c4009
			   "    exrl %[R_I],22f\n\t"			\
Packit 6c4009
			   /* Post-processing.  */			\
Packit 6c4009
			   "    lghi %[R_I],0\n\t"			\
Packit 6c4009
			   "    vzero %%v0\n\t"				\
Packit 6c4009
			   "0:  \n\t"					\
Packit 6c4009
			   /* Find invalid character - value is zero.  */ \
Packit 6c4009
			   "    vl %%v16,0(%[R_I],%[R_BUF])\n\t"	\
Packit 6c4009
			   "    vceqbs %%v23,%%v0,%%v16\n\t"		\
Packit 6c4009
			   "    jle 10f\n\t"				\
Packit 6c4009
			   "1:  \n\t"					\
Packit 6c4009
			   /* Enlarge to UCS4.  */			\
Packit 6c4009
			   "    vuplhb %%v17,%%v16\n\t"			\
Packit 6c4009
			   "    vupllb %%v18,%%v16\n\t"			\
Packit 6c4009
			   "    vuplhh %%v19,%%v17\n\t"			\
Packit 6c4009
			   "    vupllh %%v20,%%v17\n\t"			\
Packit 6c4009
			   "    vuplhh %%v21,%%v18\n\t"			\
Packit 6c4009
			   "    vupllh %%v22,%%v18\n\t"			\
Packit 6c4009
			   /* Store 64bytes to buf_out.  */		\
Packit 6c4009
			   "    vstm %%v19,%%v22,0(%[R_OUT])\n\t"	\
Packit 6c4009
			   "    aghi %[R_I],16\n\t"			\
Packit 6c4009
			   "    la %[R_OUT],64(%[R_OUT])\n\t"		\
Packit 6c4009
			   "    brct %[R_LI],0b\n\t"			\
Packit 6c4009
			   "    la %[R_IN],0(%[R_I],%[R_IN])\n\t"	\
Packit 6c4009
			   "    j 20f\n\t"				\
Packit 6c4009
			   "21: mvc 0(1,%[R_BUF]),0(%[R_IN])\n\t"	\
Packit 6c4009
			   "22: tr 0(1,%[R_BUF]),0(%[R_TBL])\n\t"	\
Packit 6c4009
			   /* Possibly invalid character found.  */	\
Packit 6c4009
			   "10: \n\t"					\
Packit 6c4009
			   /* Test if input was zero, too.  */		\
Packit 6c4009
			   "    vl %%v24,0(%[R_I],%[R_IN])\n\t"		\
Packit 6c4009
			   "    vceqb %%v24,%%v0,%%v24\n\t"		\
Packit 6c4009
			   /* Zeros in buf (v23) and inptr (v24) are marked \
Packit 6c4009
			      with one bits. After xor, invalid characters \
Packit 6c4009
			      are marked as one bits. Proceed, if no	\
Packit 6c4009
			      invalid characters are found.  */		\
Packit 6c4009
			   "    vx %%v24,%%v23,%%v24\n\t"		\
Packit 6c4009
			   "    vfenebs %%v24,%%v24,%%v0\n\t"		\
Packit 6c4009
			   "    jo 1b\n\t"				\
Packit 6c4009
			   /* Found an invalid translation.		\
Packit 6c4009
			      Store the preceding chars.  */		\
Packit 6c4009
			   "    la %[R_IN],0(%[R_I],%[R_IN])\n\t"	\
Packit 6c4009
			   "    vlgvb %[R_I],%%v24,7\n\t"		\
Packit 6c4009
			   "    la %[R_IN],0(%[R_I],%[R_IN])\n\t"	\
Packit 6c4009
			   "    sll %[R_I],2\n\t"			\
Packit 6c4009
			   "    ahi %[R_I],-1\n\t"			\
Packit 6c4009
			   "    jl 20f\n\t"				\
Packit 6c4009
			   "    lgr %[R_LI],%[R_I]\n\t"			\
Packit 6c4009
			   "    vuplhb %%v17,%%v16\n\t"			\
Packit 6c4009
			   "    vuplhh %%v19,%%v17\n\t"			\
Packit 6c4009
			   "    vstl %%v19,%[R_I],0(%[R_OUT])\n\t"	\
Packit 6c4009
			   "    ahi %[R_I],-16\n\t"			\
Packit 6c4009
			   "    jl 11f\n\t"				\
Packit 6c4009
			   "    vupllh %%v20,%%v17\n\t"			\
Packit 6c4009
			   "    vstl %%v20,%[R_I],16(%[R_OUT])\n\t"	\
Packit 6c4009
			   "    ahi %[R_I],-16\n\t"			\
Packit 6c4009
			   "    jl 11f\n\t"				\
Packit 6c4009
			   "    vupllb %%v18,%%v16\n\t"			\
Packit 6c4009
			   "    vuplhh %%v21,%%v18\n\t"			\
Packit 6c4009
			   "    vstl %%v21,%[R_I],32(%[R_OUT])\n\t"	\
Packit 6c4009
			   "    ahi %[R_I],-16\n\t"			\
Packit 6c4009
			   "    jl 11f\n\t"				\
Packit 6c4009
			   "    vupllh %%v22,%%v18\n\t"			\
Packit 6c4009
			   "    vstl %%v22,%[R_I],48(%[R_OUT])\n\t"	\
Packit 6c4009
			   "11: \n\t"					\
Packit 6c4009
			   "    la %[R_OUT],1(%[R_LI],%[R_OUT])\n\t"	\
Packit 6c4009
			   "20: \n\t"					\
Packit 6c4009
			   ".machine pop"				\
Packit 6c4009
			   : /* outputs */ [R_IN] "+a" (inptr)		\
Packit 6c4009
			     , [R_OUT] "+a" (outptr), [R_I] "=&a" (index) \
Packit 6c4009
			     , [R_LI] "+a" (loop_count)			\
Packit 6c4009
			   : /* inputs */ [R_BUF] "a" (buf)		\
Packit 6c4009
			     , [R_TBL] "a" (to_ucs1)			\
Packit 6c4009
			   : /* clobber list*/ "memory", "cc"		\
Packit 6c4009
			     ASM_CLOBBER_VR ("v0")  ASM_CLOBBER_VR ("v16") \
Packit 6c4009
			     ASM_CLOBBER_VR ("v17") ASM_CLOBBER_VR ("v18") \
Packit 6c4009
			     ASM_CLOBBER_VR ("v19") ASM_CLOBBER_VR ("v20") \
Packit 6c4009
			     ASM_CLOBBER_VR ("v21") ASM_CLOBBER_VR ("v22") \
Packit 6c4009
			     ASM_CLOBBER_VR ("v23") ASM_CLOBBER_VR ("v24") \
Packit 6c4009
			   );						\
Packit 6c4009
	 /* Error occured?  */						\
Packit 6c4009
	 if (loop_count != 0)						\
Packit 6c4009
	   {								\
Packit 6c4009
	     /* Found an invalid character!  */				\
Packit 6c4009
	    STANDARD_FROM_LOOP_ERR_HANDLER (1);				\
Packit 6c4009
	  }								\
Packit 6c4009
      }									\
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
# define LOOP_NEED_FLAGS
Packit 6c4009
# include <iconv/loop.c>
Packit 6c4009
Packit 6c4009
/* Next, define the other direction - from UCS4 to 8bit charset.  */
Packit 6c4009
# define MIN_NEEDED_INPUT	MIN_NEEDED_TO
Packit 6c4009
# define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
Packit 6c4009
# define LOOPFCT		TO_LOOP
Packit 6c4009
# define BODY_TO_ORIG \
Packit 6c4009
  {									      \
Packit 6c4009
    uint32_t ch = get32 (inptr);					      \
Packit 6c4009
									      \
Packit 6c4009
    if (__builtin_expect (ch >= sizeof (from_ucs4) / sizeof (from_ucs4[0]), 0)\
Packit 6c4009
	|| (__builtin_expect (from_ucs4[ch], '\1') == '\0' && ch != 0))	      \
Packit 6c4009
      {									      \
Packit 6c4009
	UNICODE_TAG_HANDLER (ch, 4);					      \
Packit 6c4009
									      \
Packit 6c4009
	/* This is an illegal character.  */				      \
Packit 6c4009
	STANDARD_TO_LOOP_ERR_HANDLER (4);				      \
Packit 6c4009
      }									      \
Packit 6c4009
									      \
Packit 6c4009
    *outptr++ = from_ucs4[ch];						      \
Packit 6c4009
    inptr += 4;								      \
Packit 6c4009
  }
Packit 6c4009
# define BODY								\
Packit 6c4009
  {									\
Packit 6c4009
    if (__builtin_expect (inend - inptr < 64, 1)			\
Packit 6c4009
	|| outend - outptr < 16)					\
Packit 6c4009
      /* Convert remaining bytes with c code.  */			\
Packit 6c4009
      BODY_TO_ORIG							\
Packit 6c4009
    else								\
Packit 6c4009
      {									\
Packit 6c4009
	/* Convert 64 ... 1024 bytes at once with tr-instruction.  */	\
Packit 6c4009
	size_t index, tmp;						\
Packit 6c4009
	char buf[256];							\
Packit 6c4009
	size_t loop_count = (inend - inptr) / 64;			\
Packit 6c4009
	uint32_t max = sizeof (from_ucs4) / sizeof (from_ucs4[0]);	\
Packit 6c4009
	if (loop_count > (outend - outptr) / 16)			\
Packit 6c4009
	  loop_count = (outend - outptr) / 16;				\
Packit 6c4009
	if (loop_count > 16)						\
Packit 6c4009
	  loop_count = 16;						\
Packit 6c4009
	size_t remaining_loop_count = loop_count;			\
Packit 6c4009
	/* Step 1: Check for ch>=max, ch == 0 and shorten to bytes.	\
Packit 6c4009
	   (ch == 0 is no error, but is handled differently)  */	\
Packit 6c4009
	__asm__ volatile (".machine push\n\t"				\
Packit 6c4009
			  ".machine \"z13\"\n\t"			\
Packit 6c4009
			  ".machinemode \"zarch_nohighgprs\"\n\t"	\
Packit 6c4009
			  /* Setup to check for ch >= max.  */		\
Packit 6c4009
			  "    vzero %%v21\n\t"				\
Packit 6c4009
			  "    vleih %%v21,-24576,0\n\t" /* element 0:   >  */ \
Packit 6c4009
			  "    vleih %%v21,-8192,2\n\t"  /* element 1: =<>  */ \
Packit 6c4009
			  "    vlvgf %%v20,%[R_MAX],0\n\t" /* element 0: val  */ \
Packit 6c4009
			  /* Process in 64byte - 16 characters blocks.  */ \
Packit 6c4009
			  "    lghi %[R_I],0\n\t"			\
Packit 6c4009
			  "    lghi %[R_TMP],0\n\t"			\
Packit 6c4009
			  "0:  \n\t"					\
Packit 6c4009
			  "    vlm %%v16,%%v19,0(%[R_IN])\n\t"		\
Packit 6c4009
			  /* Test for ch >= max and ch == 0.  */	\
Packit 6c4009
			  "    vstrczfs %%v22,%%v16,%%v20,%%v21\n\t"	\
Packit 6c4009
			  "    jno 10f\n\t"				\
Packit 6c4009
			  "    vstrczfs %%v22,%%v17,%%v20,%%v21\n\t"	\
Packit 6c4009
			  "    jno 11f\n\t"				\
Packit 6c4009
			  "    vstrczfs %%v22,%%v18,%%v20,%%v21\n\t"	\
Packit 6c4009
			  "    jno 12f\n\t"				\
Packit 6c4009
			  "    vstrczfs %%v22,%%v19,%%v20,%%v21\n\t"	\
Packit 6c4009
			  "    jno 13f\n\t"				\
Packit 6c4009
			  /* Shorten to byte values.  */		\
Packit 6c4009
			  "    vpkf %%v16,%%v16,%%v17\n\t"		\
Packit 6c4009
			  "    vpkf %%v18,%%v18,%%v19\n\t"		\
Packit 6c4009
			  "    vpkh %%v16,%%v16,%%v18\n\t"		\
Packit 6c4009
			  /* Store 16bytes to buf.  */			\
Packit 6c4009
			  "    vst %%v16,0(%[R_I],%[R_BUF])\n\t"	\
Packit 6c4009
			  /* Loop until all blocks are processed.  */	\
Packit 6c4009
			  "    la %[R_IN],64(%[R_IN])\n\t"		\
Packit 6c4009
			  "    aghi %[R_I],16\n\t"			\
Packit 6c4009
			  "    brct %[R_LI],0b\n\t"			\
Packit 6c4009
			  "    j 20f\n\t"				\
Packit 6c4009
			  /* Found error ch >= max or ch == 0. */	\
Packit 6c4009
			  "13: aghi %[R_TMP],4\n\t"			\
Packit 6c4009
			  "12: aghi %[R_TMP],4\n\t"			\
Packit 6c4009
			  "11: aghi %[R_TMP],4\n\t"			\
Packit 6c4009
			  "10: vlgvb %[R_I],%%v22,7\n\t"		\
Packit 6c4009
			  "    srlg %[R_I],%[R_I],2\n\t"		\
Packit 6c4009
			  "    agr %[R_I],%[R_TMP]\n\t"			\
Packit 6c4009
			  "20: \n\t"					\
Packit 6c4009
			  ".machine pop"				\
Packit 6c4009
			  : /* outputs */ [R_IN] "+a" (inptr)		\
Packit 6c4009
			    , [R_I] "=&a" (index)			\
Packit 6c4009
			    , [R_TMP] "=d" (tmp)			\
Packit 6c4009
			    , [R_LI] "+d" (remaining_loop_count)	\
Packit 6c4009
			  : /* inputs */ [R_BUF] "a" (buf)		\
Packit 6c4009
			    , [R_MAX] "d" (max)				\
Packit 6c4009
			  : /* clobber list*/ "memory", "cc"		\
Packit 6c4009
			    ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17") \
Packit 6c4009
			    ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19") \
Packit 6c4009
			    ASM_CLOBBER_VR ("v20") ASM_CLOBBER_VR ("v21") \
Packit 6c4009
			    ASM_CLOBBER_VR ("v22")			\
Packit 6c4009
			  );						\
Packit 6c4009
	/* Error occured in step 1? An error (ch >= max || ch == 0)	\
Packit 6c4009
	   occured, if remaining_loop_count > 0. The error occured	\
Packit 6c4009
	   at character-index (index) after already processed blocks.  */ \
Packit 6c4009
	loop_count -= remaining_loop_count;				\
Packit 6c4009
	if (loop_count > 0)						\
Packit 6c4009
	  {								\
Packit 6c4009
	    /* Step 2: Translate already processed blocks in buf and	\
Packit 6c4009
	       check for errors (from_ucs4[ch] == 0).  */		\
Packit 6c4009
	    __asm__ volatile (".machine push\n\t"			\
Packit 6c4009
			      ".machine \"z13\"\n\t"			\
Packit 6c4009
			      ".machinemode \"zarch_nohighgprs\"\n\t"	\
Packit 6c4009
			      "    sllk %[R_I],%[R_LI],4\n\t"		\
Packit 6c4009
			      "    ahi %[R_I],-1\n\t"			\
Packit 6c4009
			      /* Execute tr with correct len.  */	\
Packit 6c4009
			      "    exrl %[R_I],21f\n\t"			\
Packit 6c4009
			      /* Post-processing.  */			\
Packit 6c4009
			      "    lghi %[R_I],0\n\t"			\
Packit 6c4009
			      "0:  \n\t"				\
Packit 6c4009
			      /* Find invalid character - value == 0.  */ \
Packit 6c4009
			      "    vl %%v16,0(%[R_I],%[R_BUF])\n\t"	\
Packit 6c4009
			      "    vfenezbs %%v17,%%v16,%%v16\n\t"	\
Packit 6c4009
			      "    je 10f\n\t"				\
Packit 6c4009
			      /* Store 16bytes to buf_out.  */		\
Packit 6c4009
			      "    vst %%v16,0(%[R_I],%[R_OUT])\n\t"	\
Packit 6c4009
			      "    aghi %[R_I],16\n\t"			\
Packit 6c4009
			      "    brct %[R_LI],0b\n\t"			\
Packit 6c4009
			      "    la %[R_OUT],0(%[R_I],%[R_OUT])\n\t"	\
Packit 6c4009
			      "    j 20f\n\t"				\
Packit 6c4009
			      "21: tr 0(1,%[R_BUF]),0(%[R_TBL])\n\t"	\
Packit 6c4009
			      /* Found an error: from_ucs4[ch] == 0.  */ \
Packit 6c4009
			      "10: la %[R_OUT],0(%[R_I],%[R_OUT])\n\t"	\
Packit 6c4009
			      "    vlgvb %[R_I],%%v17,7\n\t"		\
Packit 6c4009
			      "20: \n\t"				\
Packit 6c4009
			      ".machine pop"				\
Packit 6c4009
			      : /* outputs */ [R_OUT] "+a" (outptr)	\
Packit 6c4009
				, [R_I] "=&a" (tmp)			\
Packit 6c4009
				, [R_LI] "+d" (loop_count)		\
Packit 6c4009
			      : /* inputs */ [R_BUF] "a" (buf)		\
Packit 6c4009
				, [R_TBL] "a" (from_ucs4)		\
Packit 6c4009
			      : /* clobber list*/ "memory", "cc"	\
Packit 6c4009
				ASM_CLOBBER_VR ("v16")			\
Packit 6c4009
				ASM_CLOBBER_VR ("v17")			\
Packit 6c4009
			      );					\
Packit 6c4009
	    /* Error occured in processed bytes of step 2?		\
Packit 6c4009
	       Thus possible error in step 1 is obselete.*/		\
Packit 6c4009
	    if (tmp < 16)						\
Packit 6c4009
	      {								\
Packit 6c4009
		index = tmp;						\
Packit 6c4009
		inptr -= loop_count * 64;				\
Packit 6c4009
	      }								\
Packit 6c4009
	  }								\
Packit 6c4009
	/* Error occured in step 1/2?  */				\
Packit 6c4009
	if (index < 16)							\
Packit 6c4009
	  {								\
Packit 6c4009
	    /* Found an invalid character (see step 2) or zero		\
Packit 6c4009
	       (see step 1) at index! Convert the chars before index	\
Packit 6c4009
	       manually. If there is a zero at index detected by step 1, \
Packit 6c4009
	       there could be invalid characters before this zero.  */	\
Packit 6c4009
	    int i;							\
Packit 6c4009
	    uint32_t ch;						\
Packit 6c4009
	    for (i = 0; i < index; i++)					\
Packit 6c4009
	      {								\
Packit 6c4009
		ch = get32 (inptr);					\
Packit 6c4009
		if (__builtin_expect (from_ucs4[ch], '\1') == '\0')     \
Packit 6c4009
		  break;						\
Packit 6c4009
		*outptr++ = from_ucs4[ch];				\
Packit 6c4009
		inptr += 4;						\
Packit 6c4009
	      }								\
Packit 6c4009
	    if (i == index)						\
Packit 6c4009
	      {								\
Packit 6c4009
		ch = get32 (inptr);					\
Packit 6c4009
		if (ch == 0)						\
Packit 6c4009
		  {							\
Packit 6c4009
		    /* This is no error, but handled differently.  */	\
Packit 6c4009
		    *outptr++ = from_ucs4[ch];				\
Packit 6c4009
		    inptr += 4;						\
Packit 6c4009
		    continue;						\
Packit 6c4009
		  }							\
Packit 6c4009
	      }								\
Packit 6c4009
									\
Packit 6c4009
	    /* iconv/loop.c disables -Wmaybe-uninitialized for a false	\
Packit 6c4009
	       positive warning in this code with -Os and has a		\
Packit 6c4009
	       comment referencing this code accordingly.  Updates in	\
Packit 6c4009
	       one place may require updates in the other.  */		\
Packit 6c4009
	    UNICODE_TAG_HANDLER (ch, 4);				\
Packit 6c4009
									\
Packit 6c4009
	    /* This is an illegal character.  */			\
Packit 6c4009
	    STANDARD_TO_LOOP_ERR_HANDLER (4);				\
Packit 6c4009
	  }								\
Packit 6c4009
      }									\
Packit 6c4009
  }
Packit 6c4009
Packit 6c4009
# define LOOP_NEED_FLAGS
Packit 6c4009
# include <iconv/loop.c>
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Generate ifunc'ed loop function.  */
Packit 6c4009
s390_libc_ifunc_expr (__from_generic_c, __from_generic,
Packit 6c4009
		      (sizeof (from_ucs4) / sizeof (from_ucs4[0]) <= 256
Packit 6c4009
		       && hwcap & HWCAP_S390_VX)
Packit 6c4009
		      ? __from_generic_vx
Packit 6c4009
		      : __from_generic_c);
Packit 6c4009
Packit 6c4009
s390_libc_ifunc_expr (__to_generic_c, __to_generic,
Packit 6c4009
		      (sizeof (from_ucs4) / sizeof (from_ucs4[0]) <= 256
Packit 6c4009
		       && hwcap & HWCAP_S390_VX)
Packit 6c4009
		      ? __to_generic_vx
Packit 6c4009
		      : __to_generic_c);
Packit 6c4009
Packit 6c4009
strong_alias (__to_generic_c_single, __to_generic_single)
Packit 6c4009
Packit 6c4009
# undef FROM_LOOP
Packit 6c4009
# undef TO_LOOP
Packit 6c4009
# define FROM_LOOP		__from_generic
Packit 6c4009
# define TO_LOOP		__to_generic
Packit 6c4009
# include <iconv/skeleton.c>
Packit 6c4009
Packit 6c4009
#else
Packit 6c4009
/* Generate this module without ifunc if build environment lacks vector
Packit 6c4009
   support.  Instead the common 8bit-generic.c is used.  */
Packit 6c4009
# include "iconvdata/8bit-generic.c"
Packit 6c4009
#endif /* !defined HAVE_S390_VX_ASM_SUPPORT */