From 9511af6682f3a81e5956b43c1af1748c289191a8 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 10 May 2011 15:38:10 +0200 Subject: COMMON: Always prefer GCC 4.x versions of READ_UINT*/WRITE_UINT* In addition, we use them if in GCC >= 3.3 if unaligned access is possible. The GCC variants of these macros also contain protection against overzealous compilers' static aliasing optimizations. --- common/endian.h | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/common/endian.h b/common/endian.h index afd7e2913e..c645243654 100644 --- a/common/endian.h +++ b/common/endian.h @@ -149,53 +149,57 @@ */ #define MKTAG(a0,a1,a2,a3) ((uint32)((a3) | ((a2) << 8) | ((a1) << 16) | ((a0) << 24))) -// Functions for reading/writing native integers, -// this transparently handles the need for alignment. +// Functions for reading/writing native integers. +// They also transparently handle the need for alignment. -#if !defined(SCUMM_NEED_ALIGNMENT) +// Test for GCC >= 4.0. These implementations will automatically use +// CPU-specific instructions for unaligned data when they are available (eg. +// MIPS). See also this email thread on scummvm-devel for details: +// +// +// Moreover, we activate this code for GCC >= 3.3 but *only* if unaligned access +// is allowed. +#if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3 && !defined(SCUMM_NEED_ALIGNMENT))) FORCEINLINE uint16 READ_UINT16(const void *ptr) { - return *(const uint16 *)(ptr); + struct Unaligned16 { uint16 val; } __attribute__ ((__packed__, __may_alias__)); + return ((const Unaligned16 *)ptr)->val; } FORCEINLINE uint32 READ_UINT32(const void *ptr) { - return *(const uint32 *)(ptr); + struct Unaligned32 { uint32 val; } __attribute__ ((__packed__, __may_alias__)); + return ((const Unaligned32 *)ptr)->val; } FORCEINLINE void WRITE_UINT16(void *ptr, uint16 value) { - *(uint16 *)(ptr) = value; + struct Unaligned16 { uint16 val; } __attribute__ ((__packed__, __may_alias__)); + ((Unaligned16 *)ptr)->val = value; } FORCEINLINE void WRITE_UINT32(void *ptr, uint32 value) { - *(uint32 *)(ptr) = value; + struct Unaligned32 { uint32 val; } __attribute__ ((__packed__, __may_alias__)); + ((Unaligned32 *)ptr)->val = value; } -// Test for GCC >= 4.0. These implementations will automatically use CPU-specific -// instructions for unaligned data when they are available (eg. MIPS). -// See also this email thread on scummvm-devel for details: -// -#elif defined(__GNUC__) && (__GNUC__ >= 4) +#elif !defined(SCUMM_NEED_ALIGNMENT) FORCEINLINE uint16 READ_UINT16(const void *ptr) { - struct Unaligned16 { uint16 val; } __attribute__ ((__packed__, __may_alias__)); - return ((const Unaligned16 *)ptr)->val; + return *(const uint16 *)(ptr); } FORCEINLINE uint32 READ_UINT32(const void *ptr) { - struct Unaligned32 { uint32 val; } __attribute__ ((__packed__, __may_alias__)); - return ((const Unaligned32 *)ptr)->val; + return *(const uint32 *)(ptr); } FORCEINLINE void WRITE_UINT16(void *ptr, uint16 value) { - struct Unaligned16 { uint16 val; } __attribute__ ((__packed__, __may_alias__)); - ((Unaligned16 *)ptr)->val = value; + *(uint16 *)(ptr) = value; } FORCEINLINE void WRITE_UINT32(void *ptr, uint32 value) { - struct Unaligned32 { uint32 val; } __attribute__ ((__packed__, __may_alias__)); - ((Unaligned32 *)ptr)->val = value; + *(uint32 *)(ptr) = value; } + // use software fallback by loading each byte explicitely #else -- cgit v1.2.3