648db22b |
1 | /* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ |
2 | /* |
3 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
4 | * All rights reserved. |
5 | * |
6 | * This source code is licensed under both the BSD-style license (found in the |
7 | * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
8 | * in the COPYING file in the root directory of this source tree). |
9 | * You may select, at your option, one of the above-listed licenses. |
10 | */ |
11 | |
12 | #ifndef MEM_H_MODULE |
13 | #define MEM_H_MODULE |
14 | |
15 | /*-**************************************** |
16 | * Dependencies |
17 | ******************************************/ |
18 | #include <asm/unaligned.h> /* get_unaligned, put_unaligned* */ |
19 | #include <linux/compiler.h> /* inline */ |
20 | #include <linux/swab.h> /* swab32, swab64 */ |
21 | #include <linux/types.h> /* size_t, ptrdiff_t */ |
22 | #include "debug.h" /* DEBUG_STATIC_ASSERT */ |
23 | |
24 | /*-**************************************** |
25 | * Compiler specifics |
26 | ******************************************/ |
27 | #define MEM_STATIC static inline |
28 | |
29 | /*-************************************************************** |
30 | * Basic Types |
31 | *****************************************************************/ |
32 | typedef uint8_t BYTE; |
33 | typedef uint8_t U8; |
34 | typedef int8_t S8; |
35 | typedef uint16_t U16; |
36 | typedef int16_t S16; |
37 | typedef uint32_t U32; |
38 | typedef int32_t S32; |
39 | typedef uint64_t U64; |
40 | typedef int64_t S64; |
41 | |
42 | /*-************************************************************** |
43 | * Memory I/O API |
44 | *****************************************************************/ |
45 | /*=== Static platform detection ===*/ |
46 | MEM_STATIC unsigned MEM_32bits(void); |
47 | MEM_STATIC unsigned MEM_64bits(void); |
48 | MEM_STATIC unsigned MEM_isLittleEndian(void); |
49 | |
50 | /*=== Native unaligned read/write ===*/ |
51 | MEM_STATIC U16 MEM_read16(const void* memPtr); |
52 | MEM_STATIC U32 MEM_read32(const void* memPtr); |
53 | MEM_STATIC U64 MEM_read64(const void* memPtr); |
54 | MEM_STATIC size_t MEM_readST(const void* memPtr); |
55 | |
56 | MEM_STATIC void MEM_write16(void* memPtr, U16 value); |
57 | MEM_STATIC void MEM_write32(void* memPtr, U32 value); |
58 | MEM_STATIC void MEM_write64(void* memPtr, U64 value); |
59 | |
60 | /*=== Little endian unaligned read/write ===*/ |
61 | MEM_STATIC U16 MEM_readLE16(const void* memPtr); |
62 | MEM_STATIC U32 MEM_readLE24(const void* memPtr); |
63 | MEM_STATIC U32 MEM_readLE32(const void* memPtr); |
64 | MEM_STATIC U64 MEM_readLE64(const void* memPtr); |
65 | MEM_STATIC size_t MEM_readLEST(const void* memPtr); |
66 | |
67 | MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val); |
68 | MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val); |
69 | MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32); |
70 | MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64); |
71 | MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val); |
72 | |
73 | /*=== Big endian unaligned read/write ===*/ |
74 | MEM_STATIC U32 MEM_readBE32(const void* memPtr); |
75 | MEM_STATIC U64 MEM_readBE64(const void* memPtr); |
76 | MEM_STATIC size_t MEM_readBEST(const void* memPtr); |
77 | |
78 | MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32); |
79 | MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64); |
80 | MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val); |
81 | |
82 | /*=== Byteswap ===*/ |
83 | MEM_STATIC U32 MEM_swap32(U32 in); |
84 | MEM_STATIC U64 MEM_swap64(U64 in); |
85 | MEM_STATIC size_t MEM_swapST(size_t in); |
86 | |
87 | /*-************************************************************** |
88 | * Memory I/O Implementation |
89 | *****************************************************************/ |
90 | MEM_STATIC unsigned MEM_32bits(void) |
91 | { |
92 | return sizeof(size_t) == 4; |
93 | } |
94 | |
95 | MEM_STATIC unsigned MEM_64bits(void) |
96 | { |
97 | return sizeof(size_t) == 8; |
98 | } |
99 | |
100 | #if defined(__LITTLE_ENDIAN) |
101 | #define MEM_LITTLE_ENDIAN 1 |
102 | #else |
103 | #define MEM_LITTLE_ENDIAN 0 |
104 | #endif |
105 | |
106 | MEM_STATIC unsigned MEM_isLittleEndian(void) |
107 | { |
108 | return MEM_LITTLE_ENDIAN; |
109 | } |
110 | |
111 | MEM_STATIC U16 MEM_read16(const void *memPtr) |
112 | { |
113 | return get_unaligned((const U16 *)memPtr); |
114 | } |
115 | |
116 | MEM_STATIC U32 MEM_read32(const void *memPtr) |
117 | { |
118 | return get_unaligned((const U32 *)memPtr); |
119 | } |
120 | |
121 | MEM_STATIC U64 MEM_read64(const void *memPtr) |
122 | { |
123 | return get_unaligned((const U64 *)memPtr); |
124 | } |
125 | |
126 | MEM_STATIC size_t MEM_readST(const void *memPtr) |
127 | { |
128 | return get_unaligned((const size_t *)memPtr); |
129 | } |
130 | |
131 | MEM_STATIC void MEM_write16(void *memPtr, U16 value) |
132 | { |
133 | put_unaligned(value, (U16 *)memPtr); |
134 | } |
135 | |
136 | MEM_STATIC void MEM_write32(void *memPtr, U32 value) |
137 | { |
138 | put_unaligned(value, (U32 *)memPtr); |
139 | } |
140 | |
141 | MEM_STATIC void MEM_write64(void *memPtr, U64 value) |
142 | { |
143 | put_unaligned(value, (U64 *)memPtr); |
144 | } |
145 | |
146 | /*=== Little endian r/w ===*/ |
147 | |
148 | MEM_STATIC U16 MEM_readLE16(const void *memPtr) |
149 | { |
150 | return get_unaligned_le16(memPtr); |
151 | } |
152 | |
153 | MEM_STATIC void MEM_writeLE16(void *memPtr, U16 val) |
154 | { |
155 | put_unaligned_le16(val, memPtr); |
156 | } |
157 | |
158 | MEM_STATIC U32 MEM_readLE24(const void *memPtr) |
159 | { |
160 | return MEM_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16); |
161 | } |
162 | |
163 | MEM_STATIC void MEM_writeLE24(void *memPtr, U32 val) |
164 | { |
165 | MEM_writeLE16(memPtr, (U16)val); |
166 | ((BYTE *)memPtr)[2] = (BYTE)(val >> 16); |
167 | } |
168 | |
169 | MEM_STATIC U32 MEM_readLE32(const void *memPtr) |
170 | { |
171 | return get_unaligned_le32(memPtr); |
172 | } |
173 | |
174 | MEM_STATIC void MEM_writeLE32(void *memPtr, U32 val32) |
175 | { |
176 | put_unaligned_le32(val32, memPtr); |
177 | } |
178 | |
179 | MEM_STATIC U64 MEM_readLE64(const void *memPtr) |
180 | { |
181 | return get_unaligned_le64(memPtr); |
182 | } |
183 | |
184 | MEM_STATIC void MEM_writeLE64(void *memPtr, U64 val64) |
185 | { |
186 | put_unaligned_le64(val64, memPtr); |
187 | } |
188 | |
189 | MEM_STATIC size_t MEM_readLEST(const void *memPtr) |
190 | { |
191 | if (MEM_32bits()) |
192 | return (size_t)MEM_readLE32(memPtr); |
193 | else |
194 | return (size_t)MEM_readLE64(memPtr); |
195 | } |
196 | |
197 | MEM_STATIC void MEM_writeLEST(void *memPtr, size_t val) |
198 | { |
199 | if (MEM_32bits()) |
200 | MEM_writeLE32(memPtr, (U32)val); |
201 | else |
202 | MEM_writeLE64(memPtr, (U64)val); |
203 | } |
204 | |
205 | /*=== Big endian r/w ===*/ |
206 | |
207 | MEM_STATIC U32 MEM_readBE32(const void *memPtr) |
208 | { |
209 | return get_unaligned_be32(memPtr); |
210 | } |
211 | |
212 | MEM_STATIC void MEM_writeBE32(void *memPtr, U32 val32) |
213 | { |
214 | put_unaligned_be32(val32, memPtr); |
215 | } |
216 | |
217 | MEM_STATIC U64 MEM_readBE64(const void *memPtr) |
218 | { |
219 | return get_unaligned_be64(memPtr); |
220 | } |
221 | |
222 | MEM_STATIC void MEM_writeBE64(void *memPtr, U64 val64) |
223 | { |
224 | put_unaligned_be64(val64, memPtr); |
225 | } |
226 | |
227 | MEM_STATIC size_t MEM_readBEST(const void *memPtr) |
228 | { |
229 | if (MEM_32bits()) |
230 | return (size_t)MEM_readBE32(memPtr); |
231 | else |
232 | return (size_t)MEM_readBE64(memPtr); |
233 | } |
234 | |
235 | MEM_STATIC void MEM_writeBEST(void *memPtr, size_t val) |
236 | { |
237 | if (MEM_32bits()) |
238 | MEM_writeBE32(memPtr, (U32)val); |
239 | else |
240 | MEM_writeBE64(memPtr, (U64)val); |
241 | } |
242 | |
243 | MEM_STATIC U32 MEM_swap32(U32 in) |
244 | { |
245 | return swab32(in); |
246 | } |
247 | |
248 | MEM_STATIC U64 MEM_swap64(U64 in) |
249 | { |
250 | return swab64(in); |
251 | } |
252 | |
253 | MEM_STATIC size_t MEM_swapST(size_t in) |
254 | { |
255 | if (MEM_32bits()) |
256 | return (size_t)MEM_swap32((U32)in); |
257 | else |
258 | return (size_t)MEM_swap64((U64)in); |
259 | } |
260 | |
261 | #endif /* MEM_H_MODULE */ |