GNU Linux-libre 4.14.290-gnu1
[releases.git] / include / linux / unaligned / generic.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_UNALIGNED_GENERIC_H
3 #define _LINUX_UNALIGNED_GENERIC_H
4
5 /*
6  * Cause a link-time error if we try an unaligned access other than
7  * 1,2,4 or 8 bytes long
8  */
9 extern void __bad_unaligned_access_size(void);
10
11 #define __get_unaligned_le(ptr) ((__force typeof(*(ptr)))({                     \
12         __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),                      \
13         __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)),   \
14         __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)),   \
15         __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)),   \
16         __bad_unaligned_access_size()))));                                      \
17         }))
18
19 #define __get_unaligned_be(ptr) ((__force typeof(*(ptr)))({                     \
20         __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),                      \
21         __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)),   \
22         __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)),   \
23         __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)),   \
24         __bad_unaligned_access_size()))));                                      \
25         }))
26
27 #define __put_unaligned_le(val, ptr) ({                                 \
28         void *__gu_p = (ptr);                                           \
29         switch (sizeof(*(ptr))) {                                       \
30         case 1:                                                         \
31                 *(u8 *)__gu_p = (__force u8)(val);                      \
32                 break;                                                  \
33         case 2:                                                         \
34                 put_unaligned_le16((__force u16)(val), __gu_p);         \
35                 break;                                                  \
36         case 4:                                                         \
37                 put_unaligned_le32((__force u32)(val), __gu_p);         \
38                 break;                                                  \
39         case 8:                                                         \
40                 put_unaligned_le64((__force u64)(val), __gu_p);         \
41                 break;                                                  \
42         default:                                                        \
43                 __bad_unaligned_access_size();                          \
44                 break;                                                  \
45         }                                                               \
46         (void)0; })
47
48 #define __put_unaligned_be(val, ptr) ({                                 \
49         void *__gu_p = (ptr);                                           \
50         switch (sizeof(*(ptr))) {                                       \
51         case 1:                                                         \
52                 *(u8 *)__gu_p = (__force u8)(val);                      \
53                 break;                                                  \
54         case 2:                                                         \
55                 put_unaligned_be16((__force u16)(val), __gu_p);         \
56                 break;                                                  \
57         case 4:                                                         \
58                 put_unaligned_be32((__force u32)(val), __gu_p);         \
59                 break;                                                  \
60         case 8:                                                         \
61                 put_unaligned_be64((__force u64)(val), __gu_p);         \
62                 break;                                                  \
63         default:                                                        \
64                 __bad_unaligned_access_size();                          \
65                 break;                                                  \
66         }                                                               \
67         (void)0; })
68
69 #endif /* _LINUX_UNALIGNED_GENERIC_H */