1 /* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
2 /*
3 * Copyright (c) Yann Collet, Facebook, Inc.
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 *****************************************************************/
MEM_32bits(void)90 MEM_STATIC unsigned MEM_32bits(void)
91 {
92 return sizeof(size_t) == 4;
93 }
94
MEM_64bits(void)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
MEM_isLittleEndian(void)106 MEM_STATIC unsigned MEM_isLittleEndian(void)
107 {
108 return MEM_LITTLE_ENDIAN;
109 }
110
MEM_read16(const void * memPtr)111 MEM_STATIC U16 MEM_read16(const void *memPtr)
112 {
113 return get_unaligned((const U16 *)memPtr);
114 }
115
MEM_read32(const void * memPtr)116 MEM_STATIC U32 MEM_read32(const void *memPtr)
117 {
118 return get_unaligned((const U32 *)memPtr);
119 }
120
MEM_read64(const void * memPtr)121 MEM_STATIC U64 MEM_read64(const void *memPtr)
122 {
123 return get_unaligned((const U64 *)memPtr);
124 }
125
MEM_readST(const void * memPtr)126 MEM_STATIC size_t MEM_readST(const void *memPtr)
127 {
128 return get_unaligned((const size_t *)memPtr);
129 }
130
MEM_write16(void * memPtr,U16 value)131 MEM_STATIC void MEM_write16(void *memPtr, U16 value)
132 {
133 put_unaligned(value, (U16 *)memPtr);
134 }
135
MEM_write32(void * memPtr,U32 value)136 MEM_STATIC void MEM_write32(void *memPtr, U32 value)
137 {
138 put_unaligned(value, (U32 *)memPtr);
139 }
140
MEM_write64(void * memPtr,U64 value)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
MEM_readLE16(const void * memPtr)148 MEM_STATIC U16 MEM_readLE16(const void *memPtr)
149 {
150 return get_unaligned_le16(memPtr);
151 }
152
MEM_writeLE16(void * memPtr,U16 val)153 MEM_STATIC void MEM_writeLE16(void *memPtr, U16 val)
154 {
155 put_unaligned_le16(val, memPtr);
156 }
157
MEM_readLE24(const void * memPtr)158 MEM_STATIC U32 MEM_readLE24(const void *memPtr)
159 {
160 return MEM_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16);
161 }
162
MEM_writeLE24(void * memPtr,U32 val)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
MEM_readLE32(const void * memPtr)169 MEM_STATIC U32 MEM_readLE32(const void *memPtr)
170 {
171 return get_unaligned_le32(memPtr);
172 }
173
MEM_writeLE32(void * memPtr,U32 val32)174 MEM_STATIC void MEM_writeLE32(void *memPtr, U32 val32)
175 {
176 put_unaligned_le32(val32, memPtr);
177 }
178
MEM_readLE64(const void * memPtr)179 MEM_STATIC U64 MEM_readLE64(const void *memPtr)
180 {
181 return get_unaligned_le64(memPtr);
182 }
183
MEM_writeLE64(void * memPtr,U64 val64)184 MEM_STATIC void MEM_writeLE64(void *memPtr, U64 val64)
185 {
186 put_unaligned_le64(val64, memPtr);
187 }
188
MEM_readLEST(const void * memPtr)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
MEM_writeLEST(void * memPtr,size_t val)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
MEM_readBE32(const void * memPtr)207 MEM_STATIC U32 MEM_readBE32(const void *memPtr)
208 {
209 return get_unaligned_be32(memPtr);
210 }
211
MEM_writeBE32(void * memPtr,U32 val32)212 MEM_STATIC void MEM_writeBE32(void *memPtr, U32 val32)
213 {
214 put_unaligned_be32(val32, memPtr);
215 }
216
MEM_readBE64(const void * memPtr)217 MEM_STATIC U64 MEM_readBE64(const void *memPtr)
218 {
219 return get_unaligned_be64(memPtr);
220 }
221
MEM_writeBE64(void * memPtr,U64 val64)222 MEM_STATIC void MEM_writeBE64(void *memPtr, U64 val64)
223 {
224 put_unaligned_be64(val64, memPtr);
225 }
226
MEM_readBEST(const void * memPtr)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
MEM_writeBEST(void * memPtr,size_t val)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
MEM_swap32(U32 in)243 MEM_STATIC U32 MEM_swap32(U32 in)
244 {
245 return swab32(in);
246 }
247
MEM_swap64(U64 in)248 MEM_STATIC U64 MEM_swap64(U64 in)
249 {
250 return swab64(in);
251 }
252
MEM_swapST(size_t in)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 */
262