From a23bab96cb9eb7a869eb260336e5837e9c63d69b Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 26 May 2018 23:29:09 +0100 Subject: [PATCH] utils/bits.h: Support compiler magic for unaligned loads and stores. Introduce `RAWw' macros to access the raw memory, and implement `LOADwe' and `STOREwe' in terms of these and `eTOHw'/`HTOew'. These are remarkably tricky because GCC (I think mistakenly) thinks that type-based aliasing is applicable when in fact the other type in question is `unsigned char', which is known to be able to alias anything. Hit things with the `may_alias' hammer and hope they quieten down. --- utils/bits.3 | 21 +++++++++++++++++ utils/bits.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/utils/bits.3 b/utils/bits.3 index 7b1c715..a002e24 100644 --- a/utils/bits.3 +++ b/utils/bits.3 @@ -112,6 +112,11 @@ bits \- portable bit manipulation macros .\" HTOB64 .\" HTOL64 .\" +.\" RAW8 +.\" RAW16 +.\" RAW32 +.\" RAW64 +.\" .\" @GETBYTE .\" @PUTBYTE .\" @@ -485,6 +490,22 @@ These macros always operate on byte offsets regardless of the type of the pointer .IR p . .PP +For each size suffix +.IR w , +there may be a macro such that the invocation +.BI RAW w ( p ) +is an lvalue designating the +.IR w /8 +octets starting at address +.IR p , +interpreted according to the environment's preferred representation, +except that +.I p +need not be aligned in any particular fashion. There are many reasons +why this might not be possible; programmers are not normally expected to +use these macros directly, and they are documented in case they are +useful for special effects. +.PP For each size-and-endian suffix .IR we , the macro invocation diff --git a/utils/bits.h b/utils/bits.h index 3b12f96..656eee5 100644 --- a/utils/bits.h +++ b/utils/bits.h @@ -40,6 +40,10 @@ # include #endif +#ifndef MLIB_COMPILER_H +# include "compiler.h" +#endif + /*----- Decide on some types ----------------------------------------------*/ /* --- Make GNU C shut up --- */ @@ -316,6 +320,16 @@ typedef unsigned char octet, uint8; /* --- Endianness swapping --- */ +#if GCC_VERSION_P(4, 8) +# define ENDSWAP16(x) ((uint16)__builtin_bswap16(x)) +#endif +#if GCC_VERSION_P(4, 3) +# define ENDSWAP32(x) ((uint32)__builtin_bswap32(x)) +#endif +#if GCC_VERSION_P(4, 3) && defined(HAVE_UINT64) +# define ENDSWAP64(x) ((uint64)__builtin_bswap64(x)) +#endif + #ifndef ENDSWAP8 # define ENDSWAP8(x) U8(x) #endif @@ -411,8 +425,71 @@ typedef unsigned char octet, uint8; # define BTOH64_(z, x) ASSIGN64(z, x) #endif +/* --- Unaligned access (GCC-specific) --- */ + +#if GCC_VERSION_P(3, 3) && CHAR_BIT == 8 +# define MLIB_MISALIGNED __attribute__((aligned(1), may_alias)) +# if __SIZEOF_SHORT__ == 2 + typedef MLIB_MISALIGNED unsigned short misaligned_uint16; +# define RAW16(p) (*(misaligned_uint16 *)(p)) +# endif +# if __SIZEOF_INT__ == 4 + typedef MLIB_MISALIGNED unsigned int misaligned_uint32; +# define RAW32(p) (*(misaligned_uint32 *)(p)) +# elif __SIZEOF_LONG__ == 4 + typedef MLIB_MISALIGNED unsigned long misaligned_uint32; +# define RAW32(p) (*(misaligned_uint32 *)(p)) +# endif +# if __SIZEOF_LONG__ == 8 + typedef MLIB_MISALIGNED unsigned long misaligned_uint64; +# define RAW64(p) (*(misaligned_uint64 *)(p)) +# elif __SIZEOF_LONG_LONG__ == 8 + typedef MLIB_MISALIGNED unsigned long long misaligned_uint64; +# define RAW64(p) (*(misaligned_uint64 *)(p)) +# endif +#endif + /* --- Storage and retrieval --- */ +#if defined(RAW16) && defined(LTOH16) +# define LOAD16_L(p) LTOH16(RAW16(p)) +#endif +#if defined(RAW16) && defined(HTOL16) +# define STORE16_L(p, x) (RAW16(p) = HTOL16(x)) +#endif +#if defined(RAW16) && defined(BTOH16) +# define LOAD16_B(p) BTOH16(RAW16(p)) +#endif +#if defined(RAW16) && defined(HTOB16) +# define STORE16_B(p, x) (RAW16(p) = HTOB16(x)) +#endif + +#if defined(RAW32) && defined(LTOH32) +# define LOAD32_L(p) LTOH32(RAW32(p)) +#endif +#if defined(RAW32) && defined(HTOL32) +# define STORE32_L(p, x) (RAW32(p) = HTOL32(x)) +#endif +#if defined(RAW32) && defined(BTOH32) +# define LOAD32_B(p) BTOH32(RAW32(p)) +#endif +#if defined(RAW32) && defined(HTOB32) +# define STORE32_B(p, x) (RAW32(p) = HTOB32(x)) +#endif + +#if defined(RAW64) && defined(LTOH64) +# define LOAD64_L(p) LTOH64(RAW64(p)) +#endif +#if defined(RAW64) && defined(HTOL64) +# define STORE64_L(p, x) (RAW64(p) = HTOL64(x)) +#endif +#if defined(RAW64) && defined(BTOH64) +# define LOAD64_B(p) BTOH64(RAW64(p)) +#endif +#if defined(RAW64) && defined(HTOB64) +# define STORE64_B(p, x) (RAW64(p) = HTOB64(x)) +#endif + #define GETBYTE(p, o) (((octet *)(p))[o] & MASK8) #define PUTBYTE(p, o, v) (((octet *)(p))[o] = U8((v))) -- 2.11.0