mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
iconv: Remove _STRING_ARCH_unaligned usage for get/set macros
And use a packed structure instead. The compiler generates optimized unaligned code if the architecture supports it. Checked on x86_64-linux-gnu and i686-linux-gnu. Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
This commit is contained in:
parent
62d4c768a4
commit
5729e0e9af
10 changed files with 42 additions and 154 deletions
|
@ -26,6 +26,34 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
/* We have to provide support for machines which are not able to handled
|
||||||
|
unaligned memory accesses. Some of the character encodings have
|
||||||
|
representations with a fixed width of 2 or 4 bytes. */
|
||||||
|
#define get16(addr) \
|
||||||
|
({ \
|
||||||
|
const struct { uint16_t r; } __attribute__ ((__packed__)) *__ptr \
|
||||||
|
= (__typeof(__ptr))(addr); \
|
||||||
|
__ptr->r; \
|
||||||
|
})
|
||||||
|
#define get32(addr) \
|
||||||
|
({ \
|
||||||
|
const struct { uint32_t r; } __attribute__ ((__packed__)) *__ptr \
|
||||||
|
= (__typeof(__ptr))(addr); \
|
||||||
|
__ptr->r; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define put16(addr, val) \
|
||||||
|
do { \
|
||||||
|
struct { uint16_t r; } __attribute__ ((__packed__)) *__ptr \
|
||||||
|
= (__typeof(__ptr))(addr); \
|
||||||
|
__ptr->r = val; \
|
||||||
|
} while (0)
|
||||||
|
#define put32(addr, val) \
|
||||||
|
do { \
|
||||||
|
struct { uint32_t r; } __attribute__ ((__packed__)) *__ptr \
|
||||||
|
= (__typeof(__ptr))(addr); \
|
||||||
|
__ptr->r = val; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* Structure for alias definition. Simply two strings. */
|
/* Structure for alias definition. Simply two strings. */
|
||||||
struct gconv_alias
|
struct gconv_alias
|
||||||
|
|
73
iconv/loop.c
73
iconv/loop.c
|
@ -57,75 +57,10 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <libc-diag.h>
|
#include <libc-diag.h>
|
||||||
|
|
||||||
/* We have to provide support for machines which are not able to handled
|
|
||||||
unaligned memory accesses. Some of the character encodings have
|
|
||||||
representations with a fixed width of 2 or 4 bytes. But if we cannot
|
|
||||||
access unaligned memory we still have to read byte-wise. */
|
|
||||||
#undef FCTNAME2
|
#undef FCTNAME2
|
||||||
#if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
|
#if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
|
||||||
/* We can handle unaligned memory access. */
|
|
||||||
# define get16(addr) *((const uint16_t *) (addr))
|
|
||||||
# define get32(addr) *((const uint32_t *) (addr))
|
|
||||||
|
|
||||||
/* We need no special support for writing values either. */
|
|
||||||
# define put16(addr, val) *((uint16_t *) (addr)) = (val)
|
|
||||||
# define put32(addr, val) *((uint32_t *) (addr)) = (val)
|
|
||||||
|
|
||||||
# define FCTNAME2(name) name
|
# define FCTNAME2(name) name
|
||||||
#else
|
#else
|
||||||
/* Distinguish between big endian and little endian. */
|
|
||||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
# define get16(addr) \
|
|
||||||
(((const unsigned char *) (addr))[1] << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[0])
|
|
||||||
# define get32(addr) \
|
|
||||||
(((((const unsigned char *) (addr))[3] << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[2]) << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[1]) << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[0])
|
|
||||||
|
|
||||||
# define put16(addr, val) \
|
|
||||||
({ uint16_t __val = (val); \
|
|
||||||
((unsigned char *) (addr))[0] = __val; \
|
|
||||||
((unsigned char *) (addr))[1] = __val >> 8; \
|
|
||||||
(void) 0; })
|
|
||||||
# define put32(addr, val) \
|
|
||||||
({ uint32_t __val = (val); \
|
|
||||||
((unsigned char *) (addr))[0] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[1] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[2] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[3] = __val; \
|
|
||||||
(void) 0; })
|
|
||||||
# else
|
|
||||||
# define get16(addr) \
|
|
||||||
(((const unsigned char *) (addr))[0] << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[1])
|
|
||||||
# define get32(addr) \
|
|
||||||
(((((const unsigned char *) (addr))[0] << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[1]) << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[2]) << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[3])
|
|
||||||
|
|
||||||
# define put16(addr, val) \
|
|
||||||
({ uint16_t __val = (val); \
|
|
||||||
((unsigned char *) (addr))[1] = __val; \
|
|
||||||
((unsigned char *) (addr))[0] = __val >> 8; \
|
|
||||||
(void) 0; })
|
|
||||||
# define put32(addr, val) \
|
|
||||||
({ uint32_t __val = (val); \
|
|
||||||
((unsigned char *) (addr))[3] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[2] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[1] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[0] = __val; \
|
|
||||||
(void) 0; })
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# define FCTNAME2(name) name##_unaligned
|
# define FCTNAME2(name) name##_unaligned
|
||||||
#endif
|
#endif
|
||||||
#define FCTNAME(name) FCTNAME2(name)
|
#define FCTNAME(name) FCTNAME2(name)
|
||||||
|
@ -349,10 +284,6 @@ FCTNAME (LOOPFCT) (struct __gconv_step *step,
|
||||||
#if !defined DEFINE_UNALIGNED && !_STRING_ARCH_unaligned \
|
#if !defined DEFINE_UNALIGNED && !_STRING_ARCH_unaligned \
|
||||||
&& MIN_NEEDED_INPUT != 1 && MAX_NEEDED_INPUT % MIN_NEEDED_INPUT == 0 \
|
&& MIN_NEEDED_INPUT != 1 && MAX_NEEDED_INPUT % MIN_NEEDED_INPUT == 0 \
|
||||||
&& MIN_NEEDED_OUTPUT != 1 && MAX_NEEDED_OUTPUT % MIN_NEEDED_OUTPUT == 0
|
&& MIN_NEEDED_OUTPUT != 1 && MAX_NEEDED_OUTPUT % MIN_NEEDED_OUTPUT == 0
|
||||||
# undef get16
|
|
||||||
# undef get32
|
|
||||||
# undef put16
|
|
||||||
# undef put32
|
|
||||||
# undef unaligned
|
# undef unaligned
|
||||||
|
|
||||||
# define DEFINE_UNALIGNED
|
# define DEFINE_UNALIGNED
|
||||||
|
@ -540,8 +471,4 @@ 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 get16
|
|
||||||
#undef get32
|
|
||||||
#undef put16
|
|
||||||
#undef put32
|
|
||||||
#undef unaligned
|
#undef unaligned
|
||||||
|
|
|
@ -204,73 +204,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Define macros which can access unaligned buffers. These macros are
|
|
||||||
supposed to be used only in code outside the inner loops. For the inner
|
|
||||||
loops we have other definitions which allow optimized access. */
|
|
||||||
#if _STRING_ARCH_unaligned
|
|
||||||
/* We can handle unaligned memory access. */
|
|
||||||
# define get16u(addr) *((const uint16_t *) (addr))
|
|
||||||
# define get32u(addr) *((const uint32_t *) (addr))
|
|
||||||
|
|
||||||
/* We need no special support for writing values either. */
|
|
||||||
# define put16u(addr, val) *((uint16_t *) (addr)) = (val)
|
|
||||||
# define put32u(addr, val) *((uint32_t *) (addr)) = (val)
|
|
||||||
#else
|
|
||||||
/* Distinguish between big endian and little endian. */
|
|
||||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
# define get16u(addr) \
|
|
||||||
(((const unsigned char *) (addr))[1] << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[0])
|
|
||||||
# define get32u(addr) \
|
|
||||||
(((((const unsigned char *) (addr))[3] << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[2]) << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[1]) << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[0])
|
|
||||||
|
|
||||||
# define put16u(addr, val) \
|
|
||||||
({ uint16_t __val = (val); \
|
|
||||||
((unsigned char *) (addr))[0] = __val; \
|
|
||||||
((unsigned char *) (addr))[1] = __val >> 8; \
|
|
||||||
(void) 0; })
|
|
||||||
# define put32u(addr, val) \
|
|
||||||
({ uint32_t __val = (val); \
|
|
||||||
((unsigned char *) (addr))[0] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[1] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[2] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[3] = __val; \
|
|
||||||
(void) 0; })
|
|
||||||
# else
|
|
||||||
# define get16u(addr) \
|
|
||||||
(((const unsigned char *) (addr))[0] << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[1])
|
|
||||||
# define get32u(addr) \
|
|
||||||
(((((const unsigned char *) (addr))[0] << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[1]) << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[2]) << 8 \
|
|
||||||
| ((const unsigned char *) (addr))[3])
|
|
||||||
|
|
||||||
# define put16u(addr, val) \
|
|
||||||
({ uint16_t __val = (val); \
|
|
||||||
((unsigned char *) (addr))[1] = __val; \
|
|
||||||
((unsigned char *) (addr))[0] = __val >> 8; \
|
|
||||||
(void) 0; })
|
|
||||||
# define put32u(addr, val) \
|
|
||||||
({ uint32_t __val = (val); \
|
|
||||||
((unsigned char *) (addr))[3] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[2] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[1] = __val; \
|
|
||||||
__val >>= 8; \
|
|
||||||
((unsigned char *) (addr))[0] = __val; \
|
|
||||||
(void) 0; })
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* For conversions from a fixed width character set to another fixed width
|
/* For conversions from a fixed width character set to another fixed width
|
||||||
character set we can define RESET_INPUT_BUFFER in a very fast way. */
|
character set we can define RESET_INPUT_BUFFER in a very fast way. */
|
||||||
#if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE
|
#if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE
|
||||||
|
|
|
@ -91,7 +91,7 @@ enum
|
||||||
if (__glibc_likely (outbuf + 4 <= outend)) \
|
if (__glibc_likely (outbuf + 4 <= outend)) \
|
||||||
{ \
|
{ \
|
||||||
/* Write out the last character. */ \
|
/* Write out the last character. */ \
|
||||||
put32u (outbuf, ch); \
|
put32 (outbuf, ch); \
|
||||||
outbuf += 4; \
|
outbuf += 4; \
|
||||||
data->__statep->__count &= 7; \
|
data->__statep->__count &= 7; \
|
||||||
data->__statep->__count |= ASCII_set; \
|
data->__statep->__count |= ASCII_set; \
|
||||||
|
|
|
@ -51,10 +51,10 @@
|
||||||
return (inptr == inend \
|
return (inptr == inend \
|
||||||
? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT); \
|
? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT); \
|
||||||
\
|
\
|
||||||
if (get16u (inptr) == BOM) \
|
if (get16 (inptr) == BOM) \
|
||||||
/* Simply ignore the BOM character. */ \
|
/* Simply ignore the BOM character. */ \
|
||||||
*inptrp = inptr += 2; \
|
*inptrp = inptr += 2; \
|
||||||
else if (get16u (inptr) == BOM_OE) \
|
else if (get16 (inptr) == BOM_OE) \
|
||||||
{ \
|
{ \
|
||||||
data->__flags |= __GCONV_SWAP; \
|
data->__flags |= __GCONV_SWAP; \
|
||||||
*inptrp = inptr += 2; \
|
*inptrp = inptr += 2; \
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
||||||
return __GCONV_FULL_OUTPUT; \
|
return __GCONV_FULL_OUTPUT; \
|
||||||
\
|
\
|
||||||
put16u (outbuf, BOM); \
|
put16 (outbuf, BOM); \
|
||||||
outbuf += 2; \
|
outbuf += 2; \
|
||||||
} \
|
} \
|
||||||
swap = data->__flags & __GCONV_SWAP;
|
swap = data->__flags & __GCONV_SWAP;
|
||||||
|
|
|
@ -55,10 +55,10 @@
|
||||||
return (inptr == inend \
|
return (inptr == inend \
|
||||||
? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT); \
|
? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT); \
|
||||||
\
|
\
|
||||||
if (get16u (inptr) == BOM) \
|
if (get16 (inptr) == BOM) \
|
||||||
/* Simply ignore the BOM character. */ \
|
/* Simply ignore the BOM character. */ \
|
||||||
*inptrp = inptr += 2; \
|
*inptrp = inptr += 2; \
|
||||||
else if (get16u (inptr) == BOM_OE) \
|
else if (get16 (inptr) == BOM_OE) \
|
||||||
{ \
|
{ \
|
||||||
data->__flags |= __GCONV_SWAP; \
|
data->__flags |= __GCONV_SWAP; \
|
||||||
*inptrp = inptr += 2; \
|
*inptrp = inptr += 2; \
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
||||||
return __GCONV_FULL_OUTPUT; \
|
return __GCONV_FULL_OUTPUT; \
|
||||||
\
|
\
|
||||||
put16u (outbuf, BOM); \
|
put16 (outbuf, BOM); \
|
||||||
outbuf += 2; \
|
outbuf += 2; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -52,10 +52,10 @@
|
||||||
return (inptr == inend \
|
return (inptr == inend \
|
||||||
? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT); \
|
? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT); \
|
||||||
\
|
\
|
||||||
if (get32u (inptr) == BOM) \
|
if (get32 (inptr) == BOM) \
|
||||||
/* Simply ignore the BOM character. */ \
|
/* Simply ignore the BOM character. */ \
|
||||||
*inptrp = inptr += 4; \
|
*inptrp = inptr += 4; \
|
||||||
else if (get32u (inptr) == BOM_OE) \
|
else if (get32 (inptr) == BOM_OE) \
|
||||||
{ \
|
{ \
|
||||||
data->__flags |= __GCONV_SWAP; \
|
data->__flags |= __GCONV_SWAP; \
|
||||||
*inptrp = inptr += 4; \
|
*inptrp = inptr += 4; \
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
if (__glibc_unlikely (outbuf + 4 > outend)) \
|
if (__glibc_unlikely (outbuf + 4 > outend)) \
|
||||||
return __GCONV_FULL_OUTPUT; \
|
return __GCONV_FULL_OUTPUT; \
|
||||||
\
|
\
|
||||||
put32u (outbuf, BOM); \
|
put32 (outbuf, BOM); \
|
||||||
outbuf += 4; \
|
outbuf += 4; \
|
||||||
} \
|
} \
|
||||||
else if (__builtin_expect (data->__invocation_counter == 0, 0) \
|
else if (__builtin_expect (data->__invocation_counter == 0, 0) \
|
||||||
|
|
|
@ -171,7 +171,7 @@ gconv_end (struct __gconv_step *data)
|
||||||
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
||||||
return __GCONV_FULL_OUTPUT; \
|
return __GCONV_FULL_OUTPUT; \
|
||||||
\
|
\
|
||||||
put16u (outbuf, BOM_UTF16); \
|
put16 (outbuf, BOM_UTF16); \
|
||||||
outbuf += 2; \
|
outbuf += 2; \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
|
@ -180,7 +180,7 @@ gconv_end (struct __gconv_step *data)
|
||||||
if (__glibc_unlikely (outbuf + 4 > outend)) \
|
if (__glibc_unlikely (outbuf + 4 > outend)) \
|
||||||
return __GCONV_FULL_OUTPUT; \
|
return __GCONV_FULL_OUTPUT; \
|
||||||
\
|
\
|
||||||
put32u (outbuf, BOM_UTF32); \
|
put32 (outbuf, BOM_UTF32); \
|
||||||
outbuf += 4; \
|
outbuf += 4; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,7 +211,7 @@ gconv_end (struct __gconv_step *data)
|
||||||
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
||||||
return __GCONV_FULL_OUTPUT; \
|
return __GCONV_FULL_OUTPUT; \
|
||||||
\
|
\
|
||||||
put16u (outbuf, BOM_UTF16); \
|
put16 (outbuf, BOM_UTF16); \
|
||||||
outbuf += 2; \
|
outbuf += 2; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@ gconv_end (struct __gconv_step *data)
|
||||||
if (__glibc_unlikely (outbuf + 4 > outend)) \
|
if (__glibc_unlikely (outbuf + 4 > outend)) \
|
||||||
return __GCONV_FULL_OUTPUT; \
|
return __GCONV_FULL_OUTPUT; \
|
||||||
\
|
\
|
||||||
put32u (outbuf, BOM); \
|
put32 (outbuf, BOM); \
|
||||||
outbuf += 4; \
|
outbuf += 4; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue