Blame sysdeps/s390/utf16-utf32-z9.c

Packit Service 82fcde
/* Conversion between UTF-16 and UTF-32 BE/internal.
Packit Service 82fcde
Packit Service 82fcde
   This module uses the Z9-109 variants of the Convert Unicode
Packit Service 82fcde
   instructions.
Packit Service 82fcde
   Copyright (C) 1997-2018 Free Software Foundation, Inc.
Packit Service 82fcde
Packit Service 82fcde
   Author: Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
Packit Service 82fcde
   Based on the work by Ulrich Drepper  <drepper@cygnus.com>, 1997.
Packit Service 82fcde
Packit Service 82fcde
   Thanks to Daniel Appich who covered the relevant performance work
Packit Service 82fcde
   in his diploma thesis.
Packit Service 82fcde
Packit Service 82fcde
   This is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   This is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <dlfcn.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <gconv.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
Packit Service 82fcde
/* Select which versions should be defined depending on support
Packit Service 82fcde
   for multiarch, vector and used minimum architecture level.  */
Packit Service 82fcde
#define HAVE_FROM_C		1
Packit Service 82fcde
#define FROM_LOOP_DEFAULT	FROM_LOOP_C
Packit Service 82fcde
#define HAVE_TO_C		1
Packit Service 82fcde
#define TO_LOOP_DEFAULT		TO_LOOP_C
Packit Service 82fcde
Packit Service 82fcde
#if defined HAVE_S390_VX_ASM_SUPPORT && defined USE_MULTIARCH
Packit Service 82fcde
# define HAVE_FROM_VX		1
Packit Service 82fcde
# define HAVE_FROM_VX_CU	1
Packit Service 82fcde
# define HAVE_TO_VX		1
Packit Service 82fcde
# define HAVE_TO_VX_CU		1
Packit Service 82fcde
#else
Packit Service 82fcde
# define HAVE_FROM_VX		0
Packit Service 82fcde
# define HAVE_FROM_VX_CU	0
Packit Service 82fcde
# define HAVE_TO_VX		0
Packit Service 82fcde
# define HAVE_TO_VX_CU		0
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#if defined HAVE_S390_VX_GCC_SUPPORT
Packit Service 82fcde
# define ASM_CLOBBER_VR(NR) , NR
Packit Service 82fcde
#else
Packit Service 82fcde
# define ASM_CLOBBER_VR(NR)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#if defined __s390x__
Packit Service 82fcde
# define CONVERT_32BIT_SIZE_T(REG)
Packit Service 82fcde
#else
Packit Service 82fcde
# define CONVERT_32BIT_SIZE_T(REG) "llgfr %" #REG ",%" #REG "\n\t"
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* UTF-32 big endian byte order mark.  */
Packit Service 82fcde
#define BOM_UTF32               0x0000feffu
Packit Service 82fcde
Packit Service 82fcde
/* UTF-16 big endian byte order mark.  */
Packit Service 82fcde
#define BOM_UTF16               0xfeff
Packit Service 82fcde
Packit Service 82fcde
#define DEFINE_INIT		0
Packit Service 82fcde
#define DEFINE_FINI		0
Packit Service 82fcde
#define MIN_NEEDED_FROM		2
Packit Service 82fcde
#define MAX_NEEDED_FROM		4
Packit Service 82fcde
#define MIN_NEEDED_TO		4
Packit Service 82fcde
#define FROM_LOOP		FROM_LOOP_DEFAULT
Packit Service 82fcde
#define TO_LOOP			TO_LOOP_DEFAULT
Packit Service 82fcde
#define FROM_DIRECTION		(dir == from_utf16)
Packit Service 82fcde
#define ONE_DIRECTION           0
Packit Service 82fcde
Packit Service 82fcde
/* Direction of the transformation.  */
Packit Service 82fcde
enum direction
Packit Service 82fcde
{
Packit Service 82fcde
  illegal_dir,
Packit Service 82fcde
  to_utf16,
Packit Service 82fcde
  from_utf16
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
struct utf16_data
Packit Service 82fcde
{
Packit Service 82fcde
  enum direction dir;
Packit Service 82fcde
  int emit_bom;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
extern int gconv_init (struct __gconv_step *step);
Packit Service 82fcde
int
Packit Service 82fcde
gconv_init (struct __gconv_step *step)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Determine which direction.  */
Packit Service 82fcde
  struct utf16_data *new_data;
Packit Service 82fcde
  enum direction dir = illegal_dir;
Packit Service 82fcde
  int emit_bom;
Packit Service 82fcde
  int result;
Packit Service 82fcde
Packit Service 82fcde
  emit_bom = (__strcasecmp (step->__to_name, "UTF-32//") == 0
Packit Service 82fcde
	      || __strcasecmp (step->__to_name, "UTF-16//") == 0);
Packit Service 82fcde
Packit Service 82fcde
  if (__strcasecmp (step->__from_name, "UTF-16BE//") == 0
Packit Service 82fcde
      && (__strcasecmp (step->__to_name, "UTF-32//") == 0
Packit Service 82fcde
	  || __strcasecmp (step->__to_name, "UTF-32BE//") == 0
Packit Service 82fcde
	  || __strcasecmp (step->__to_name, "INTERNAL") == 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      dir = from_utf16;
Packit Service 82fcde
    }
Packit Service 82fcde
  else if ((__strcasecmp (step->__to_name, "UTF-16//") == 0
Packit Service 82fcde
	    || __strcasecmp (step->__to_name, "UTF-16BE//") == 0)
Packit Service 82fcde
	   && (__strcasecmp (step->__from_name, "UTF-32BE//") == 0
Packit Service 82fcde
	       || __strcasecmp (step->__from_name, "INTERNAL") == 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      dir = to_utf16;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  result = __GCONV_NOCONV;
Packit Service 82fcde
  if (dir != illegal_dir)
Packit Service 82fcde
    {
Packit Service 82fcde
      new_data = (struct utf16_data *) malloc (sizeof (struct utf16_data));
Packit Service 82fcde
Packit Service 82fcde
      result = __GCONV_NOMEM;
Packit Service 82fcde
      if (new_data != NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  new_data->dir = dir;
Packit Service 82fcde
	  new_data->emit_bom = emit_bom;
Packit Service 82fcde
	  step->__data = new_data;
Packit Service 82fcde
Packit Service 82fcde
	  if (dir == from_utf16)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      step->__min_needed_from = MIN_NEEDED_FROM;
Packit Service 82fcde
	      step->__max_needed_from = MIN_NEEDED_FROM;
Packit Service 82fcde
	      step->__min_needed_to = MIN_NEEDED_TO;
Packit Service 82fcde
	      step->__max_needed_to = MIN_NEEDED_TO;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      step->__min_needed_from = MIN_NEEDED_TO;
Packit Service 82fcde
	      step->__max_needed_from = MIN_NEEDED_TO;
Packit Service 82fcde
	      step->__min_needed_to = MIN_NEEDED_FROM;
Packit Service 82fcde
	      step->__max_needed_to = MIN_NEEDED_FROM;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  step->__stateful = 0;
Packit Service 82fcde
Packit Service 82fcde
	  result = __GCONV_OK;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
extern void gconv_end (struct __gconv_step *data);
Packit Service 82fcde
void
Packit Service 82fcde
gconv_end (struct __gconv_step *data)
Packit Service 82fcde
{
Packit Service 82fcde
  free (data->__data);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#define PREPARE_LOOP							\
Packit Service 82fcde
  enum direction dir = ((struct utf16_data *) step->__data)->dir;	\
Packit Service 82fcde
  int emit_bom = ((struct utf16_data *) step->__data)->emit_bom;	\
Packit Service 82fcde
									\
Packit Service 82fcde
  if (emit_bom && !data->__internal_use					\
Packit Service 82fcde
      && data->__invocation_counter == 0)				\
Packit Service 82fcde
    {									\
Packit Service 82fcde
      if (dir == to_utf16)						\
Packit Service 82fcde
	{								\
Packit Service 82fcde
	  /* Emit the UTF-16 Byte Order Mark.  */			\
Packit Service 82fcde
	  if (__glibc_unlikely (outbuf + 2 > outend))			\
Packit Service 82fcde
	    return __GCONV_FULL_OUTPUT;					\
Packit Service 82fcde
									\
Packit Service 82fcde
	  put16u (outbuf, BOM_UTF16);					\
Packit Service 82fcde
	  outbuf += 2;							\
Packit Service 82fcde
	}								\
Packit Service 82fcde
      else								\
Packit Service 82fcde
	{								\
Packit Service 82fcde
	  /* Emit the UTF-32 Byte Order Mark.  */			\
Packit Service 82fcde
	  if (__glibc_unlikely (outbuf + 4 > outend))			\
Packit Service 82fcde
	    return __GCONV_FULL_OUTPUT;					\
Packit Service 82fcde
									\
Packit Service 82fcde
	  put32u (outbuf, BOM_UTF32);					\
Packit Service 82fcde
	  outbuf += 4;							\
Packit Service 82fcde
	}								\
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
/* Conversion function from UTF-16 to UTF-32 internal/BE.  */
Packit Service 82fcde
Packit Service 82fcde
#if HAVE_FROM_C == 1
Packit Service 82fcde
/* The software routine is copied from utf-16.c (minus bytes
Packit Service 82fcde
   swapping).  */
Packit Service 82fcde
# define BODY_FROM_C							\
Packit Service 82fcde
  {									\
Packit Service 82fcde
    uint16_t u1 = get16 (inptr);					\
Packit Service 82fcde
									\
Packit Service 82fcde
    if (__builtin_expect (u1 < 0xd800, 1) || u1 > 0xdfff)		\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	/* No surrogate.  */						\
Packit Service 82fcde
	put32 (outptr, u1);						\
Packit Service 82fcde
	inptr += 2;							\
Packit Service 82fcde
      }									\
Packit Service 82fcde
    else								\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	/* An isolated low-surrogate was found.  This has to be         \
Packit Service 82fcde
	   considered ill-formed.  */					\
Packit Service 82fcde
	if (__glibc_unlikely (u1 >= 0xdc00))				\
Packit Service 82fcde
	  {								\
Packit Service 82fcde
	    STANDARD_FROM_LOOP_ERR_HANDLER (2);				\
Packit Service 82fcde
	  }								\
Packit Service 82fcde
	/* It's a surrogate character.  At least the first word says	\
Packit Service 82fcde
	   it is.  */							\
Packit Service 82fcde
	if (__glibc_unlikely (inptr + 4 > inend))			\
Packit Service 82fcde
	  {								\
Packit Service 82fcde
	    /* We don't have enough input for another complete input	\
Packit Service 82fcde
	       character.  */						\
Packit Service 82fcde
	    result = __GCONV_INCOMPLETE_INPUT;				\
Packit Service 82fcde
	    break;							\
Packit Service 82fcde
	  }								\
Packit Service 82fcde
									\
Packit Service 82fcde
	inptr += 2;							\
Packit Service 82fcde
	uint16_t u2 = get16 (inptr);					\
Packit Service 82fcde
	if (__builtin_expect (u2 < 0xdc00, 0)				\
Packit Service 82fcde
	    || __builtin_expect (u2 > 0xdfff, 0))			\
Packit Service 82fcde
	  {								\
Packit Service 82fcde
	    /* This is no valid second word for a surrogate.  */	\
Packit Service 82fcde
	    inptr -= 2;							\
Packit Service 82fcde
	    STANDARD_FROM_LOOP_ERR_HANDLER (2);				\
Packit Service 82fcde
	  }								\
Packit Service 82fcde
									\
Packit Service 82fcde
	put32 (outptr, ((u1 - 0xd7c0) << 10) + (u2 - 0xdc00));		\
Packit Service 82fcde
	inptr += 2;							\
Packit Service 82fcde
      }									\
Packit Service 82fcde
    outptr += 4;							\
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Generate loop-function with software routing.  */
Packit Service 82fcde
# define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
Packit Service 82fcde
# define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
Packit Service 82fcde
# define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
Packit Service 82fcde
# define FROM_LOOP_C		__from_utf16_loop_c
Packit Service 82fcde
# define LOOPFCT		FROM_LOOP_C
Packit Service 82fcde
# define LOOP_NEED_FLAGS
Packit Service 82fcde
# define BODY			BODY_FROM_C
Packit Service 82fcde
# include <iconv/loop.c>
Packit Service 82fcde
#else
Packit Service 82fcde
# define FROM_LOOP_C		NULL
Packit Service 82fcde
#endif /* HAVE_FROM_C != 1  */
Packit Service 82fcde
Packit Service 82fcde
#if HAVE_FROM_VX == 1
Packit Service 82fcde
# define BODY_FROM_VX							\
Packit Service 82fcde
  {									\
Packit Service 82fcde
    size_t inlen = inend - inptr;					\
Packit Service 82fcde
    size_t outlen = outend - outptr;					\
Packit Service 82fcde
    unsigned long tmp, tmp2, tmp3;					\
Packit Service 82fcde
    asm volatile (".machine push\n\t"					\
Packit Service 82fcde
		  ".machine \"z13\"\n\t"				\
Packit Service 82fcde
		  ".machinemode \"zarch_nohighgprs\"\n\t"		\
Packit Service 82fcde
		  /* Setup to check for surrogates.  */			\
Packit Service 82fcde
		  "    larl %[R_TMP],9f\n\t"				\
Packit Service 82fcde
		  "    vlm %%v30,%%v31,0(%[R_TMP])\n\t"			\
Packit Service 82fcde
		  CONVERT_32BIT_SIZE_T ([R_INLEN])			\
Packit Service 82fcde
		  CONVERT_32BIT_SIZE_T ([R_OUTLEN])			\
Packit Service 82fcde
		  /* Loop which handles UTF-16 chars <0xd800, >0xdfff.  */ \
Packit Service 82fcde
		  "0:  clgijl %[R_INLEN],16,2f\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_OUTLEN],32,2f\n\t"			\
Packit Service 82fcde
		  "1:  vl %%v16,0(%[R_IN])\n\t"				\
Packit Service 82fcde
		  /* Check for surrogate chars.  */			\
Packit Service 82fcde
		  "    vstrchs %%v19,%%v16,%%v30,%%v31\n\t"		\
Packit Service 82fcde
		  "    jno 10f\n\t"					\
Packit Service 82fcde
		  /* Enlarge to UTF-32.  */				\
Packit Service 82fcde
		  "    vuplhh %%v17,%%v16\n\t"				\
Packit Service 82fcde
		  "    la %[R_IN],16(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    vupllh %%v18,%%v16\n\t"				\
Packit Service 82fcde
		  "    aghi %[R_INLEN],-16\n\t"				\
Packit Service 82fcde
		  /* Store 32 bytes to buf_out.  */			\
Packit Service 82fcde
		  "    vstm %%v17,%%v18,0(%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "    aghi %[R_OUTLEN],-32\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],32(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_INLEN],16,2f\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_OUTLEN],32,2f\n\t"			\
Packit Service 82fcde
		  "    j 1b\n\t"					\
Packit Service 82fcde
		  /* Setup to check for ch >= 0xd800 && ch <= 0xdfff. (v30, v31)  */ \
Packit Service 82fcde
		  "9:  .short 0xd800,0xdfff,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \
Packit Service 82fcde
		  "    .short 0xa000,0xc000,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \
Packit Service 82fcde
		  /* At least one uint16_t is in range of surrogates.	\
Packit Service 82fcde
		     Store the preceding chars.  */			\
Packit Service 82fcde
		  "10: vlgvb %[R_TMP],%%v19,7\n\t"			\
Packit Service 82fcde
		  "    vuplhh %%v17,%%v16\n\t"				\
Packit Service 82fcde
		  "    sllg %[R_TMP3],%[R_TMP],1\n\t" /* Number of out bytes.  */ \
Packit Service 82fcde
		  "    ahik %[R_TMP2],%[R_TMP3],-1\n\t" /* Highest index to store.  */ \
Packit Service 82fcde
		  "    jl 12f\n\t"					\
Packit Service 82fcde
		  "    vstl %%v17,%[R_TMP2],0(%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "    vupllh %%v18,%%v16\n\t"				\
Packit Service 82fcde
		  "    ahi %[R_TMP2],-16\n\t"				\
Packit Service 82fcde
		  "    jl 11f\n\t"					\
Packit Service 82fcde
		  "    vstl %%v18,%[R_TMP2],16(%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "11: \n\t" /* Update pointers.  */			\
Packit Service 82fcde
		  "    la %[R_IN],0(%[R_TMP],%[R_IN])\n\t"		\
Packit Service 82fcde
		  "    slgr %[R_INLEN],%[R_TMP]\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],0(%[R_TMP3],%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "    slgr %[R_OUTLEN],%[R_TMP3]\n\t"			\
Packit Service 82fcde
		  /* Calculate remaining uint16_t values in loaded vrs.  */ \
Packit Service 82fcde
		  "12: lghi %[R_TMP2],16\n\t"				\
Packit Service 82fcde
		  "    slgr %[R_TMP2],%[R_TMP]\n\t"			\
Packit Service 82fcde
		  "    srl %[R_TMP2],1\n\t"				\
Packit Service 82fcde
		  "    llh %[R_TMP],0(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    aghi %[R_OUTLEN],-4\n\t"				\
Packit Service 82fcde
		  "    j 16f\n\t"					\
Packit Service 82fcde
		  /* Handle remaining bytes.  */			\
Packit Service 82fcde
		  "2:  \n\t"						\
Packit Service 82fcde
		  /* Zero, one or more bytes available?  */		\
Packit Service 82fcde
		  "    clgfi %[R_INLEN],1\n\t"				\
Packit Service 82fcde
		  "    je 97f\n\t" /* Only one byte available.  */	\
Packit Service 82fcde
		  "    jl 99f\n\t" /* End if no bytes available.  */	\
Packit Service 82fcde
		  /* Calculate remaining uint16_t values in inptr.  */	\
Packit Service 82fcde
		  "    srlg %[R_TMP2],%[R_INLEN],1\n\t"			\
Packit Service 82fcde
		  /* Handle remaining uint16_t values.  */		\
Packit Service 82fcde
		  "13: llh %[R_TMP],0(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    slgfi %[R_OUTLEN],4\n\t"				\
Packit Service 82fcde
		  "    jl 96f \n\t"					\
Packit Service 82fcde
		  "    clfi %[R_TMP],0xd800\n\t"			\
Packit Service 82fcde
		  "    jhe 15f\n\t"					\
Packit Service 82fcde
		  "14: st %[R_TMP],0(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    la %[R_IN],2(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    aghi %[R_INLEN],-2\n\t"				\
Packit Service 82fcde
		  "    la %[R_OUT],4(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    brctg %[R_TMP2],13b\n\t"				\
Packit Service 82fcde
		  "    j 0b\n\t" /* Switch to vx-loop.  */		\
Packit Service 82fcde
		  /* Handle UTF-16 surrogate pair.  */			\
Packit Service 82fcde
		  "15: clfi %[R_TMP],0xdfff\n\t"			\
Packit Service 82fcde
		  "    jh 14b\n\t" /* Jump away if ch > 0xdfff.  */	\
Packit Service 82fcde
		  "16: clfi %[R_TMP],0xdc00\n\t"			\
Packit Service 82fcde
		  "    jhe 98f\n\t" /* Jump away in case of low-surrogate.  */ \
Packit Service 82fcde
		  "    slgfi %[R_INLEN],4\n\t"				\
Packit Service 82fcde
		  "    jl 97f\n\t" /* Big enough input?  */		\
Packit Service 82fcde
		  "    llh %[R_TMP3],2(%[R_IN])\n\t" /* Load low surrogate.  */ \
Packit Service 82fcde
		  "    slfi %[R_TMP],0xd7c0\n\t"			\
Packit Service 82fcde
		  "    sll %[R_TMP],10\n\t"				\
Packit Service 82fcde
		  "    risbgn %[R_TMP],%[R_TMP3],54,63,0\n\t" /* Insert klmnopqrst.  */ \
Packit Service 82fcde
		  "    nilf %[R_TMP3],0xfc00\n\t"			\
Packit Service 82fcde
		  "    clfi %[R_TMP3],0xdc00\n\t" /* Check if it starts with 0xdc00.  */ \
Packit Service 82fcde
		  "    jne 98f\n\t"					\
Packit Service 82fcde
		  "    st %[R_TMP],0(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    la %[R_IN],4(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],4(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    aghi %[R_TMP2],-2\n\t"				\
Packit Service 82fcde
		  "    jh 13b\n\t" /* Handle remaining uint16_t values.  */ \
Packit Service 82fcde
		  "    j 0b\n\t" /* Switch to vx-loop.  */		\
Packit Service 82fcde
		  "96: \n\t" /* Return full output.  */			\
Packit Service 82fcde
		  "    lghi %[R_RES],%[RES_OUT_FULL]\n\t"		\
Packit Service 82fcde
		  "    j 99f\n\t"					\
Packit Service 82fcde
		  "97: \n\t" /* Return incomplete input.  */		\
Packit Service 82fcde
		  "    lghi %[R_RES],%[RES_IN_FULL]\n\t"		\
Packit Service 82fcde
		  "    j 99f\n\t"					\
Packit Service 82fcde
		  "98:\n\t" /* Return Illegal character.  */		\
Packit Service 82fcde
		  "    lghi %[R_RES],%[RES_IN_ILL]\n\t"			\
Packit Service 82fcde
		  "99:\n\t"						\
Packit Service 82fcde
		  ".machine pop"					\
Packit Service 82fcde
		  : /* outputs */ [R_IN] "+a" (inptr)			\
Packit Service 82fcde
		    , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (outptr)	\
Packit Service 82fcde
		    , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp)	\
Packit Service 82fcde
		    , [R_TMP2] "=d" (tmp2), [R_TMP3] "=a" (tmp3)	\
Packit Service 82fcde
		    , [R_RES] "+d" (result)				\
Packit Service 82fcde
		  : /* inputs */					\
Packit Service 82fcde
		    [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT)		\
Packit Service 82fcde
		    , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT)		\
Packit Service 82fcde
		    , [RES_IN_FULL] "i" (__GCONV_INCOMPLETE_INPUT)	\
Packit Service 82fcde
		  : /* clobber list */ "memory", "cc"			\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17")	\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19")	\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v30") ASM_CLOBBER_VR ("v31")	\
Packit Service 82fcde
		  );							\
Packit Service 82fcde
    if (__glibc_likely (inptr == inend)					\
Packit Service 82fcde
	|| result != __GCONV_ILLEGAL_INPUT)				\
Packit Service 82fcde
      break;								\
Packit Service 82fcde
									\
Packit Service 82fcde
    STANDARD_FROM_LOOP_ERR_HANDLER (2);					\
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
/* Generate loop-function with hardware vector instructions.  */
Packit Service 82fcde
# define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
Packit Service 82fcde
# define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
Packit Service 82fcde
# define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
Packit Service 82fcde
# define FROM_LOOP_VX		__from_utf16_loop_vx
Packit Service 82fcde
# define LOOPFCT		FROM_LOOP_VX
Packit Service 82fcde
# define LOOP_NEED_FLAGS
Packit Service 82fcde
# define BODY			BODY_FROM_VX
Packit Service 82fcde
# include <iconv/loop.c>
Packit Service 82fcde
#else
Packit Service 82fcde
# define FROM_LOOP_VX		NULL
Packit Service 82fcde
#endif /* HAVE_FROM_VX != 1  */
Packit Service 82fcde
Packit Service 82fcde
#if HAVE_FROM_VX_CU == 1
Packit Service 82fcde
#define BODY_FROM_VX_CU							\
Packit Service 82fcde
  {									\
Packit Service 82fcde
    register const unsigned char* pInput asm ("8") = inptr;		\
Packit Service 82fcde
    register size_t inlen asm ("9") = inend - inptr;			\
Packit Service 82fcde
    register unsigned char* pOutput asm ("10") = outptr;		\
Packit Service 82fcde
    register size_t outlen asm ("11") = outend - outptr;		\
Packit Service 82fcde
    unsigned long tmp, tmp2, tmp3;					\
Packit Service 82fcde
    asm volatile (".machine push\n\t"					\
Packit Service 82fcde
		  ".machine \"z13\"\n\t"				\
Packit Service 82fcde
		  ".machinemode \"zarch_nohighgprs\"\n\t"		\
Packit Service 82fcde
		  /* Setup to check for surrogates.  */			\
Packit Service 82fcde
		  "    larl %[R_TMP],9f\n\t"				\
Packit Service 82fcde
		  "    vlm %%v30,%%v31,0(%[R_TMP])\n\t"			\
Packit Service 82fcde
		  CONVERT_32BIT_SIZE_T ([R_INLEN])			\
Packit Service 82fcde
		  CONVERT_32BIT_SIZE_T ([R_OUTLEN])			\
Packit Service 82fcde
		  /* Loop which handles UTF-16 chars <0xd800, >0xdfff.  */ \
Packit Service 82fcde
		  "0:  clgijl %[R_INLEN],16,20f\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_OUTLEN],32,20f\n\t"			\
Packit Service 82fcde
		  "1:  vl %%v16,0(%[R_IN])\n\t"				\
Packit Service 82fcde
		  /* Check for surrogate chars.  */			\
Packit Service 82fcde
		  "    vstrchs %%v19,%%v16,%%v30,%%v31\n\t"		\
Packit Service 82fcde
		  "    jno 10f\n\t"					\
Packit Service 82fcde
		  /* Enlarge to UTF-32.  */				\
Packit Service 82fcde
		  "    vuplhh %%v17,%%v16\n\t"				\
Packit Service 82fcde
		  "    la %[R_IN],16(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    vupllh %%v18,%%v16\n\t"				\
Packit Service 82fcde
		  "    aghi %[R_INLEN],-16\n\t"				\
Packit Service 82fcde
		  /* Store 32 bytes to buf_out.  */			\
Packit Service 82fcde
		  "    vstm %%v17,%%v18,0(%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "    aghi %[R_OUTLEN],-32\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],32(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_INLEN],16,20f\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_OUTLEN],32,20f\n\t"			\
Packit Service 82fcde
		  "    j 1b\n\t"					\
Packit Service 82fcde
		  /* Setup to check for ch >= 0xd800 && ch <= 0xdfff. (v30, v31)  */ \
Packit Service 82fcde
		  "9:  .short 0xd800,0xdfff,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \
Packit Service 82fcde
		  "    .short 0xa000,0xc000,0x0,0x0,0x0,0x0,0x0,0x0\n\t" \
Packit Service 82fcde
		  /* At least one uint16_t is in range of surrogates.	\
Packit Service 82fcde
		     Store the preceding chars.  */			\
Packit Service 82fcde
		  "10: vlgvb %[R_TMP],%%v19,7\n\t"			\
Packit Service 82fcde
		  "    vuplhh %%v17,%%v16\n\t"				\
Packit Service 82fcde
		  "    sllg %[R_TMP3],%[R_TMP],1\n\t" /* Number of out bytes.  */ \
Packit Service 82fcde
		  "    ahik %[R_TMP2],%[R_TMP3],-1\n\t" /* Highest index to store.  */ \
Packit Service 82fcde
		  "    jl 20f\n\t"					\
Packit Service 82fcde
		  "    vstl %%v17,%[R_TMP2],0(%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "    vupllh %%v18,%%v16\n\t"				\
Packit Service 82fcde
		  "    ahi %[R_TMP2],-16\n\t"				\
Packit Service 82fcde
		  "    jl 11f\n\t"					\
Packit Service 82fcde
		  "    vstl %%v18,%[R_TMP2],16(%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "11: \n\t" /* Update pointers.  */			\
Packit Service 82fcde
		  "    la %[R_IN],0(%[R_TMP],%[R_IN])\n\t"		\
Packit Service 82fcde
		  "    slgr %[R_INLEN],%[R_TMP]\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],0(%[R_TMP3],%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "    slgr %[R_OUTLEN],%[R_TMP3]\n\t"			\
Packit Service 82fcde
		  /* Handles UTF16 surrogates with convert instruction.  */ \
Packit Service 82fcde
		  "20: cu24 %[R_OUT],%[R_IN],1\n\t"			\
Packit Service 82fcde
		  "    jo 0b\n\t" /* Try vector implemenation again.  */ \
Packit Service 82fcde
		  "    lochil %[R_RES],%[RES_OUT_FULL]\n\t" /* cc == 1.  */ \
Packit Service 82fcde
		  "    lochih %[R_RES],%[RES_IN_ILL]\n\t" /* cc == 2.  */ \
Packit Service 82fcde
		  ".machine pop"					\
Packit Service 82fcde
		  : /* outputs */ [R_IN] "+a" (pInput)			\
Packit Service 82fcde
		    , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (pOutput)	\
Packit Service 82fcde
		    , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp)	\
Packit Service 82fcde
		    , [R_TMP2] "=d" (tmp2), [R_TMP3] "=a" (tmp3)	\
Packit Service 82fcde
		    , [R_RES] "+d" (result)				\
Packit Service 82fcde
		  : /* inputs */					\
Packit Service 82fcde
		    [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT)		\
Packit Service 82fcde
		    , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT)		\
Packit Service 82fcde
		  : /* clobber list */ "memory", "cc"			\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17")	\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19")	\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v30") ASM_CLOBBER_VR ("v31")	\
Packit Service 82fcde
		  );							\
Packit Service 82fcde
    inptr = pInput;							\
Packit Service 82fcde
    outptr = pOutput;							\
Packit Service 82fcde
									\
Packit Service 82fcde
    if (__glibc_likely (inlen == 0)					\
Packit Service 82fcde
	|| result == __GCONV_FULL_OUTPUT)				\
Packit Service 82fcde
      break;								\
Packit Service 82fcde
    if (inlen == 1)							\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	/* Input does not contain a complete utf16 character.  */	\
Packit Service 82fcde
	result = __GCONV_INCOMPLETE_INPUT;				\
Packit Service 82fcde
	break;								\
Packit Service 82fcde
      }									\
Packit Service 82fcde
    else if (result != __GCONV_ILLEGAL_INPUT)				\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	/* Input is >= 2 and < 4 bytes (as cu24 would have processed	\
Packit Service 82fcde
	   a possible next utf16 character) and not illegal.		\
Packit Service 82fcde
	   => we have a single high surrogate at end of input.  */	\
Packit Service 82fcde
	result = __GCONV_INCOMPLETE_INPUT;				\
Packit Service 82fcde
	break;								\
Packit Service 82fcde
      }									\
Packit Service 82fcde
									\
Packit Service 82fcde
    STANDARD_FROM_LOOP_ERR_HANDLER (2);					\
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
/* Generate loop-function with hardware vector and utf-convert instructions.  */
Packit Service 82fcde
# define MIN_NEEDED_INPUT	MIN_NEEDED_FROM
Packit Service 82fcde
# define MAX_NEEDED_INPUT	MAX_NEEDED_FROM
Packit Service 82fcde
# define MIN_NEEDED_OUTPUT	MIN_NEEDED_TO
Packit Service 82fcde
# define FROM_LOOP_VX_CU	__from_utf16_loop_vx_cu
Packit Service 82fcde
# define LOOPFCT		FROM_LOOP_VX_CU
Packit Service 82fcde
# define LOOP_NEED_FLAGS
Packit Service 82fcde
# define BODY			BODY_FROM_VX_CU
Packit Service 82fcde
# include <iconv/loop.c>
Packit Service 82fcde
#else
Packit Service 82fcde
# define FROM_LOOP_VX_CU	NULL
Packit Service 82fcde
#endif /* HAVE_FROM_VX_CU != 1  */
Packit Service 82fcde
Packit Service 82fcde
/* Conversion from UTF-32 internal/BE to UTF-16.  */
Packit Service 82fcde
Packit Service 82fcde
#if HAVE_TO_C == 1
Packit Service 82fcde
/* The software routine is copied from utf-16.c (minus bytes
Packit Service 82fcde
   swapping).  */
