[ARM] 3849/1: fix get_unaligned() for gcc >= 4.1
authorLennert Buytenhek <buytenh@wantstofly.org>
Thu, 21 Sep 2006 01:24:38 +0000 (02:24 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 25 Sep 2006 09:34:00 +0000 (10:34 +0100)
gcc 4.1's __typeof__ propagates 'const', which breaks get_unaligned().
Rewrite get_unaligned() not to use __typeof__.

Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
include/asm-arm/unaligned.h

index 1b39c2f..795b9e5 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <asm/types.h>
 
-extern int __bug_unaligned_x(void *ptr);
+extern int __bug_unaligned_x(const void *ptr);
 
 /*
  * What is the most efficient way of loading/storing an unaligned value?
@@ -51,44 +51,32 @@ extern int __bug_unaligned_x(void *ptr);
 #define __get_unaligned_4_be(__p)                                      \
        (__p[0] << 24 | __p[1] << 16 | __p[2] << 8 | __p[3])
 
-#define __get_unaligned_le(ptr)                                        \
-       ({                                                      \
-               __typeof__(*(ptr)) __v;                         \
-               __u8 *__p = (__u8 *)(ptr);                      \
-               switch (sizeof(*(ptr))) {                       \
-               case 1: __v = *(ptr);                   break;  \
-               case 2: __v = __get_unaligned_2_le(__p);        break;  \
-               case 4: __v = __get_unaligned_4_le(__p);        break;  \
-               case 8: {                                       \
-                               unsigned int __v1, __v2;        \
-                               __v2 = __get_unaligned_4_le((__p+4)); \
-                               __v1 = __get_unaligned_4_le(__p);       \
-                               __v = ((unsigned long long)__v2 << 32 | __v1);  \
-                       }                                       \
-                       break;                                  \
-               default: __v = __bug_unaligned_x(__p);  break;  \
-               }                                               \
-               __v;                                            \
+#define __get_unaligned_8_le(__p)                                      \
+       ((unsigned long long)__get_unaligned_4_le((__p+4)) << 32 |      \
+               __get_unaligned_4_le(__p))
+
+#define __get_unaligned_8_be(__p)                                      \
+       ((unsigned long long)__get_unaligned_4_be(__p) << 32 |          \
+               __get_unaligned_4_be((__p+4)))
+
+#define __get_unaligned_le(ptr)                                                \
+       ({                                                              \
+               const __u8 *__p = (const __u8 *)(ptr);                  \
+               __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p,        \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_le(__p), \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_le(__p), \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_le(__p), \
+                   (void)__bug_unaligned_x(__p)))));                   \
        })
 
-#define __get_unaligned_be(ptr)                                        \
-       ({                                                      \
-               __typeof__(*(ptr)) __v;                         \
-               __u8 *__p = (__u8 *)(ptr);                      \
-               switch (sizeof(*(ptr))) {                       \
-               case 1: __v = *(ptr);                   break;  \
-               case 2: __v = __get_unaligned_2_be(__p);        break;  \
-               case 4: __v = __get_unaligned_4_be(__p);        break;  \
-               case 8: {                                       \
-                               unsigned int __v1, __v2;        \
-                               __v2 = __get_unaligned_4_be(__p); \
-                               __v1 = __get_unaligned_4_be((__p+4));   \
-                               __v = ((unsigned long long)__v2 << 32 | __v1);  \
-                       }                                       \
-                       break;                                  \
-               default: __v = __bug_unaligned_x(__p);  break;  \
-               }                                               \
-               __v;                                            \
+#define __get_unaligned_be(ptr)                                                \
+       ({                                                              \
+               const __u8 *__p = (const __u8 *)(ptr);                  \
+               __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p,        \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_be(__p), \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_be(__p), \
+                 __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_be(__p), \
+                   (void)__bug_unaligned_x(__p)))));                   \
        })