aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMax Horn2011-05-10 15:38:10 +0200
committerMax Horn2011-05-10 15:38:18 +0200
commit9511af6682f3a81e5956b43c1af1748c289191a8 (patch)
treebb58728bedf096c426cc550f3a0e0ade7128ae4b /common
parent5bf8a0bf846a5d3d0a02b8186de00518ca437c80 (diff)
downloadscummvm-rg350-9511af6682f3a81e5956b43c1af1748c289191a8.tar.gz
scummvm-rg350-9511af6682f3a81e5956b43c1af1748c289191a8.tar.bz2
scummvm-rg350-9511af6682f3a81e5956b43c1af1748c289191a8.zip
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.
Diffstat (limited to 'common')
-rw-r--r--common/endian.h44
1 files 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:
+// <http://thread.gmane.org/gmane.games.devel.scummvm/8063>
+//
+// 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:
-// <http://thread.gmane.org/gmane.games.devel.scummvm/8063>
-#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