Packit Service 82fcde
# define BODY_TO_C							\
Packit Service 82fcde
  {									\
Packit Service 82fcde
    uint32_t c = get32 (inptr);						\
Packit Service 82fcde
									\
Packit Service 82fcde
    if (__builtin_expect (c <= 0xd7ff, 1)				\
Packit Service 82fcde
	|| (c > 0xdfff && c <= 0xffff))					\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	/* Two UTF-16 chars.  */					\
Packit Service 82fcde
	put16 (outptr, c);						\
Packit Service 82fcde
      }									\
Packit Service 82fcde
    else if (__builtin_expect (c >= 0x10000, 1)				\
Packit Service 82fcde
	     && __builtin_expect (c <= 0x10ffff, 1))			\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	/* Four UTF-16 chars.  */					\
Packit Service 82fcde
	uint16_t zabcd = ((c & 0x1f0000) >> 16) - 1;			\
Packit Service 82fcde
	uint16_t out;							\
Packit Service 82fcde
									\
Packit Service 82fcde
	/* Generate a surrogate character.  */				\
Packit Service 82fcde
	if (__glibc_unlikely (outptr + 4 > outend))			\
Packit Service 82fcde
	  {								\
Packit Service 82fcde
	    /* Overflow in the output buffer.  */			\
Packit Service 82fcde
	    result = __GCONV_FULL_OUTPUT;				\
Packit Service 82fcde
	    break;							\
Packit Service 82fcde
	  }								\
