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 *****************************************************************/ 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 */ 262