From: Martin Mares Date: Sat, 10 Mar 2007 20:21:23 +0000 (+0100) Subject: Unaligned access functions (formerly macros) work in native, big and little endian. X-Git-Tag: holmes-import~506^2~98^2~3 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=167b6a9e94c23c4123ee372b0a0561b1be3dca79;p=libucw.git Unaligned access functions (formerly macros) work in native, big and little endian. --- diff --git a/lib/unaligned.h b/lib/unaligned.h index 6da60d4d..115ed073 100644 --- a/lib/unaligned.h +++ b/lib/unaligned.h @@ -1,7 +1,7 @@ /* * UCW Library -- Fast Access to Unaligned Data * - * (c) 1997--2003 Martin Mares + * (c) 1997--2007 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -10,43 +10,153 @@ #ifndef _UCW_UNALIGNED_H #define _UCW_UNALIGNED_H -#ifdef CPU_ALLOW_UNALIGNED -#define GET_U16(p) (*((u16 *)(p))) -#define GET_U32(p) (*((u32 *)(p))) -#define GET_U32_16(p) (*((u32 *)(p))) -#define GET_U64(p) (*((u64 *)(p))) -#define PUT_U16(p,x) *((u16 *)(p)) = (x) -#define PUT_U32(p,x) *((u32 *)(p)) = (x) -#define PUT_U64(p,x) *((u64 *)(p)) = (x) -#else -#define GET_U64(p) ({ u64 _x; memcpy(&_x, p, 8); _x; }) -#define PUT_U64(p,x) do { u64 _x=x; memcpy(p, &_x, 8); } while(0) -#ifdef CPU_BIG_ENDIAN -#define GET_U16(p) (((p)[0] << 8) | (p)[1]) -#define GET_U32(p) (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | (p)[3]) -#define PUT_U16(p,x) (void)(((p)[0] = ((x) >> 8)), (((p)[1]) = (x))) -#define PUT_U32(p,x) (void)(((p)[0] = ((x) >> 24)), (((p)[1]) = ((x) >> 16)), (((p)[2]) = ((x) >> 8)), (((p)[3]) = (x))) +/* Big endian format */ + +#if defined(CPU_ALLOW_UNALIGNED) && defined(CPU_BIG_ENDIAN) +static inline uns get_u16_be(byte *p) { return *(u16 *)p; } +static inline u32 get_u32_be(byte *p) { return *(u32 *)p; } +static inline u64 get_u64_be(byte *p) { return *(u64 *)p; } +static inline void put_u16_be(byte *p, uns x) { *(u16 *)p = x; } +static inline void put_u32_be(byte *p, u32 x) { *(u32 *)p = x; } +static inline void put_u64_be(byte *p, u64 x) { *(u64 *)p = x; } #else -#define GET_U16(p) (((p)[1] << 8) | (p)[0]) -#define GET_U32(p) (((p)[3] << 24) | ((p)[2] << 16) | ((p)[1] << 8) | (p)[0]) -#define PUT_U16(p,x) (void)(((p)[1] = ((x) >> 8)), (((p)[0]) = (x))) -#define PUT_U32(p,x) (void)(((p)[3] = ((x) >> 24)), (((p)[2]) = ((x) >> 16)), (((p)[1]) = ((x) >> 8)), (((p)[0]) = (x))) +static inline uns get_u16_be(byte *p) +{ + return (p[0] << 8) | p[1]; +} +static inline u32 get_u32_be(byte *p) +{ + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; +} +static inline u64 get_u64_be(byte *p) +{ + return ((u64) get_u32_be(p) << 32) | get_u32_be(p+4); +} +static inline void put_u16_be(byte *p, uns x) +{ + p[0] = x >> 8; + p[1] = x; +} +static inline void put_u32_be(byte *p, u32 x) +{ + p[0] = x >> 24; + p[1] = x >> 16; + p[2] = x >> 8; + p[3] = x; +} +static inline void put_u64_be(byte *p, u64 x) +{ + put_u32_be(p, x >> 32); + put_u32_be(p+4, x); +} #endif + +/* Little-endian format */ + +#if defined(CPU_ALLOW_UNALIGNED) && !defined(CPU_BIG_ENDIAN) +static inline uns get_u16_le(byte *p) { return *(u16 *)p; } +static inline u32 get_u32_le(byte *p) { return *(u32 *)p; } +static inline u64 get_u64_le(byte *p) { return *(u64 *)p; } +static inline void put_u16_le(byte *p, uns x) { *(u16 *)p = x; } +static inline void put_u32_le(byte *p, u32 x) { *(u32 *)p = x; } +static inline void put_u64_le(byte *p, u64 x) { *(u64 *)p = x; } +#else +static inline uns get_u16_le(byte *p) +{ + return p[0] | (p[1] << 8); +} +static inline u32 get_u32_le(byte *p) +{ + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} +static inline u64 get_u64_le(byte *p) +{ + return get_u32_le(p) | ((u64) get_u32_le(p+4) << 32); +} +static inline void put_u16_le(byte *p, uns x) +{ + p[0] = x; + p[1] = x >> 8; +} +static inline void put_u32_le(byte *p, u32 x) +{ + p[0] = x; + p[1] = x >> 8; + p[2] = x >> 16; + p[3] = x >> 24; +} +static inline void put_u64_le(byte *p, u64 x) +{ + put_u32_le(p, x); + put_u32_le(p+4, x >> 32); +} #endif -#define GET_U32_BE16(p) (((p)[0] << 16) | (p)[1]) +static inline u64 get_u40_be(byte *p) +{ + return ((u64)p[0] << 32) | get_u32_be(p+1); +} + +static inline void put_u40_be(byte *p, u64 x) +{ + p[0] = x >> 32; + put_u32_be(p+1, x); +} + +static inline u64 get_u40_le(byte *p) +{ + return get_u32_le(p) | ((u64) p[4] << 32); +} + +static inline void put_u40_le(byte *p, u64 x) +{ + put_u32_le(p, x); + p[4] = x >> 32; +} + +/* The native format */ #ifdef CPU_BIG_ENDIAN -#define GET_U40(p) (((u64) (p)[0] << 32) | GET_U32((p)+1)) -#define PUT_U40(p,x) do { (p)[0] = ((x) >> 32); PUT_U32(((p)+1), x); } while(0) + +static inline uns get_u16(byte *p) { return get_u16_be(p); } +static inline u32 get_u32(byte *p) { return get_u32_be(p); } +static inline u64 get_u64(byte *p) { return get_u64_be(p); } +static inline u64 get_u40(byte *p) { return get_u40_be(p); } +static inline void put_u16(byte *p, uns x) { return put_u16_be(p, x); } +static inline void put_u32(byte *p, u32 x) { return put_u32_be(p, x); } +static inline void put_u64(byte *p, u64 x) { return put_u64_be(p, x); } +static inline void put_u40(byte *p, u64 x) { return put_u40_be(p, x); } + #else -#define GET_U40(p) (((u64) (p)[4] << 32) | GET_U32(p)) -#define PUT_U40(p,x) do { (p)[4] = ((x) >> 32); PUT_U32(p, x); } while(0) + +static inline uns get_u16(byte *p) { return get_u16_le(p); } +static inline u32 get_u32(byte *p) { return get_u32_le(p); } +static inline u64 get_u64(byte *p) { return get_u64_le(p); } +static inline u64 get_u40(byte *p) { return get_u40_le(p); } +static inline void put_u16(byte *p, uns x) { return put_u16_le(p, x); } +static inline void put_u32(byte *p, u32 x) { return put_u32_le(p, x); } +static inline void put_u64(byte *p, u64 x) { return put_u64_le(p, x); } +static inline void put_u40(byte *p, u64 x) { return put_u40_le(p, x); } + #endif /* Just for completeness */ -#define GET_U8(p) (*(byte *)(p)) -#define PUT_U8(p,x) *((byte *)(p)) = (x) +static inline uns get_u8(byte *p) { return *p; } +static inline void put_u8(byte *p, uns x) { *p = x; } + +/* Backward compatibility macros */ + +#define GET_U8(p) get_u8((byte*)(p)) +#define GET_U16(p) get_u16((byte*)(p)) +#define GET_U32(p) get_u32((byte*)(p)) +#define GET_U64(p) get_u64((byte*)(p)) +#define GET_U40(p) get_u40((byte*)(p)) + +#define PUT_U8(p,x) put_u8((byte*)(p),x); +#define PUT_U16(p,x) put_u16((byte*)(p),x) +#define PUT_U32(p,x) put_u32((byte*)p,x) +#define PUT_U64(p,x) put_u64((byte*)p,x) +#define PUT_U40(p,x) put_u40((byte*)p,x) #endif