iconv: Remove _STRING_ARCH_unaligned usage

Use put/get macros __builtin_bswap32 instead.  It allows to remove
the unaligned routines, the compiler will generate unaligned access
if the ABI allows it.

Checked on x86_64-linux-gnu and i686-linux-gnu.

Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
This commit is contained in:
Adhemerval Zanella 2023-02-10 16:37:36 -03:00
parent 5729e0e9af
commit 3e20ddade3
3 changed files with 59 additions and 407 deletions

View file

@ -86,13 +86,15 @@ internal_ucs4_loop (struct __gconv_step *step,
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
/* Sigh, we have to do some real work. */ /* Sigh, we have to do some real work. */
size_t cnt; size_t cnt;
uint32_t *outptr32 = (uint32_t *) outptr;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
*outptr32++ = bswap_32 (*(const uint32_t *) inptr); {
uint32_t val = get32 (inptr);
put32 (outptr, __builtin_bswap32 (val));
}
*inptrp = inptr; *inptrp = inptr;
*outptrp = (unsigned char *) outptr32; *outptrp = outptr;
#elif __BYTE_ORDER == __BIG_ENDIAN #elif __BYTE_ORDER == __BIG_ENDIAN
/* Simply copy the data. */ /* Simply copy the data. */
*inptrp = inptr + n_convert * 4; *inptrp = inptr + n_convert * 4;
@ -112,56 +114,6 @@ internal_ucs4_loop (struct __gconv_step *step,
return result; return result;
} }
#if !_STRING_ARCH_unaligned
static inline int
__attribute ((always_inline))
internal_ucs4_loop_unaligned (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
# if __BYTE_ORDER == __LITTLE_ENDIAN
/* Sigh, we have to do some real work. */
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
{
outptr[0] = inptr[3];
outptr[1] = inptr[2];
outptr[2] = inptr[1];
outptr[3] = inptr[0];
}
*inptrp = inptr;
*outptrp = outptr;
# elif __BYTE_ORDER == __BIG_ENDIAN
/* Simply copy the data. */
*inptrp = inptr + n_convert * 4;
*outptrp = __mempcpy (outptr, inptr, n_convert * 4);
# else
# error "This endianess is not supported."
# endif
/* Determine the status. */
if (*inptrp == inend)
result = __GCONV_EMPTY_INPUT;
else if (*outptrp + 4 > outend)
result = __GCONV_FULL_OUTPUT;
else
result = __GCONV_INCOMPLETE_INPUT;
return result;
}
#endif
static inline int static inline int
__attribute ((always_inline)) __attribute ((always_inline))
@ -242,12 +194,9 @@ ucs4_internal_loop (struct __gconv_step *step,
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{ {
uint32_t inval; uint32_t inval = get32 (inptr);
#if __BYTE_ORDER == __LITTLE_ENDIAN #if __BYTE_ORDER == __LITTLE_ENDIAN
inval = bswap_32 (*(const uint32_t *) inptr); inval = __builtin_bswap32 (inval);
#else
inval = *(const uint32_t *) inptr;
#endif #endif
if (__glibc_unlikely (inval > 0x7fffffff)) if (__glibc_unlikely (inval > 0x7fffffff))
@ -272,7 +221,7 @@ ucs4_internal_loop (struct __gconv_step *step,
return __GCONV_ILLEGAL_INPUT; return __GCONV_ILLEGAL_INPUT;
} }
*((uint32_t *) outptr) = inval; put32 (outptr, inval);
outptr += sizeof (uint32_t); outptr += sizeof (uint32_t);
} }
@ -290,75 +239,6 @@ ucs4_internal_loop (struct __gconv_step *step,
return result; return result;
} }
#if !_STRING_ARCH_unaligned
static inline int
__attribute ((always_inline))
ucs4_internal_loop_unaligned (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
int result;
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
if (__glibc_unlikely (inptr[0] > 0x80))
{
/* The value is too large. We don't try transliteration here since
this is not an error because of the lack of possibilities to
represent the result. This is a genuine bug in the input since
UCS4 does not allow such values. */
if (irreversible == NULL)
/* We are transliterating, don't try to correct anything. */
return __GCONV_ILLEGAL_INPUT;
if (flags & __GCONV_IGNORE_ERRORS)
{
/* Just ignore this character. */
++*irreversible;
continue;
}
*inptrp = inptr;
*outptrp = outptr;
return __GCONV_ILLEGAL_INPUT;
}
# if __BYTE_ORDER == __LITTLE_ENDIAN
outptr[3] = inptr[0];
outptr[2] = inptr[1];
outptr[1] = inptr[2];
outptr[0] = inptr[3];
# else
outptr[0] = inptr[0];
outptr[1] = inptr[1];
outptr[2] = inptr[2];
outptr[3] = inptr[3];
# endif
outptr += 4;
}
*inptrp = inptr;
*outptrp = outptr;
/* Determine the status. */
if (*inptrp == inend)
result = __GCONV_EMPTY_INPUT;
else if (*outptrp + 4 > outend)
result = __GCONV_FULL_OUTPUT;
else
result = __GCONV_INCOMPLETE_INPUT;
return result;
}
#endif
static inline int static inline int
__attribute ((always_inline)) __attribute ((always_inline))
@ -453,11 +333,12 @@ internal_ucs4le_loop (struct __gconv_step *step,
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
/* Sigh, we have to do some real work. */ /* Sigh, we have to do some real work. */
size_t cnt; size_t cnt;
uint32_t *outptr32 = (uint32_t *) outptr;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
*outptr32++ = bswap_32 (*(const uint32_t *) inptr); {
outptr = (unsigned char *) outptr32; uint32_t val = get32 (inptr);
put32 (outptr, __builtin_bswap32 (val));
}
*inptrp = inptr; *inptrp = inptr;
*outptrp = outptr; *outptrp = outptr;
@ -480,59 +361,6 @@ internal_ucs4le_loop (struct __gconv_step *step,
return result; return result;
} }
#if !_STRING_ARCH_unaligned
static inline int
__attribute ((always_inline))
internal_ucs4le_loop_unaligned (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
# if __BYTE_ORDER == __BIG_ENDIAN
/* Sigh, we have to do some real work. */
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
{
outptr[0] = inptr[3];
outptr[1] = inptr[2];
outptr[2] = inptr[1];
outptr[3] = inptr[0];
}
*inptrp = inptr;
*outptrp = outptr;
# elif __BYTE_ORDER == __LITTLE_ENDIAN
/* Simply copy the data. */
*inptrp = inptr + n_convert * 4;
*outptrp = __mempcpy (outptr, inptr, n_convert * 4);
# else
# error "This endianess is not supported."
# endif
/* Determine the status. */
if (*inptrp == inend)
result = __GCONV_EMPTY_INPUT;
else if (*inptrp + 4 > inend)
result = __GCONV_INCOMPLETE_INPUT;
else
{
assert (*outptrp + 4 > outend);
result = __GCONV_FULL_OUTPUT;
}
return result;
}
#endif
static inline int static inline int
__attribute ((always_inline)) __attribute ((always_inline))
@ -612,12 +440,9 @@ ucs4le_internal_loop (struct __gconv_step *step,
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{ {
uint32_t inval; uint32_t inval = get32 (inptr);
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
inval = bswap_32 (*(const uint32_t *) inptr); inval = __builtin_bswap32 (inval);
#else
inval = *(const uint32_t *) inptr;
#endif #endif
if (__glibc_unlikely (inval > 0x7fffffff)) if (__glibc_unlikely (inval > 0x7fffffff))
@ -642,7 +467,7 @@ ucs4le_internal_loop (struct __gconv_step *step,
return __GCONV_ILLEGAL_INPUT; return __GCONV_ILLEGAL_INPUT;
} }
*((uint32_t *) outptr) = inval; put32 (outptr, inval);
outptr += sizeof (uint32_t); outptr += sizeof (uint32_t);
} }
@ -663,79 +488,6 @@ ucs4le_internal_loop (struct __gconv_step *step,
return result; return result;
} }
#if !_STRING_ARCH_unaligned
static inline int
__attribute ((always_inline))
ucs4le_internal_loop_unaligned (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
int result;
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
if (__glibc_unlikely (inptr[3] > 0x80))
{
/* The value is too large. We don't try transliteration here since
this is not an error because of the lack of possibilities to
represent the result. This is a genuine bug in the input since
UCS4 does not allow such values. */
if (irreversible == NULL)
/* We are transliterating, don't try to correct anything. */
return __GCONV_ILLEGAL_INPUT;
if (flags & __GCONV_IGNORE_ERRORS)
{
/* Just ignore this character. */
++*irreversible;
continue;
}
*inptrp = inptr;
*outptrp = outptr;
return __GCONV_ILLEGAL_INPUT;
}
# if __BYTE_ORDER == __BIG_ENDIAN
outptr[3] = inptr[0];
outptr[2] = inptr[1];
outptr[1] = inptr[2];
outptr[0] = inptr[3];
# else
outptr[0] = inptr[0];
outptr[1] = inptr[1];
outptr[2] = inptr[2];
outptr[3] = inptr[3];
# endif
outptr += 4;
}
*inptrp = inptr;
*outptrp = outptr;
/* Determine the status. */
if (*inptrp == inend)
result = __GCONV_EMPTY_INPUT;
else if (*inptrp + 4 > inend)
result = __GCONV_INCOMPLETE_INPUT;
else
{
assert (*outptrp + 4 > outend);
result = __GCONV_FULL_OUTPUT;
}
return result;
}
#endif
static inline int static inline int
__attribute ((always_inline)) __attribute ((always_inline))

