lowstar_endianness.h (7422B)
1 /* Copyright (c) INRIA and Microsoft Corporation. All rights reserved. 2 Licensed under the Apache 2.0 and MIT Licenses. */ 3 4 #ifndef KRML_HEADER_LOWSTAR_ENDIANNESS_H 5 #define KRML_HEADER_LOWSTAR_ENDIANNESS_H 6 7 #include <string.h> 8 #include <inttypes.h> 9 10 /******************************************************************************/ 11 /* Implementing C.fst (part 2: endian-ness macros) */ 12 /******************************************************************************/ 13 14 /* ... for Linux */ 15 #if defined(__linux__) || defined(__CYGWIN__) || defined(__USE_SYSTEM_ENDIAN_H__) || defined(__GLIBC__) 16 #include <endian.h> 17 18 /* ... for OSX */ 19 #elif defined(__APPLE__) 20 #include <libkern/OSByteOrder.h> 21 #define htole64(x) OSSwapHostToLittleInt64(x) 22 #define le64toh(x) OSSwapLittleToHostInt64(x) 23 #define htobe64(x) OSSwapHostToBigInt64(x) 24 #define be64toh(x) OSSwapBigToHostInt64(x) 25 26 #define htole16(x) OSSwapHostToLittleInt16(x) 27 #define le16toh(x) OSSwapLittleToHostInt16(x) 28 #define htobe16(x) OSSwapHostToBigInt16(x) 29 #define be16toh(x) OSSwapBigToHostInt16(x) 30 31 #define htole32(x) OSSwapHostToLittleInt32(x) 32 #define le32toh(x) OSSwapLittleToHostInt32(x) 33 #define htobe32(x) OSSwapHostToBigInt32(x) 34 #define be32toh(x) OSSwapBigToHostInt32(x) 35 36 /* ... for Solaris */ 37 #elif defined(__sun__) 38 #include <sys/byteorder.h> 39 #define htole64(x) LE_64(x) 40 #define le64toh(x) LE_64(x) 41 #define htobe64(x) BE_64(x) 42 #define be64toh(x) BE_64(x) 43 44 #define htole16(x) LE_16(x) 45 #define le16toh(x) LE_16(x) 46 #define htobe16(x) BE_16(x) 47 #define be16toh(x) BE_16(x) 48 49 #define htole32(x) LE_32(x) 50 #define le32toh(x) LE_32(x) 51 #define htobe32(x) BE_32(x) 52 #define be32toh(x) BE_32(x) 53 54 /* ... for the BSDs */ 55 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) 56 #include <sys/endian.h> 57 #elif defined(__OpenBSD__) 58 #include <endian.h> 59 60 /* ... for Windows (MSVC)... not targeting XBOX 360! */ 61 #elif defined(_MSC_VER) 62 63 #include <stdlib.h> 64 #define htobe16(x) _byteswap_ushort(x) 65 #define htole16(x) (x) 66 #define be16toh(x) _byteswap_ushort(x) 67 #define le16toh(x) (x) 68 69 #define htobe32(x) _byteswap_ulong(x) 70 #define htole32(x) (x) 71 #define be32toh(x) _byteswap_ulong(x) 72 #define le32toh(x) (x) 73 74 #define htobe64(x) _byteswap_uint64(x) 75 #define htole64(x) (x) 76 #define be64toh(x) _byteswap_uint64(x) 77 #define le64toh(x) (x) 78 79 /* ... for Windows (GCC-like, e.g. mingw or clang) */ 80 #elif (defined(_WIN32) || defined(_WIN64) || defined(__EMSCRIPTEN__)) && \ 81 (defined(__GNUC__) || defined(__clang__)) 82 83 #define htobe16(x) __builtin_bswap16(x) 84 #define htole16(x) (x) 85 #define be16toh(x) __builtin_bswap16(x) 86 #define le16toh(x) (x) 87 88 #define htobe32(x) __builtin_bswap32(x) 89 #define htole32(x) (x) 90 #define be32toh(x) __builtin_bswap32(x) 91 #define le32toh(x) (x) 92 93 #define htobe64(x) __builtin_bswap64(x) 94 #define htole64(x) (x) 95 #define be64toh(x) __builtin_bswap64(x) 96 #define le64toh(x) (x) 97 98 /* ... generic big-endian fallback code */ 99 /* ... AIX doesn't have __BYTE_ORDER__ (with XLC compiler) & is always big-endian */ 100 #elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || defined(_AIX) 101 102 /* byte swapping code inspired by: 103 * https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h 104 * */ 105 106 #define htobe32(x) (x) 107 #define be32toh(x) (x) 108 #define htole32(x) \ 109 (__extension__({ \ 110 uint32_t _temp = (x); \ 111 ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \ 112 ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \ 113 })) 114 #define le32toh(x) (htole32((x))) 115 116 #define htobe64(x) (x) 117 #define be64toh(x) (x) 118 #define htole64(x) \ 119 (__extension__({ \ 120 uint64_t __temp = (x); \ 121 uint32_t __low = htobe32((uint32_t)__temp); \ 122 uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \ 123 (((uint64_t)__low) << 32) | __high; \ 124 })) 125 #define le64toh(x) (htole64((x))) 126 127 /* ... generic little-endian fallback code */ 128 #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 129 130 #define htole32(x) (x) 131 #define le32toh(x) (x) 132 #define htobe32(x) \ 133 (__extension__({ \ 134 uint32_t _temp = (x); \ 135 ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \ 136 ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \ 137 })) 138 #define be32toh(x) (htobe32((x))) 139 140 #define htole64(x) (x) 141 #define le64toh(x) (x) 142 #define htobe64(x) \ 143 (__extension__({ \ 144 uint64_t __temp = (x); \ 145 uint32_t __low = htobe32((uint32_t)__temp); \ 146 uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \ 147 (((uint64_t)__low) << 32) | __high; \ 148 })) 149 #define be64toh(x) (htobe64((x))) 150 151 /* ... couldn't determine endian-ness of the target platform */ 152 #else 153 #error "Please define __BYTE_ORDER__!" 154 155 #endif /* defined(__linux__) || ... */ 156 157 /* Loads and stores. These avoid undefined behavior due to unaligned memory 158 * accesses, via memcpy. */ 159 160 inline static uint16_t 161 load16(uint8_t *b) 162 { 163 uint16_t x; 164 memcpy(&x, b, 2); 165 return x; 166 } 167 168 inline static uint32_t 169 load32(uint8_t *b) 170 { 171 uint32_t x; 172 memcpy(&x, b, 4); 173 return x; 174 } 175 176 inline static uint64_t 177 load64(uint8_t *b) 178 { 179 uint64_t x; 180 memcpy(&x, b, 8); 181 return x; 182 } 183 184 inline static void 185 store16(uint8_t *b, uint16_t i) 186 { 187 memcpy(b, &i, 2); 188 } 189 190 inline static void 191 store32(uint8_t *b, uint32_t i) 192 { 193 memcpy(b, &i, 4); 194 } 195 196 inline static void 197 store64(uint8_t *b, uint64_t i) 198 { 199 memcpy(b, &i, 8); 200 } 201 202 /* Legacy accessors so that this header can serve as an implementation of 203 * C.Endianness */ 204 #define load16_le(b) (le16toh(load16(b))) 205 #define store16_le(b, i) (store16(b, htole16(i))) 206 #define load16_be(b) (be16toh(load16(b))) 207 #define store16_be(b, i) (store16(b, htobe16(i))) 208 209 #define load32_le(b) (le32toh(load32(b))) 210 #define store32_le(b, i) (store32(b, htole32(i))) 211 #define load32_be(b) (be32toh(load32(b))) 212 #define store32_be(b, i) (store32(b, htobe32(i))) 213 214 #define load64_le(b) (le64toh(load64(b))) 215 #define store64_le(b, i) (store64(b, htole64(i))) 216 #define load64_be(b) (be64toh(load64(b))) 217 #define store64_be(b, i) (store64(b, htobe64(i))) 218 219 /* Co-existence of LowStar.Endianness and FStar.Endianness generates name 220 * conflicts, because of course both insist on having no prefixes. Until a 221 * prefix is added, or until we truly retire FStar.Endianness, solve this issue 222 * in an elegant way. */ 223 #define load16_le0 load16_le 224 #define store16_le0 store16_le 225 #define load16_be0 load16_be 226 #define store16_be0 store16_be 227 228 #define load32_le0 load32_le 229 #define store32_le0 store32_le 230 #define load32_be0 load32_be 231 #define store32_be0 store32_be 232 233 #define load64_le0 load64_le 234 #define store64_le0 store64_le 235 #define load64_be0 load64_be 236 #define store64_be0 store64_be 237 238 #define load128_le0 load128_le 239 #define store128_le0 store128_le 240 #define load128_be0 load128_be 241 #define store128_be0 store128_be 242 243 #endif /* KRML_HEADER_LOWSTAR_ENDIANNESS_H */