• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_UNALIGNED_GENERIC_H
3 #define _LINUX_UNALIGNED_GENERIC_H
4 
5 #include <linux/types.h>
6 
7 /*
8  * Cause a link-time error if we try an unaligned access other than
9  * 1,2,4 or 8 bytes long
10  */
11 extern void __bad_unaligned_access_size(void);
12 
13 #define __get_unaligned_le(ptr) ((__force typeof(*(ptr)))({			\
14 	__builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),			\
15 	__builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)),	\
16 	__builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)),	\
17 	__builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)),	\
18 	__bad_unaligned_access_size()))));					\
19 	}))
20 
21 #define __get_unaligned_be(ptr) ((__force typeof(*(ptr)))({			\
22 	__builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),			\
23 	__builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)),	\
24 	__builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)),	\
25 	__builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)),	\
26 	__bad_unaligned_access_size()))));					\
27 	}))
28 
29 #define __put_unaligned_le(val, ptr) ({					\
30 	void *__gu_p = (ptr);						\
31 	switch (sizeof(*(ptr))) {					\
32 	case 1:								\
33 		*(u8 *)__gu_p = (__force u8)(val);			\
34 		break;							\
35 	case 2:								\
36 		put_unaligned_le16((__force u16)(val), __gu_p);		\
37 		break;							\
38 	case 4:								\
39 		put_unaligned_le32((__force u32)(val), __gu_p);		\
40 		break;							\
41 	case 8:								\
42 		put_unaligned_le64((__force u64)(val), __gu_p);		\
43 		break;							\
44 	default:							\
45 		__bad_unaligned_access_size();				\
46 		break;							\
47 	}								\
48 	(void)0; })
49 
50 #define __put_unaligned_be(val, ptr) ({					\
51 	void *__gu_p = (ptr);						\
52 	switch (sizeof(*(ptr))) {					\
53 	case 1:								\
54 		*(u8 *)__gu_p = (__force u8)(val);			\
55 		break;							\
56 	case 2:								\
57 		put_unaligned_be16((__force u16)(val), __gu_p);		\
58 		break;							\
59 	case 4:								\
60 		put_unaligned_be32((__force u32)(val), __gu_p);		\
61 		break;							\
62 	case 8:								\
63 		put_unaligned_be64((__force u64)(val), __gu_p);		\
64 		break;							\
65 	default:							\
66 		__bad_unaligned_access_size();				\
67 		break;							\
68 	}								\
69 	(void)0; })
70 
__get_unaligned_be24(const u8 * p)71 static inline u32 __get_unaligned_be24(const u8 *p)
72 {
73 	return p[0] << 16 | p[1] << 8 | p[2];
74 }
75 
get_unaligned_be24(const void * p)76 static inline u32 get_unaligned_be24(const void *p)
77 {
78 	return __get_unaligned_be24(p);
79 }
80 
__get_unaligned_le24(const u8 * p)81 static inline u32 __get_unaligned_le24(const u8 *p)
82 {
83 	return p[0] | p[1] << 8 | p[2] << 16;
84 }
85 
get_unaligned_le24(const void * p)86 static inline u32 get_unaligned_le24(const void *p)
87 {
88 	return __get_unaligned_le24(p);
89 }
90 
__put_unaligned_be24(const u32 val,u8 * p)91 static inline void __put_unaligned_be24(const u32 val, u8 *p)
92 {
93 	*p++ = val >> 16;
94 	*p++ = val >> 8;
95 	*p++ = val;
96 }
97 
put_unaligned_be24(const u32 val,void * p)98 static inline void put_unaligned_be24(const u32 val, void *p)
99 {
100 	__put_unaligned_be24(val, p);
101 }
102 
__put_unaligned_le24(const u32 val,u8 * p)103 static inline void __put_unaligned_le24(const u32 val, u8 *p)
104 {
105 	*p++ = val;
106 	*p++ = val >> 8;
107 	*p++ = val >> 16;
108 }
109 
put_unaligned_le24(const u32 val,void * p)110 static inline void put_unaligned_le24(const u32 val, void *p)
111 {
112 	__put_unaligned_le24(val, p);
113 }
114 
115 #endif /* _LINUX_UNALIGNED_GENERIC_H */
116