1 #ifndef _ASM_GENERIC_UNALIGNED_H_
2 #define _ASM_GENERIC_UNALIGNED_H_
5 * For the benefit of those who are trying to port Linux to another
6 * architecture, here are some C-language equivalents.
8 * This is based almost entirely upon Richard Henderson's
9 * asm-alpha/unaligned.h implementation. Some comments were
10 * taken from David Mosberger's asm-ia64/unaligned.h header.
13 #include <linux/types.h>
15 struct __una_u64
{ __u64 x
; } __attribute__((packed
));
16 struct __una_u32
{ __u32 x
; } __attribute__((packed
));
17 struct __una_u16
{ __u16 x
; } __attribute__((packed
));
20 * Elemental unaligned loads
23 static inline __u64
__get_unaligned_cpu64(const void *addr
)
25 const struct __una_u64
*ptr
= (const struct __una_u64
*) addr
;
29 static inline __u32
__get_unaligned_cpu32(const void *addr
)
31 const struct __una_u32
*ptr
= (const struct __una_u32
*) addr
;
35 static inline __u16
__get_unaligned_cpu16(const void *addr
)
37 const struct __una_u16
*ptr
= (const struct __una_u16
*) addr
;
42 * Elemental unaligned stores
45 static inline void __put_unaligned_cpu64(__u64 val
, void *addr
)
47 struct __una_u64
*ptr
= (struct __una_u64
*) addr
;
51 static inline void __put_unaligned_cpu32(__u32 val
, void *addr
)
53 struct __una_u32
*ptr
= (struct __una_u32
*) addr
;
57 static inline void __put_unaligned_cpu16(__u16 val
, void *addr
)
59 struct __una_u16
*ptr
= (struct __una_u16
*) addr
;
63 #include <asm/byteorder.h>
65 #if defined(__LITTLE_ENDIAN)
66 # include <linux/unaligned/le_struct.h>
67 # include <linux/unaligned/be_byteshift.h>
68 # define get_unaligned __get_unaligned_le
69 # define put_unaligned __put_unaligned_le
70 #elif defined(__BIG_ENDIAN)
71 # include <linux/unaligned/be_struct.h>
72 # include <linux/unaligned/le_byteshift.h>
73 # define get_unaligned __get_unaligned_be
74 # define put_unaligned __put_unaligned_be
76 # error need to define endianess
80 * Cause a link-time error if we try an unaligned access other than
81 * 1,2,4 or 8 bytes long
83 extern void __bad_unaligned_access_size(void);
85 #define __get_unaligned_le(ptr) ((__force typeof(*(ptr)))({ \
86 __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \
87 __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)), \
88 __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)), \
89 __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)), \
90 __bad_unaligned_access_size())))); \
93 #define __get_unaligned_be(ptr) ((__force typeof(*(ptr)))({ \
94 __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr), \
95 __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)), \
96 __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)), \
97 __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)), \
98 __bad_unaligned_access_size())))); \
101 #define __put_unaligned_le(val, ptr) ({ \
102 void *__gu_p = (ptr); \
103 switch (sizeof(*(ptr))) { \
105 *(u8 *)__gu_p = (__force u8)(val); \
108 put_unaligned_le16((__force u16)(val), __gu_p); \
111 put_unaligned_le32((__force u32)(val), __gu_p); \
114 put_unaligned_le64((__force u64)(val), __gu_p); \
117 __bad_unaligned_access_size(); \
122 #define __put_unaligned_be(val, ptr) ({ \
123 void *__gu_p = (ptr); \
124 switch (sizeof(*(ptr))) { \
126 *(u8 *)__gu_p = (__force u8)(val); \
129 put_unaligned_be16((__force u16)(val), __gu_p); \
132 put_unaligned_be32((__force u32)(val), __gu_p); \
135 put_unaligned_be64((__force u64)(val), __gu_p); \
138 __bad_unaligned_access_size(); \
143 #endif /* _ASM_GENERIC_UNALIGNED_H */