View file

@ -58,12 +58,7 @@
#include <libc-diag.h> #include <libc-diag.h>
#undef FCTNAME2 #undef FCTNAME2
#if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED #define FCTNAME(name) name
# define FCTNAME2(name) name
#else
# define FCTNAME2(name) name##_unaligned
#endif
#define FCTNAME(name) FCTNAME2(name)
/* We need at least one byte for the next round. */ /* We need at least one byte for the next round. */
@ -279,20 +274,9 @@ FCTNAME (LOOPFCT) (struct __gconv_step *step,
} }
/* Include the file a second time to define the function to handle #if MAX_NEEDED_INPUT > 1
unaligned access. */ # define SINGLE(fct) SINGLE2 (fct)
#if !defined DEFINE_UNALIGNED && !_STRING_ARCH_unaligned \ # define SINGLE2(fct) fct##_single
&& MIN_NEEDED_INPUT != 1 && MAX_NEEDED_INPUT % MIN_NEEDED_INPUT == 0 \
&& MIN_NEEDED_OUTPUT != 1 && MAX_NEEDED_OUTPUT % MIN_NEEDED_OUTPUT == 0
# undef unaligned
# define DEFINE_UNALIGNED
# include "loop.c"
# undef DEFINE_UNALIGNED
#else
# if MAX_NEEDED_INPUT > 1
# define SINGLE(fct) SINGLE2 (fct)
# define SINGLE2(fct) fct##_single
static inline int static inline int
__attribute ((always_inline)) __attribute ((always_inline))
SINGLE(LOOPFCT) (struct __gconv_step *step, SINGLE(LOOPFCT) (struct __gconv_step *step,
@ -302,37 +286,37 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
size_t *irreversible EXTRA_LOOP_DECLS) size_t *irreversible EXTRA_LOOP_DECLS)
{ {
mbstate_t *state = step_data->__statep; mbstate_t *state = step_data->__statep;
# ifdef LOOP_NEED_FLAGS # ifdef LOOP_NEED_FLAGS
int flags = step_data->__flags; int flags = step_data->__flags;
# endif # endif
# ifdef LOOP_NEED_DATA # ifdef LOOP_NEED_DATA
void *data = step->__data; void *data = step->__data;
# endif # endif
int result = __GCONV_OK; int result = __GCONV_OK;
unsigned char bytebuf[MAX_NEEDED_INPUT]; unsigned char bytebuf[MAX_NEEDED_INPUT];
const unsigned char *inptr = *inptrp; const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp; unsigned char *outptr = *outptrp;
size_t inlen; size_t inlen;
# ifdef INIT_PARAMS # ifdef INIT_PARAMS
INIT_PARAMS; INIT_PARAMS;
# endif # endif
# ifdef UNPACK_BYTES # ifdef UNPACK_BYTES
UNPACK_BYTES UNPACK_BYTES
# else # else
/* Add the bytes from the state to the input buffer. */ /* Add the bytes from the state to the input buffer. */
assert ((state->__count & 7) <= sizeof (state->__value)); assert ((state->__count & 7) <= sizeof (state->__value));
for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen) for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
bytebuf[inlen] = state->__value.__wchb[inlen]; bytebuf[inlen] = state->__value.__wchb[inlen];
# endif # endif
/* Are there enough bytes in the input buffer? */ /* Are there enough bytes in the input buffer? */
if (MIN_NEEDED_INPUT > 1 if (MIN_NEEDED_INPUT > 1
&& __builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0)) && __builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
{ {
*inptrp = inend; *inptrp = inend;
# ifdef STORE_REST # ifdef STORE_REST
/* Building with -O3 GCC emits a `array subscript is above array /* Building with -O3 GCC emits a `array subscript is above array
bounds' warning. GCC BZ #64739 has been opened for this. */ bounds' warning. GCC BZ #64739 has been opened for this. */
@ -347,14 +331,14 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
inend = &bytebuf[inlen]; inend = &bytebuf[inlen];
STORE_REST STORE_REST
# else # else
/* We don't have enough input for another complete input /* We don't have enough input for another complete input
character. */ character. */
size_t inlen_after = inlen + (inend - inptr); size_t inlen_after = inlen + (inend - inptr);
assert (inlen_after <= sizeof (state->__value.__wchb)); assert (inlen_after <= sizeof (state->__value.__wchb));
for (; inlen < inlen_after; inlen++) for (; inlen < inlen_after; inlen++)
state->__value.__wchb[inlen] = *inptr++; state->__value.__wchb[inlen] = *inptr++;
# endif # endif
return __GCONV_INCOMPLETE_INPUT; return __GCONV_INCOMPLETE_INPUT;
} }
@ -406,11 +390,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
result = __GCONV_OK; result = __GCONV_OK;
/* Clear the state buffer. */ /* Clear the state buffer. */
# ifdef CLEAR_STATE # ifdef CLEAR_STATE
CLEAR_STATE; CLEAR_STATE;
# else # else
state->__count &= ~7; state->__count &= ~7;
# endif # endif
} }
else if (result == __GCONV_INCOMPLETE_INPUT) else if (result == __GCONV_INCOMPLETE_INPUT)
{ {
@ -419,11 +403,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
assert (inend != &bytebuf[MAX_NEEDED_INPUT]); assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
*inptrp += inend - bytebuf - (state->__count & 7); *inptrp += inend - bytebuf - (state->__count & 7);
# ifdef STORE_REST # ifdef STORE_REST
inptrp = &inptr; inptrp = &inptr;
STORE_REST STORE_REST
# else # else
/* We don't have enough input for another complete input /* We don't have enough input for another complete input
character. */ character. */
assert (inend - inptr > (state->__count & ~7)); assert (inend - inptr > (state->__count & ~7));
@ -432,14 +416,13 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
for (inlen = 0; inlen < inend - inptr; inlen++) for (inlen = 0; inlen < inend - inptr; inlen++)
state->__value.__wchb[inlen] = inptr[inlen]; state->__value.__wchb[inlen] = inptr[inlen];
inptr = inend; inptr = inend;
# endif # endif
} }
return result; return result;
} }
# undef SINGLE # undef SINGLE
# undef SINGLE2 # undef SINGLE2
# endif
# ifdef ONEBYTE_BODY # ifdef ONEBYTE_BODY
@ -471,4 +454,3 @@ gconv_btowc (struct __gconv_step *step, unsigned char c)
#undef LOOP_NEED_STATE #undef LOOP_NEED_STATE
#undef LOOP_NEED_FLAGS #undef LOOP_NEED_FLAGS
#undef LOOP_NEED_DATA #undef LOOP_NEED_DATA
#undef unaligned

