aboutsummaryrefslogtreecommitdiff
path: root/iconv/gconv_simple.c
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-02-10 16:37:36 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-02-17 15:56:54 -0300
commit3e20ddade31d9c392d8ccf7ec902172f4bb01c2b (patch)
tree5e101d3002d011abd922deb713513f979dcbfb05 /iconv/gconv_simple.c
parent5729e0e9af590807df66a3db688008f9547bce9f (diff)
downloadglibc-3e20ddade31d9c392d8ccf7ec902172f4bb01c2b.tar
glibc-3e20ddade31d9c392d8ccf7ec902172f4bb01c2b.tar.gz
glibc-3e20ddade31d9c392d8ccf7ec902172f4bb01c2b.tar.bz2
glibc-3e20ddade31d9c392d8ccf7ec902172f4bb01c2b.zip
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>
Diffstat (limited to 'iconv/gconv_simple.c')
-rw-r--r--iconv/gconv_simple.c282
1 files changed, 17 insertions, 265 deletions
diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c
index c50ffd3bf0..c60cffad4c 100644
--- a/iconv/gconv_simple.c
+++ b/iconv/gconv_simple.c
@@ -86,69 +86,22 @@ internal_ucs4_loop (struct __gconv_step *step,
#if __BYTE_ORDER == __LITTLE_ENDIAN
/* Sigh, we have to do some real work. */
size_t cnt;
- uint32_t *outptr32 = (uint32_t *) outptr;
-
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
- *outptr32++ = bswap_32 (*(const uint32_t *) inptr);
-
- *inptrp = inptr;
- *outptrp = (unsigned char *) outptr32;
-#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;
-}
-
-#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];
+ uint32_t val = get32 (inptr);
+ put32 (outptr, __builtin_bswap32 (val));
}
*inptrp = inptr;
*outptrp = outptr;
-# elif __BYTE_ORDER == __BIG_ENDIAN
+#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
+#else
+# error "This endianess is not supported."
+#endif
/* Determine the status. */
if (*inptrp == inend)
@@ -160,7 +113,6 @@ internal_ucs4_loop_unaligned (struct __gconv_step *step,
return result;
}
-#endif
static inline int
@@ -242,12 +194,9 @@ ucs4_internal_loop (struct __gconv_step *step,
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
- uint32_t inval;
-
+ uint32_t inval = get32 (inptr);
#if __BYTE_ORDER == __LITTLE_ENDIAN
- inval = bswap_32 (*(const uint32_t *) inptr);
-#else
- inval = *(const uint32_t *) inptr;
+ inval = __builtin_bswap32 (inval);
#endif
if (__glibc_unlikely (inval > 0x7fffffff))
@@ -272,7 +221,7 @@ ucs4_internal_loop (struct __gconv_step *step,
return __GCONV_ILLEGAL_INPUT;
}
- *((uint32_t *) outptr) = inval;
+ put32 (outptr, inval);
outptr += sizeof (uint32_t);
}
@@ -290,75 +239,6 @@ ucs4_internal_loop (struct __gconv_step *step,
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
__attribute ((always_inline))
@@ -453,11 +333,12 @@ internal_ucs4le_loop (struct __gconv_step *step,
#if __BYTE_ORDER == __BIG_ENDIAN
/* Sigh, we have to do some real work. */
size_t cnt;
- uint32_t *outptr32 = (uint32_t *) outptr;
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
- *outptr32++ = bswap_32 (*(const uint32_t *) inptr);
- outptr = (unsigned char *) outptr32;
+ for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
+ {
+ uint32_t val = get32 (inptr);
+ put32 (outptr, __builtin_bswap32 (val));
+ }
*inptrp = inptr;
*outptrp = outptr;
@@ -480,59 +361,6 @@ internal_ucs4le_loop (struct __gconv_step *step,
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
__attribute ((always_inline))
@@ -612,12 +440,9 @@ ucs4le_internal_loop (struct __gconv_step *step,
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
- uint32_t inval;
-
+ uint32_t inval = get32 (inptr);
#if __BYTE_ORDER == __BIG_ENDIAN
- inval = bswap_32 (*(const uint32_t *) inptr);
-#else
- inval = *(const uint32_t *) inptr;
+ inval = __builtin_bswap32 (inval);
#endif
if (__glibc_unlikely (inval > 0x7fffffff))
@@ -642,7 +467,7 @@ ucs4le_internal_loop (struct __gconv_step *step,
return __GCONV_ILLEGAL_INPUT;
}
- *((uint32_t *) outptr) = inval;
+ put32 (outptr, inval);
outptr += sizeof (uint32_t);
}
@@ -663,79 +488,6 @@ ucs4le_internal_loop (struct __gconv_step *step,
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
__attribute ((always_inline))