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