Packit Service 82fcde
									\
Packit Service 82fcde
	out = 0xd800;							\
Packit Service 82fcde
	out |= (zabcd & 0xff) << 6;					\
Packit Service 82fcde
	out |= (c >> 10) & 0x3f;					\
Packit Service 82fcde
	put16 (outptr, out);						\
Packit Service 82fcde
	outptr += 2;							\
Packit Service 82fcde
									\
Packit Service 82fcde
	out = 0xdc00;							\
Packit Service 82fcde
	out |= c & 0x3ff;						\
Packit Service 82fcde
	put16 (outptr, out);						\
Packit Service 82fcde
      }									\
Packit Service 82fcde
    else								\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	STANDARD_TO_LOOP_ERR_HANDLER (4);				\
Packit Service 82fcde
      }									\
Packit Service 82fcde
    outptr += 2;							\
Packit Service 82fcde
    inptr += 4;								\
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
/* Generate loop-function with software routing.  */
Packit Service 82fcde
# define MIN_NEEDED_INPUT	MIN_NEEDED_TO
Packit Service 82fcde
# define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
Packit Service 82fcde
# define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
Packit Service 82fcde
# define TO_LOOP_C		__to_utf16_loop_c
Packit Service 82fcde
# define LOOPFCT		TO_LOOP_C
Packit Service 82fcde
# define LOOP_NEED_FLAGS
Packit Service 82fcde
# define BODY			BODY_TO_C
Packit Service 82fcde
# include <iconv/loop.c>
Packit Service 82fcde
#else
Packit Service 82fcde
# define TO_LOOP_C		NULL
Packit Service 82fcde
#endif /* HAVE_TO_C != 1  */
Packit Service 82fcde
Packit Service 82fcde
#if HAVE_TO_VX == 1
Packit Service 82fcde
# define BODY_TO_VX							\
Packit Service 82fcde
  {									\
Packit Service 82fcde
    size_t inlen = inend - inptr;					\
Packit Service 82fcde
    size_t outlen = outend - outptr;					\
Packit Service 82fcde
    unsigned long tmp, tmp2, tmp3;					\
Packit Service 82fcde
    asm volatile (".machine push\n\t"					\
Packit Service 82fcde
		  ".machine \"z13\"\n\t"				\
Packit Service 82fcde
		  ".machinemode \"zarch_nohighgprs\"\n\t"		\
Packit Service 82fcde
		  /* Setup to check for surrogates.  */			\
Packit Service 82fcde
		  "    larl %[R_TMP],9f\n\t"				\
Packit Service 82fcde
		  "    vlm %%v30,%%v31,0(%[R_TMP])\n\t"			\
Packit Service 82fcde
		  CONVERT_32BIT_SIZE_T ([R_INLEN])			\
Packit Service 82fcde
		  CONVERT_32BIT_SIZE_T ([R_OUTLEN])			\
Packit Service 82fcde
		  /* Loop which handles UTF-32 chars			\
Packit Service 82fcde
		     ch < 0xd800 || (ch > 0xdfff && ch < 0x10000).  */	\
Packit Service 82fcde
		  "0:  clgijl %[R_INLEN],32,2f\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_OUTLEN],16,2f\n\t"			\
Packit Service 82fcde
		  "1:  vlm %%v16,%%v17,0(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    lghi %[R_TMP2],0\n\t"				\
Packit Service 82fcde
		  /* Shorten to UTF-16.  */				\
Packit Service 82fcde
		  "    vpkf %%v18,%%v16,%%v17\n\t"			\
Packit Service 82fcde
		  /* Check for surrogate chars.  */			\
Packit Service 82fcde
		  "    vstrcfs %%v19,%%v16,%%v30,%%v31\n\t"		\
Packit Service 82fcde
		  "    jno 10f\n\t"					\
Packit Service 82fcde
		  "    vstrcfs %%v19,%%v17,%%v30,%%v31\n\t"		\
Packit Service 82fcde
		  "    jno 11f\n\t"					\
Packit Service 82fcde
		  /* Store 16 bytes to buf_out.  */			\
Packit Service 82fcde
		  "    vst %%v18,0(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    la %[R_IN],32(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    aghi %[R_INLEN],-32\n\t"				\
Packit Service 82fcde
		  "    aghi %[R_OUTLEN],-16\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],16(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_INLEN],32,2f\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_OUTLEN],16,2f\n\t"			\
Packit Service 82fcde
		  "    j 1b\n\t"					\
Packit Service 82fcde
		  /* Calculate remaining uint32_t values in inptr.  */	\
Packit Service 82fcde
		  "2:  \n\t"						\
Packit Service 82fcde
		  "    clgije %[R_INLEN],0,99f\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_INLEN],4,92f\n\t"			\
Packit Service 82fcde
		  "    srlg %[R_TMP2],%[R_INLEN],2\n\t"			\
Packit Service 82fcde
		  "    j 20f\n\t"					\
Packit Service 82fcde
		  /* Setup to check for ch >= 0xd800 && ch <= 0xdfff	\
Packit Service 82fcde
		     and check for ch >= 0x10000. (v30, v31)  */	\
Packit Service 82fcde
		  "9:  .long 0xd800,0xdfff,0x10000,0x10000\n\t"		\
Packit Service 82fcde
		  "    .long 0xa0000000,0xc0000000, 0xa0000000,0xa0000000\n\t" \
Packit Service 82fcde
		  /* At least on UTF32 char is in range of surrogates.	\
Packit Service 82fcde
		     Store the preceding characters.  */		\
Packit Service 82fcde
		  "11: ahi %[R_TMP2],16\n\t"				\
Packit Service 82fcde
		  "10: vlgvb %[R_TMP],%%v19,7\n\t"			\
Packit Service 82fcde
		  "    agr %[R_TMP],%[R_TMP2]\n\t"			\
Packit Service 82fcde
		  "    srlg %[R_TMP3],%[R_TMP],1\n\t" /* Number of out bytes.  */ \
Packit Service 82fcde
		  "    ahik %[R_TMP2],%[R_TMP3],-1\n\t" /* Highest index to store.  */ \
Packit Service 82fcde
		  "    jl 12f\n\t"					\
Packit Service 82fcde
		  "    vstl %%v18,%[R_TMP2],0(%[R_OUT])\n\t"		\
Packit Service 82fcde
		  /* Update pointers.  */				\
Packit Service 82fcde
		  "    la %[R_IN],0(%[R_TMP],%[R_IN])\n\t"		\
Packit Service 82fcde
		  "    slgr %[R_INLEN],%[R_TMP]\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],0(%[R_TMP3],%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "    slgr %[R_OUTLEN],%[R_TMP3]\n\t"			\
Packit Service 82fcde
		  /* Calculate remaining uint32_t values in vrs.  */	\
Packit Service 82fcde
		  "12: lghi %[R_TMP2],8\n\t"				\
Packit Service 82fcde
		  "    srlg %[R_TMP3],%[R_TMP3],1\n\t"			\
Packit Service 82fcde
		  "    slgr %[R_TMP2],%[R_TMP3]\n\t"			\
Packit Service 82fcde
		  /* Handle remaining UTF-32 characters.  */		\
Packit Service 82fcde
		  "20: l %[R_TMP],0(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    aghi %[R_INLEN],-4\n\t"				\
Packit Service 82fcde
		  /* Test if ch is 2byte UTF-16 char. */		\
Packit Service 82fcde
		  "    clfi %[R_TMP],0xffff\n\t"			\
Packit Service 82fcde
		  "    jh 21f\n\t"					\
Packit Service 82fcde
		  /* Handle 2 byte UTF16 char.  */			\
Packit Service 82fcde
		  "    lgr %[R_TMP3],%[R_TMP]\n\t"			\
Packit Service 82fcde
		  "    nilf %[R_TMP],0xf800\n\t"			\
Packit Service 82fcde
		  "    clfi %[R_TMP],0xd800\n\t"			\
Packit Service 82fcde
		  "    je 91f\n\t" /* Do not accept UTF-16 surrogates.  */ \
Packit Service 82fcde
		  "    slgfi %[R_OUTLEN],2\n\t"				\
Packit Service 82fcde
		  "    jl 90f \n\t"					\
Packit Service 82fcde
		  "    sth %[R_TMP3],0(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    la %[R_IN],4(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],2(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    brctg %[R_TMP2],20b\n\t"				\
Packit Service 82fcde
		  "    j 0b\n\t" /* Switch to vx-loop.  */		\
Packit Service 82fcde
		  /* Test if ch is 4byte UTF-16 char. */		\
Packit Service 82fcde
		  "21: clfi %[R_TMP],0x10ffff\n\t"			\
Packit Service 82fcde
		  "    jh 91f\n\t" /* ch > 0x10ffff is not allowed!  */	\
Packit Service 82fcde
		  /* Handle 4 byte UTF16 char.  */			\
Packit Service 82fcde
		  "    slgfi %[R_OUTLEN],4\n\t"				\
Packit Service 82fcde
		  "    jl 90f \n\t"					\
Packit Service 82fcde
		  "    slfi %[R_TMP],0x10000\n\t" /* zabcd = uvwxy - 1.  */ \
Packit Service 82fcde
		  "    llilf %[R_TMP3],0xd800dc00\n\t"			\
Packit Service 82fcde
		  "    la %[R_IN],4(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    risbgn %[R_TMP3],%[R_TMP],38,47,6\n\t" /* High surrogate.  */ \
Packit Service 82fcde
		  "    risbgn %[R_TMP3],%[R_TMP],54,63,0\n\t" /* Low surrogate.  */ \
Packit Service 82fcde
		  "    st %[R_TMP3],0(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],4(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    brctg %[R_TMP2],20b\n\t"				\
Packit Service 82fcde
		  "    j 0b\n\t" /* Switch to vx-loop.  */		\
Packit Service 82fcde
		  "92: lghi %[R_RES],%[RES_IN_FULL]\n\t"		\
Packit Service 82fcde
		  "    j 99f\n\t"					\
Packit Service 82fcde
		  "91: lghi %[R_RES],%[RES_IN_ILL]\n\t"			\
Packit Service 82fcde
		  "    j 99f\n\t"					\
Packit Service 82fcde
		  "90: lghi %[R_RES],%[RES_OUT_FULL]\n\t"		\
Packit Service 82fcde
		  "99: \n\t"						\
Packit Service 82fcde
		  ".machine pop"					\
Packit Service 82fcde
		  : /* outputs */ [R_IN] "+a" (inptr)			\
Packit Service 82fcde
		    , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (outptr)	\
Packit Service 82fcde
		    , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp)	\
Packit Service 82fcde
		    , [R_TMP2] "=d" (tmp2), [R_TMP3] "=a" (tmp3)	\
Packit Service 82fcde
		    , [R_RES] "+d" (result)				\
Packit Service 82fcde
		  : /* inputs */					\
Packit Service 82fcde
		    [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT)		\
Packit Service 82fcde
		    , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT)		\
