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 uint16_t U16; 34 typedef int16_t S16; 35 typedef uint32_t U32; 36 typedef int32_t S32; 37 typedef uint64_t U64; 38 typedef int64_t S64; 39 40 /*-************************************************************** 41 * Memory I/O API 42 *****************************************************************/ 43 /*=== Static platform detection ===*/ 44 MEM_STATIC unsigned MEM_32bits(void); 45 MEM_STATIC unsigned MEM_64bits(void); 46 MEM_STATIC unsigned MEM_isLittleEndian(void); 47 48 /*=== Native unaligned read/write ===*/ 49 MEM_STATIC U16 MEM_read16(const void* memPtr); 50 MEM_STATIC U32 MEM_read32(const void* memPtr); 51 MEM_STATIC U64 MEM_read64(const void* memPtr); 52 MEM_STATIC size_t MEM_readST(const void* memPtr); 53 54 MEM_STATIC void MEM_write16(void* memPtr, U16 value); 55 MEM_STATIC void MEM_write32(void* memPtr, U32 value); 56 MEM_STATIC void MEM_write64(void* memPtr, U64 value); 57 58 /*=== Little endian unaligned read/write ===*/ 59 MEM_STATIC U16 MEM_readLE16(const void* memPtr); 60 MEM_STATIC U32 MEM_readLE24(const void* memPtr); 61 MEM_STATIC U32 MEM_readLE32(const void* memPtr); 62 MEM_STATIC U64 MEM_readLE64(const void* memPtr); 63 MEM_STATIC size_t MEM_readLEST(const void* memPtr); 64 65 MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val); 66 MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val); 67 MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32); 68 MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64); 69 MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val); 70 71 /*=== Big endian unaligned read/write ===*/ 72 MEM_STATIC U32 MEM_readBE32(const void* memPtr); 73 MEM_STATIC U64 MEM_readBE64(const void* memPtr); 74 MEM_STATIC size_t MEM_readBEST(const void* memPtr); 75 76 MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32); 77 MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64); 78 MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val); 79 80 /*=== Byteswap ===*/ 81 MEM_STATIC U32 MEM_swap32(U32 in); 82 MEM_STATIC U64 MEM_swap64(U64 in); 83 MEM_STATIC size_t MEM_swapST(size_t in); 84 85 /*-************************************************************** 86 * Memory I/O Implementation 87 *****************************************************************/ 88 MEM_STATIC unsigned MEM_32bits(void) 89 { 90 return sizeof(size_t) == 4; 91 } 92 93 MEM_STATIC unsigned MEM_64bits(void) 94 { 95 return sizeof(size_t) == 8; 96 } 97 98 #if defined(__LITTLE_ENDIAN) 99 #define MEM_LITTLE_ENDIAN 1 100 #else 101 #define MEM_LITTLE_ENDIAN 0 102 #endif 103 104 MEM_STATIC unsigned MEM_isLittleEndian(void) 105 { 106 return MEM_LITTLE_ENDIAN; 107 } 108 109 MEM_STATIC U16 MEM_read16(const void *memPtr) 110 { 111 return get_unaligned((const U16 *)memPtr); 112 } 113 114 MEM_STATIC U32 MEM_read32(const void *memPtr) 115 { 116 return get_unaligned((const U32 *)memPtr); 117 } 118 119 MEM_STATIC U64 MEM_read64(const void *memPtr) 120 { 121 return get_unaligned((const U64 *)memPtr); 122 } 123 124 MEM_STATIC size_t MEM_readST(const void *memPtr) 125 { 126 return get_unaligned((const size_t *)memPtr); 127 } 128 129 MEM_STATIC void MEM_write16(void *memPtr, U16 value) 130 { 131 put_unaligned(value, (U16 *)memPtr); 132 } 133 134 MEM_STATIC void MEM_write32(void *memPtr, U32 value) 135 { 136 put_unaligned(value, (U32 *)memPtr); 137 } 138 139 MEM_STATIC void MEM_write64(void *memPtr, U64 value) 140 { 141 put_unaligned(value, (U64 *)memPtr); 142 } 143 144 /*=== Little endian r/w ===*/ 145 146 MEM_STATIC U16 MEM_readLE16(const void *memPtr) 147 { 148 return get_unaligned_le16(memPtr); 149 } 150 151 MEM_STATIC void MEM_writeLE16(void *memPtr, U16 val) 152 { 153 put_unaligned_le16(val, memPtr); 154 } 155 156 MEM_STATIC U32 MEM_readLE24(const void *memPtr) 157 { 158 return MEM_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16); 159 } 160 161 MEM_STATIC void MEM_writeLE24(void *memPtr, U32 val) 162 { 163 MEM_writeLE16(memPtr, (U16)val); 164 ((BYTE *)memPtr)[2] = (BYTE)(val >> 16); 165 } 166 167 MEM_STATIC U32 MEM_readLE32(const void *memPtr) 168 { 169 return get_unaligned_le32(memPtr); 170 } 171 172 MEM_STATIC void MEM_writeLE32(void *memPtr, U32 val32) 173 { 174 put_unaligned_le32(val32, memPtr); 175 } 176 177 MEM_STATIC U64 MEM_readLE64(const void *memPtr) 178 { 179 return get_unaligned_le64(memPtr); 180 } 181 182 MEM_STATIC void MEM_writeLE64(void *memPtr, U64 val64) 183 { 184 put_unaligned_le64(val64, memPtr); 185 } 186 187 MEM_STATIC size_t MEM_readLEST(const void *memPtr) 188 { 189 if (MEM_32bits()) 190 return (size_t)MEM_readLE32(memPtr); 191 else 192 return (size_t)MEM_readLE64(memPtr); 193 } 194 195 MEM_STATIC void MEM_writeLEST(void *memPtr, size_t val) 196 { 197 if (MEM_32bits()) 198 MEM_writeLE32(memPtr, (U32)val); 199 else 200 MEM_writeLE64(memPtr, (U64)val); 201 } 202 203 /*=== Big endian r/w ===*/ 204 205 MEM_STATIC U32 MEM_readBE32(const void *memPtr) 206 { 207 return get_unaligned_be32(memPtr); 208 } 209 210 MEM_STATIC void MEM_writeBE32(void *memPtr, U32 val32) 211 { 212 put_unaligned_be32(val32, memPtr); 213 } 214 215 MEM_STATIC U64 MEM_readBE64(const void *memPtr) 216 { 217 return get_unaligned_be64(memPtr); 218 } 219 220 MEM_STATIC void MEM_writeBE64(void *memPtr, U64 val64) 221 { 222 put_unaligned_be64(val64, memPtr); 223 } 224 225 MEM_STATIC size_t MEM_readBEST(const void *memPtr) 226 { 227 if (MEM_32bits()) 228 return (size_t)MEM_readBE32(memPtr); 229 else 230 return (size_t)MEM_readBE64(memPtr); 231 } 232 233 MEM_STATIC void MEM_writeBEST(void *memPtr, size_t val) 234 { 235 if (MEM_32bits()) 236 MEM_writeBE32(memPtr, (U32)val); 237 else 238 MEM_writeBE64(memPtr, (U64)val); 239 } 240 241 MEM_STATIC U32 MEM_swap32(U32 in) 242 { 243 return swab32(in); 244 } 245 246 MEM_STATIC U64 MEM_swap64(U64 in) 247 { 248 return swab64(in); 249 } 250 251 MEM_STATIC size_t MEM_swapST(size_t in) 252 { 253 if (MEM_32bits()) 254 return (size_t)MEM_swap32((U32)in); 255 else 256 return (size_t)MEM_swap64((U64)in); 257 } 258 259 #endif /* MEM_H_MODULE */ 260