123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- /* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
- // Written in 2014 by Nils Maier
- #ifndef CRYPTO_ENDIAN_H
- #define CRYPTO_ENDIAN_H
- #include <cstdint>
- #include "config.h"
- namespace crypto {
- #if defined(__GNUG__)
- #define forceinline __attribute__((always_inline)) inline
- #elif defined(_MSC_VER)
- #define forceinline __forceinline
- #else // ! _MSC_VER
- #define forceinline inline
- #endif // ! _MSC_VER
- /* In order for this implementation to work your system (or you yourself) must
- * define after including <sys/param.h>
- * - LITTLE_ENDIAN
- * - BIG_ENDIAN
- * - BYTE_ORDER
- * - where BYTE_ORDER == LITTLE_ENDIAN or BYTE_ORDER == BIG_ENDIAN
- * Failing to conform will render this implementation utterly incorrect.
- */
- #if defined(_WIN32) || defined(__INTEL_COMPILER) || defined (_MSC_VER)
- // Itanium is dead!
- #define LITTLE_ENDIAN 1234
- #define BIG_ENDIAN 4321
- #define BYTE_ORDER LITTLE_ENDIAN
- #else // ! defined(_WIN32) || defined(__INTEL_COMPILER) || defined (_MSC_VER)
- #ifdef HAVE_SYS_PARAM_H
- #include <sys/param.h>
- #endif // HAVE_SYS_PARAM_H
- #endif // ! defined(_WIN32) || defined(__INTEL_COMPILER) || defined (_MSC_VER)
- #if !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN) || !defined(BYTE_ORDER) || (LITTLE_ENDIAN != BYTE_ORDER && BIG_ENDIAN != BYTE_ORDER)
- #error Unsupported byte order/endianess
- #endif
- // Lets spend some quality time mucking around with byte swap and endian-ness.
- // First bswap32:
- #if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUG__)
- forceinline uint32_t __crypto_bswap32(uint32_t p)
- {
- __asm__ __volatile__("bswap %0" : "=r"(p) : "0"(p));
- return p;
- }
- #elif defined(__GNUG__)
- #define __crypto_bswap32 __builtin_bswap32
- #else // defined(__GNUG__)
- forceinline uint32_t __crypto_bswap32(uint32_t n)
- {
- n = ((n << 8) & 0xff00ff00) | ((n >> 8) & 0xff00ff);
- return (n << 16) | (n >> 16);
- }
- #endif // defined(__GNUG__)
- // Next up: bswap64
- #if defined(__x86_64__) && defined(__GNUG__)
- forceinline uint64_t __crypto_bswap64(uint64_t p)
- {
- __asm__ __volatile__("bswapq %q0" : "=r"(p) : "0"(p));
- return p;
- }
- #elif defined(__GNUG__)
- #define __crypto_bswap64 __builtin_bswap64
- #else // defined(__GNUG__)
- forceinline uint64_t __crypto_bswap64(uint64_t n)
- {
- n = ((n << 8) & 0xff00ff00ff00ff00) | ((n >> 8) & 0x00ff00ff00ff00ff);
- n = ((n << 16) & 0xffff0000ffff0000) | ((n >> 16) & 0x0000ffff0000ffff);
- return (n << 32) | (n >> 32);
- }
- #endif // defined(__GNUG__)
- // Time for an implementation that makes reuse easier.
- namespace {
- template<typename T>
- inline T __crypto_bswap(T n)
- {
- static_assert(sizeof(T) != sizeof(T), "Not implemented");
- }
- template<>
- inline uint32_t __crypto_bswap(uint32_t n)
- {
- return __crypto_bswap32(n);
- }
- template<>
- inline uint64_t __crypto_bswap(uint64_t n)
- {
- return __crypto_bswap64(n);
- }
- } // namespace
- // __crypto_le and __crypto_be depending on byte order
- #if LITTLE_ENDIAN == BYTE_ORDER
- #define __crypto_be(n) __crypto_bswap(n)
- #define __crypto_le(n) (n)
- #else // LITTLE_ENDIAN != WORD_ORDER
- #define __crypto_be(n) (n)
- #define __crypto_le(n) __crypto_bswap(n)
- #endif // LITTLE_ENDIAN != WORD_ORDER
- } // namespace crypto
- #endif // CRYPTO_ENDIAN_H
|