Packit Service 82fcde
		    , [RES_IN_FULL] "i" (__GCONV_INCOMPLETE_INPUT)	\
Packit Service 82fcde
		  : /* clobber list */ "memory", "cc"			\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17")	\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19")	\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v30") ASM_CLOBBER_VR ("v31")	\
Packit Service 82fcde
		  );							\
Packit Service 82fcde
    if (__glibc_likely (inptr == inend)					\
Packit Service 82fcde
	|| result != __GCONV_ILLEGAL_INPUT)				\
Packit Service 82fcde
      break;								\
Packit Service 82fcde
									\
Packit Service 82fcde
    STANDARD_TO_LOOP_ERR_HANDLER (4);					\
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
/* Generate loop-function with hardware vector instructions.  */
Packit Service 82fcde
# define MIN_NEEDED_INPUT	MIN_NEEDED_TO
Packit Service 82fcde
# define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
Packit Service 82fcde
# define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
Packit Service 82fcde
# define TO_LOOP_VX		__to_utf16_loop_vx
Packit Service 82fcde
# define LOOPFCT		TO_LOOP_VX
Packit Service 82fcde
# define LOOP_NEED_FLAGS
Packit Service 82fcde
# define BODY			BODY_TO_VX
Packit Service 82fcde
# include <iconv/loop.c>
Packit Service 82fcde
#else
Packit Service 82fcde
# define TO_LOOP_VX		NULL
Packit Service 82fcde
#endif /* HAVE_TO_VX != 1  */
Packit Service 82fcde
Packit Service 82fcde
#if HAVE_TO_VX_CU == 1
Packit Service 82fcde
#define BODY_TO_VX_CU							\
Packit Service 82fcde
  {									\
Packit Service 82fcde
    register const unsigned char* pInput asm ("8") = inptr;		\
Packit Service 82fcde
    register size_t inlen asm ("9") = inend - inptr;			\
Packit Service 82fcde
    register unsigned char* pOutput asm ("10") = outptr;		\
Packit Service 82fcde
    register size_t outlen asm ("11") = outend - outptr;		\
Packit Service 82fcde
    unsigned long tmp, tmp2, tmp3;					\
Packit Service 82fcde
    asm volatile (".machine push\n\t"					\
Packit Service 82fcde
		  ".machine \"z13\"\n\t"				\
Packit Service 82fcde
		  ".machinemode \"zarch_nohighgprs\"\n\t"		\
Packit Service 82fcde
		  /* Setup to check for surrogates.  */			\
Packit Service 82fcde
		  "    larl %[R_TMP],9f\n\t"				\
Packit Service 82fcde
		  "    vlm %%v30,%%v31,0(%[R_TMP])\n\t"			\
Packit Service 82fcde
		  CONVERT_32BIT_SIZE_T ([R_INLEN])			\
Packit Service 82fcde
		  CONVERT_32BIT_SIZE_T ([R_OUTLEN])			\
Packit Service 82fcde
		  /* Loop which handles UTF-32 chars			\
Packit Service 82fcde
		     ch < 0xd800 || (ch > 0xdfff && ch < 0x10000).  */	\
Packit Service 82fcde
		  "0:  clgijl %[R_INLEN],32,20f\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_OUTLEN],16,20f\n\t"			\
Packit Service 82fcde
		  "1:  vlm %%v16,%%v17,0(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    lghi %[R_TMP2],0\n\t"				\
Packit Service 82fcde
		  /* Shorten to UTF-16.  */				\
Packit Service 82fcde
		  "    vpkf %%v18,%%v16,%%v17\n\t"			\
Packit Service 82fcde
		  /* Check for surrogate chars.  */			\
Packit Service 82fcde
		  "    vstrcfs %%v19,%%v16,%%v30,%%v31\n\t"		\
Packit Service 82fcde
		  "    jno 10f\n\t"					\
Packit Service 82fcde
		  "    vstrcfs %%v19,%%v17,%%v30,%%v31\n\t"		\
Packit Service 82fcde
		  "    jno 11f\n\t"					\
Packit Service 82fcde
		  /* Store 16 bytes to buf_out.  */			\
Packit Service 82fcde
		  "    vst %%v18,0(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    la %[R_IN],32(%[R_IN])\n\t"			\
Packit Service 82fcde
		  "    aghi %[R_INLEN],-32\n\t"				\
Packit Service 82fcde
		  "    aghi %[R_OUTLEN],-16\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],16(%[R_OUT])\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_INLEN],32,20f\n\t"			\
Packit Service 82fcde
		  "    clgijl %[R_OUTLEN],16,20f\n\t"			\
Packit Service 82fcde
		  "    j 1b\n\t"					\
Packit Service 82fcde
		  /* Setup to check for ch >= 0xd800 && ch <= 0xdfff	\
Packit Service 82fcde
		     and check for ch >= 0x10000. (v30, v31)  */	\
Packit Service 82fcde
		  "9:  .long 0xd800,0xdfff,0x10000,0x10000\n\t"		\
Packit Service 82fcde
		  "    .long 0xa0000000,0xc0000000, 0xa0000000,0xa0000000\n\t" \
Packit Service 82fcde
		  /* At least one UTF32 char is in range of surrogates.	\
Packit Service 82fcde
		     Store the preceding characters.  */		\
Packit Service 82fcde
		  "11: ahi %[R_TMP2],16\n\t"				\
Packit Service 82fcde
		  "10: vlgvb %[R_TMP],%%v19,7\n\t"			\
Packit Service 82fcde
		  "    agr %[R_TMP],%[R_TMP2]\n\t"			\
Packit Service 82fcde
		  "    srlg %[R_TMP3],%[R_TMP],1\n\t" /* Number of out bytes.  */ \
Packit Service 82fcde
		  "    ahik %[R_TMP2],%[R_TMP3],-1\n\t" /* Highest index to store.  */ \
Packit Service 82fcde
		  "    jl 20f\n\t"					\
Packit Service 82fcde
		  "    vstl %%v18,%[R_TMP2],0(%[R_OUT])\n\t"		\
Packit Service 82fcde
		  /* Update pointers.  */				\
Packit Service 82fcde
		  "    la %[R_IN],0(%[R_TMP],%[R_IN])\n\t"		\
Packit Service 82fcde
		  "    slgr %[R_INLEN],%[R_TMP]\n\t"			\
Packit Service 82fcde
		  "    la %[R_OUT],0(%[R_TMP3],%[R_OUT])\n\t"		\
Packit Service 82fcde
		  "    slgr %[R_OUTLEN],%[R_TMP3]\n\t"			\
Packit Service 82fcde
		  /* Handles UTF16 surrogates with convert instruction.  */ \
Packit Service 82fcde
		  "20: cu42 %[R_OUT],%[R_IN]\n\t"			\
Packit Service 82fcde
		  "    jo 0b\n\t" /* Try vector implemenation again.  */ \
Packit Service 82fcde
		  "    lochil %[R_RES],%[RES_OUT_FULL]\n\t" /* cc == 1.  */ \
Packit Service 82fcde
		  "    lochih %[R_RES],%[RES_IN_ILL]\n\t" /* cc == 2.  */ \
Packit Service 82fcde
		  ".machine pop"					\
Packit Service 82fcde
		  : /* outputs */ [R_IN] "+a" (pInput)			\
Packit Service 82fcde
		    , [R_INLEN] "+d" (inlen), [R_OUT] "+a" (pOutput)	\
Packit Service 82fcde
		    , [R_OUTLEN] "+d" (outlen), [R_TMP] "=a" (tmp)	\
Packit Service 82fcde
		    , [R_TMP2] "=d" (tmp2), [R_TMP3] "=a" (tmp3)	\
Packit Service 82fcde
		    , [R_RES] "+d" (result)				\
Packit Service 82fcde
		  : /* inputs */					\
Packit Service 82fcde
		    [RES_OUT_FULL] "i" (__GCONV_FULL_OUTPUT)		\
Packit Service 82fcde
		    , [RES_IN_ILL] "i" (__GCONV_ILLEGAL_INPUT)		\
Packit Service 82fcde
		  : /* clobber list */ "memory", "cc"			\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v16") ASM_CLOBBER_VR ("v17")	\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v18") ASM_CLOBBER_VR ("v19")	\
Packit Service 82fcde
		    ASM_CLOBBER_VR ("v30") ASM_CLOBBER_VR ("v31")	\
Packit Service 82fcde
		  );							\