View file

@ -448,33 +448,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
size_t lirreversible = 0; size_t lirreversible = 0;
size_t *lirreversiblep = irreversible ? &lirreversible : NULL; size_t *lirreversiblep = irreversible ? &lirreversible : NULL;
/* The following assumes that encodings, which have a variable length
what might unalign a buffer even though it is an aligned in the
beginning, either don't have the minimal number of bytes as a divisor
of the maximum length or have a minimum length of 1. This is true
for all known and supported encodings.
We use && instead of || to combine the subexpression for the FROM
encoding and for the TO encoding, because usually one of them is
INTERNAL, for which the subexpression evaluates to 1, but INTERNAL
buffers are always aligned correctly. */
#define POSSIBLY_UNALIGNED \
(!_STRING_ARCH_unaligned \
&& (((FROM_LOOP_MIN_NEEDED_FROM != 1 \
&& FROM_LOOP_MAX_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_FROM == 0) \
&& (FROM_LOOP_MIN_NEEDED_TO != 1 \
&& FROM_LOOP_MAX_NEEDED_TO % FROM_LOOP_MIN_NEEDED_TO == 0)) \
|| ((TO_LOOP_MIN_NEEDED_FROM != 1 \
&& TO_LOOP_MAX_NEEDED_FROM % TO_LOOP_MIN_NEEDED_FROM == 0) \
&& (TO_LOOP_MIN_NEEDED_TO != 1 \
&& TO_LOOP_MAX_NEEDED_TO % TO_LOOP_MIN_NEEDED_TO == 0))))
#if POSSIBLY_UNALIGNED
int unaligned;
# define GEN_unaligned(name) GEN_unaligned2 (name)
# define GEN_unaligned2(name) name##_unaligned
#else
# define unaligned 0
#endif
#ifdef PREPARE_LOOP #ifdef PREPARE_LOOP
PREPARE_LOOP PREPARE_LOOP
#endif #endif
@ -514,18 +487,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
} }
#endif #endif
#if POSSIBLY_UNALIGNED
unaligned =
((FROM_DIRECTION
&& ((uintptr_t) inptr % FROM_LOOP_MIN_NEEDED_FROM != 0
|| ((data->__flags & __GCONV_IS_LAST)
&& (uintptr_t) outbuf % FROM_LOOP_MIN_NEEDED_TO != 0)))
|| (!FROM_DIRECTION
&& (((data->__flags & __GCONV_IS_LAST)
&& (uintptr_t) outbuf % TO_LOOP_MIN_NEEDED_TO != 0)
|| (uintptr_t) inptr % TO_LOOP_MIN_NEEDED_FROM != 0)));
#endif
while (1) while (1)
{ {
/* Remember the start value for this round. */ /* Remember the start value for this round. */
@ -543,34 +504,14 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
SAVE_RESET_STATE (1); SAVE_RESET_STATE (1);
#endif #endif
if (__glibc_likely (!unaligned)) if (FROM_DIRECTION)
{ /* Run the conversion loop. */
if (FROM_DIRECTION) status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
/* Run the conversion loop. */ lirreversiblep EXTRA_LOOP_ARGS);
status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
lirreversiblep EXTRA_LOOP_ARGS);
else
/* Run the conversion loop. */
status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
lirreversiblep EXTRA_LOOP_ARGS);
}
#if POSSIBLY_UNALIGNED
else else
{ /* Run the conversion loop. */
if (FROM_DIRECTION) status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
/* Run the conversion loop. */ lirreversiblep EXTRA_LOOP_ARGS);
status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend,
&outbuf, outend,
lirreversiblep
EXTRA_LOOP_ARGS);
else
/* Run the conversion loop. */
status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend,
&outbuf, outend,
lirreversiblep
EXTRA_LOOP_ARGS);
}
#endif
/* If we were called as part of an error handling module we /* If we were called as part of an error handling module we
don't do anything else here. */ don't do anything else here. */
@ -635,41 +576,18 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
SAVE_RESET_STATE (0); SAVE_RESET_STATE (0);
#endif #endif
if (__glibc_likely (!unaligned)) if (FROM_DIRECTION)
{ /* Run the conversion loop. */
if (FROM_DIRECTION) nstatus = FROM_LOOP (step, data, inptrp, inend,
/* Run the conversion loop. */ &outbuf, outerr,
nstatus = FROM_LOOP (step, data, inptrp, inend, lirreversiblep
&outbuf, outerr, EXTRA_LOOP_ARGS);
lirreversiblep
EXTRA_LOOP_ARGS);
else
/* Run the conversion loop. */
nstatus = TO_LOOP (step, data, inptrp, inend,
&outbuf, outerr,
lirreversiblep
EXTRA_LOOP_ARGS);
}
#if POSSIBLY_UNALIGNED
else else
{ /* Run the conversion loop. */
if (FROM_DIRECTION) nstatus = TO_LOOP (step, data, inptrp, inend,
/* Run the conversion loop. */ &outbuf, outerr,
nstatus = GEN_unaligned (FROM_LOOP) (step, data, lirreversiblep
inptrp, inend, EXTRA_LOOP_ARGS);
&outbuf,
outerr,
lirreversiblep
EXTRA_LOOP_ARGS);
else
/* Run the conversion loop. */
nstatus = GEN_unaligned (TO_LOOP) (step, data,
inptrp, inend,
&outbuf, outerr,
lirreversiblep
EXTRA_LOOP_ARGS);
}
#endif
/* We must run out of output buffer space in this /* We must run out of output buffer space in this
rerun. */ rerun. */