diff --git a/plat_local.h b/plat_local.h index f1bf1e3..a98ef3d 100644 --- a/plat_local.h +++ b/plat_local.h @@ -107,31 +107,47 @@ extern "C" /* revert if not big endian */ -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -/* nop */ -#define rev8_be32(x) (x) -#else -/* RISC-V: grev(x, 0x18) or rev8 */ +#if defined(SLH_SYS_LITTLE_ENDIAN) -static SLH_INLINE uint32_t rev8_be32(uint32_t x) -{ - return ((x & 0xFF000000) >> 24) | ((x & 0x00FF0000) >> 8) | - ((x & 0x0000FF00) << 8) | ((x & 0x000000FF) << 24); -} -#endif + /* RISC-V: grev(x, 0x18) or rev8 */ + static SLH_INLINE uint32_t rev8_be32(uint32_t x) + { + return ((x & 0xFF000000) >> 24) | ((x & 0x00FF0000) >> 8) | + ((x & 0x0000FF00) << 8) | ((x & 0x000000FF) << 24); + } + + /* RISC-V: grev(x, 0x38) or rev8(x) */ + static SLH_INLINE uint64_t rev8_be64(uint64_t x) + { + return (x << 56) | ((x & 0x000000000000FF00LL) << 40) | + ((x & 0x0000000000FF0000LL) << 24) | + ((x & 0x00000000FF000000LL) << 8) | + ((x & 0x000000FF00000000LL) >> 8) | + ((x & 0x0000FF0000000000LL) >> 24) | + ((x & 0x00FF000000000000LL) >> 40) | (x >> 56); + } -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define rev8_be64(x) (x) #else -/* RISC-V: grev(x, 0x38) or rev8(x) */ -static SLH_INLINE uint64_t rev8_be64(uint64_t x) -{ - return (x << 56) | ((x & 0x000000000000FF00LL) << 40) | - ((x & 0x0000000000FF0000LL) << 24) | - ((x & 0x00000000FF000000LL) << 8) | ((x & 0x000000FF00000000LL) >> 8) | - ((x & 0x0000FF0000000000LL) >> 24) | - ((x & 0x00FF000000000000LL) >> 40) | (x >> 56); -} + + /* Portable versions that do not depend on the endianness of the host: + * read the bytes of the argument in memory order and assemble the + * result in big-endian order. */ + static SLH_INLINE uint32_t rev8_be32(uint32_t x) + { + const uint8_t *p = (const uint8_t *)&x; + return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | + ((uint32_t)p[2] << 8) | (uint32_t)p[3]; + } + + static SLH_INLINE uint64_t rev8_be64(uint64_t x) + { + const uint8_t *p = (const uint8_t *)&x; + return ((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) | + ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32) | + ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) | + ((uint64_t)p[6] << 8) | (uint64_t)p[7]; + } + #endif /* rotate left */ diff --git a/slh_sys.h b/slh_sys.h index 48eabf2..6169061 100644 --- a/slh_sys.h +++ b/slh_sys.h @@ -7,6 +7,28 @@ #ifndef SLH_SYS_H #define SLH_SYS_H +/* Try to find endianness, if not forced through CFLAGS already */ +#if !defined(SLH_SYS_LITTLE_ENDIAN) && !defined(SLH_SYS_BIG_ENDIAN) +#if defined(__BYTE_ORDER__) +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define SLH_SYS_LITTLE_ENDIAN +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define SLH_SYS_BIG_ENDIAN +#else +#error "__BYTE_ORDER__ defined, but don't recognize value." +#endif +#endif /* __BYTE_ORDER__ */ + +/* MSVC does not define __BYTE_ORDER__. However, MSVC only supports + * little endian x86, x86_64, and AArch64. It is, hence, safe to assume + * little endian. */ +#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || \ + defined(_M_IX86) || defined(_M_ARM64)) +#define SLH_SYS_LITTLE_ENDIAN +#endif + +#endif /* !SLH_SYS_LITTLE_ENDIAN && !SLH_SYS_BIG_ENDIAN */ + /* * C90 does not have the inline compiler directive yet. * We don't use it in C90 builds.