1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef __ASM_GENERIC_UNALIGNED_H |
3 | #define __ASM_GENERIC_UNALIGNED_H |
4 | |
5 | /* |
6 | * This is the most generic implementation of unaligned accesses |
7 | * and should work almost anywhere. |
8 | */ |
9 | #include <linux/unaligned/packed_struct.h> |
10 | #include <asm/byteorder.h> |
11 | |
12 | #define __get_unaligned_t(type, ptr) ({ \ |
13 | const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ |
14 | __pptr->x; \ |
15 | }) |
16 | |
17 | #define __put_unaligned_t(type, val, ptr) do { \ |
18 | struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ |
19 | __pptr->x = (val); \ |
20 | } while (0) |
21 | |
22 | #define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr)) |
23 | #define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr)) |
24 | |
25 | static inline u16 get_unaligned_le16(const void *p) |
26 | { |
27 | return le16_to_cpu(__get_unaligned_t(__le16, p)); |
28 | } |
29 | |
30 | static inline u32 get_unaligned_le32(const void *p) |
31 | { |
32 | return le32_to_cpu(__get_unaligned_t(__le32, p)); |
33 | } |
34 | |
35 | static inline u64 get_unaligned_le64(const void *p) |
36 | { |
37 | return le64_to_cpu(__get_unaligned_t(__le64, p)); |
38 | } |
39 | |
40 | static inline void put_unaligned_le16(u16 val, void *p) |
41 | { |
42 | __put_unaligned_t(__le16, cpu_to_le16(val), p); |
43 | } |
44 | |
45 | static inline void put_unaligned_le32(u32 val, void *p) |
46 | { |
47 | __put_unaligned_t(__le32, cpu_to_le32(val), p); |
48 | } |
49 | |
50 | static inline void put_unaligned_le64(u64 val, void *p) |
51 | { |
52 | __put_unaligned_t(__le64, cpu_to_le64(val), p); |
53 | } |
54 | |
55 | static inline u16 get_unaligned_be16(const void *p) |
56 | { |
57 | return be16_to_cpu(__get_unaligned_t(__be16, p)); |
58 | } |
59 | |
60 | static inline u32 get_unaligned_be32(const void *p) |
61 | { |
62 | return be32_to_cpu(__get_unaligned_t(__be32, p)); |
63 | } |
64 | |
65 | static inline u64 get_unaligned_be64(const void *p) |
66 | { |
67 | return be64_to_cpu(__get_unaligned_t(__be64, p)); |
68 | } |
69 | |
70 | static inline void put_unaligned_be16(u16 val, void *p) |
71 | { |
72 | __put_unaligned_t(__be16, cpu_to_be16(val), p); |
73 | } |
74 | |
75 | static inline void put_unaligned_be32(u32 val, void *p) |
76 | { |
77 | __put_unaligned_t(__be32, cpu_to_be32(val), p); |
78 | } |
79 | |
80 | static inline void put_unaligned_be64(u64 val, void *p) |
81 | { |
82 | __put_unaligned_t(__be64, cpu_to_be64(val), p); |
83 | } |
84 | |
85 | static inline u32 __get_unaligned_be24(const u8 *p) |
86 | { |
87 | return p[0] << 16 | p[1] << 8 | p[2]; |
88 | } |
89 | |
90 | static inline u32 get_unaligned_be24(const void *p) |
91 | { |
92 | return __get_unaligned_be24(p); |
93 | } |
94 | |
95 | static inline u32 __get_unaligned_le24(const u8 *p) |
96 | { |
97 | return p[0] | p[1] << 8 | p[2] << 16; |
98 | } |
99 | |
100 | static inline u32 get_unaligned_le24(const void *p) |
101 | { |
102 | return __get_unaligned_le24(p); |
103 | } |
104 | |
105 | static inline void __put_unaligned_be24(const u32 val, u8 *p) |
106 | { |
107 | *p++ = val >> 16; |
108 | *p++ = val >> 8; |
109 | *p++ = val; |
110 | } |
111 | |
112 | static inline void put_unaligned_be24(const u32 val, void *p) |
113 | { |
114 | __put_unaligned_be24(val, p); |
115 | } |
116 | |
117 | static inline void __put_unaligned_le24(const u32 val, u8 *p) |
118 | { |
119 | *p++ = val; |
120 | *p++ = val >> 8; |
121 | *p++ = val >> 16; |
122 | } |
123 | |
124 | static inline void put_unaligned_le24(const u32 val, void *p) |
125 | { |
126 | __put_unaligned_le24(val, p); |
127 | } |
128 | |
129 | static inline void __put_unaligned_be48(const u64 val, u8 *p) |
130 | { |
131 | *p++ = val >> 40; |
132 | *p++ = val >> 32; |
133 | *p++ = val >> 24; |
134 | *p++ = val >> 16; |
135 | *p++ = val >> 8; |
136 | *p++ = val; |
137 | } |
138 | |
139 | static inline void put_unaligned_be48(const u64 val, void *p) |
140 | { |
141 | __put_unaligned_be48(val, p); |
142 | } |
143 | |
144 | static inline u64 __get_unaligned_be48(const u8 *p) |
145 | { |
146 | return (u64)p[0] << 40 | (u64)p[1] << 32 | (u64)p[2] << 24 | |
147 | p[3] << 16 | p[4] << 8 | p[5]; |
148 | } |
149 | |
150 | static inline u64 get_unaligned_be48(const void *p) |
151 | { |
152 | return __get_unaligned_be48(p); |
153 | } |
154 | |
155 | #endif /* __ASM_GENERIC_UNALIGNED_H */ |
156 | |