Packit Service 82fcde
    inptr = pInput;							\
Packit Service 82fcde
    outptr = pOutput;							\
Packit Service 82fcde
									\
Packit Service 82fcde
    if (__glibc_likely (inlen == 0)					\
Packit Service 82fcde
	|| result == __GCONV_FULL_OUTPUT)				\
Packit Service 82fcde
      break;								\
Packit Service 82fcde
    if (inlen < 4)							\
Packit Service 82fcde
      {									\
Packit Service 82fcde
	result = __GCONV_INCOMPLETE_INPUT;				\
Packit Service 82fcde
	break;								\
Packit Service 82fcde
      }									\
Packit Service 82fcde
									\
Packit Service 82fcde
    STANDARD_TO_LOOP_ERR_HANDLER (4);					\
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
/* Generate loop-function with hardware vector and utf-convert instructions.  */
Packit Service 82fcde
# define MIN_NEEDED_INPUT	MIN_NEEDED_TO
Packit Service 82fcde
# define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
Packit Service 82fcde
# define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
Packit Service 82fcde
# define TO_LOOP_VX_CU		__to_utf16_loop_vx_cu
Packit Service 82fcde
# define LOOPFCT		TO_LOOP_VX_CU
Packit Service 82fcde
# define LOOP_NEED_FLAGS
Packit Service 82fcde
# define BODY			BODY_TO_VX_CU
Packit Service 82fcde
# include <iconv/loop.c>
Packit Service 82fcde
#else
Packit Service 82fcde
# define TO_LOOP_VX_CU		NULL
Packit Service 82fcde
#endif /* HAVE_TO_VX_CU != 1  */
Packit Service 82fcde
Packit Service 82fcde
/* This file also exists in sysdeps/s390/multiarch/ which
Packit Service 82fcde
   generates ifunc resolvers for FROM/TO_LOOP functions
Packit Service 82fcde
   and includes iconv/skeleton.c afterwards.  */
Packit Service 82fcde
#if ! defined USE_MULTIARCH
Packit Service 82fcde
# include <iconv/skeleton.c>
Packit Service 82fcde
#endif