Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
aafe4dbe AB |
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. | |
aafe4dbe | 8 | */ |
803f4e1e | 9 | #include <linux/unaligned/packed_struct.h> |
aafe4dbe AB |
10 | #include <asm/byteorder.h> |
11 | ||
803f4e1e AB |
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 | } | |
aafe4dbe | 128 | |
7b9e664b | 129 | static inline void __put_unaligned_be48(const u64 val, u8 *p) |
c2ea5fcf KB |
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 | { | |
b9768752 | 146 | return (u64)p[0] << 40 | (u64)p[1] << 32 | (u64)p[2] << 24 | |
c2ea5fcf KB |
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 | ||
aafe4dbe | 155 | #endif /* __ASM_GENERIC_UNALIGNED_H */ |