1 /* @(#)byte_order.h 1.3 15/11/22 2015 J. Schilling */ 2 /* byte_order.h */ 3 /* 4 * SHA3 hash code taken from 5 * https://github.com/rhash/RHash/tree/master/librhash 6 * 7 * Portions Copyright (c) 2015 J. Schilling 8 */ 9 #ifndef BYTE_ORDER_H 10 #define BYTE_ORDER_H 11 #include <schily/stdlib.h> 12 #include <schily/types.h> 13 #include <schily/stdint.h> 14 15 #ifdef IN_RHASH 16 #include "config.h" 17 #endif 18 19 #ifdef __GLIBC__ 20 # include <endian.h> 21 #endif 22 23 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 #ifdef HAVE_C_BIGENDIAN 28 29 /* 30 * Use the Schily autoconf results. 31 */ 32 #ifdef WORDS_BIGENDIAN 33 #define CPU_BIG_ENDIAN 34 #else 35 #define CPU_LITTLE_ENDIAN 36 #endif 37 38 #else /* HAVE_C_BIGENDIAN */ 39 40 /* if x86 compatible cpu */ 41 #if defined(i386) || defined(__i386__) || defined(__i486__) || \ 42 defined(__i586__) || defined(__i686__) || defined(__pentium__) || \ 43 defined(__pentiumpro__) || defined(__pentium4__) || \ 44 defined(__nocona__) || defined(prescott) || defined(__core2__) || \ 45 defined(__k6__) || defined(__k8__) || defined(__athlon__) || \ 46 defined(__amd64) || defined(__amd64__) || \ 47 defined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \ 48 defined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64) 49 /* detect if x86-64 instruction set is supported */ 50 # if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \ 51 defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) 52 #define CPU_X64 53 #else 54 #define CPU_IA32 55 #endif 56 #endif 57 58 59 /* detect CPU endianness */ 60 #if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ 61 __BYTE_ORDER == __LITTLE_ENDIAN) || \ 62 defined(CPU_IA32) || defined(CPU_X64) || \ 63 defined(__ia64) || defined(__ia64__) || defined(__alpha__) || defined(_M_ALPHA) || \ 64 defined(vax) || defined(MIPSEL) || \ 65 defined(_ARM_) || defined(__arm64__) || defined(_M_ARM) || defined(_M_ARM64) 66 #define CPU_LITTLE_ENDIAN 67 #define IS_BIG_ENDIAN 0 68 #define IS_LITTLE_ENDIAN 1 69 #elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ 70 __BYTE_ORDER == __BIG_ENDIAN) || \ 71 defined(__sparc) || defined(__sparc__) || defined(sparc) || \ 72 defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \ 73 defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \ 74 defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \ 75 defined(__hpux) || defined(_MIPSEB) || defined(mc68000) || \ 76 defined(__s390__) || defined(__s390x__) || defined(sel) 77 #define CPU_BIG_ENDIAN 78 #define IS_BIG_ENDIAN 1 79 #define IS_LITTLE_ENDIAN 0 80 #else 81 #error "Can't detect CPU architechture" 82 #endif 83 84 #endif /* HAVE_C_BIGENDIAN */ 85 86 #define IS_ALIGNED_32(p) (0 == (3 & ((const char *)(p) - (const char *)0))) 87 #define IS_ALIGNED_64(p) (0 == (7 & ((const char *)(p) - (const char *)0))) 88 89 #if defined(_MSC_VER) 90 #define ALIGN_ATTR(n) __declspec(align(n)) 91 #elif defined(__GNUC__) 92 #define ALIGN_ATTR(n) __attribute__((aligned(n))) 93 #else 94 #define ALIGN_ATTR(n) /* nothing */ 95 #endif 96 97 98 #ifdef PROTOTYPES 99 #if defined(_MSC_VER) || defined(__BORLANDC__) 100 #define I64(x) x##ui64 101 #define UI64(x) x##ui64 102 #else 103 #define I64(x) x##LL 104 #define UI64(x) x##ULL 105 #endif 106 #else /* !PROTOTYPES */ 107 #ifdef __hpux 108 #define I64(x) x/**/LL 109 #define UI64(x) x/**/ULL 110 #else 111 #define I64(x) ((long long)(x)) 112 #define UI64(x) ((unsigned long long)(x)) 113 #endif 114 #endif /* !PROTOTYPES */ 115 116 /* convert a hash flag to index */ 117 #if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) /* GCC < 3.4 */ 118 #define rhash_ctz(x) __builtin_ctz(x) 119 #else 120 unsigned rhash_ctz __PR((unsigned)); /* define as function */ 121 #endif 122 123 void rhash_swap_copy_str_to_u32 __PR((void* to, int idx, const void* from, size_t length)); 124 void rhash_swap_copy_str_to_u64 __PR((void* to, int idx, const void* from, size_t length)); 125 void rhash_swap_copy_u64_to_str __PR((void* to, const void* from, size_t length)); 126 void rhash_u32_mem_swap __PR((unsigned *p, int length_in_u32)); 127 128 /* define bswap_32 */ 129 #if defined(__GNUC__) && defined(CPU_IA32) && !defined(__i386__) 130 /* for intel x86 CPU */ 131 static inline UInt32_t bswap_32(UInt32_t x) { 132 __asm("bswap\t%0" : "=r" (x) : "0" (x)); 133 return (x); 134 } 135 #elif defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) 136 /* for GCC >= 4.3 */ 137 # define bswap_32(x) __builtin_bswap32(x) 138 #elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */ 139 # define bswap_32(x) _byteswap_ulong((unsigned long)x) 140 #elif !defined(__STRICT_ANSI__) 141 /* general bswap_32 definition */ 142 static inline UInt32_t bswap_32 __PR((UInt32_t x)); 143 static inline UInt32_t bswap_32(x) 144 UInt32_t x; 145 { 146 x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF); 147 return ((x >> 16) | (x << 16)); 148 } 149 #else 150 #define bswap_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ 151 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) 152 #endif /* bswap_32 */ 153 154 #if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) 155 # define bswap_64(x) __builtin_bswap64(x) 156 #elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */ 157 # define bswap_64(x) _byteswap_uint64((__int64)x) 158 #elif !defined(__STRICT_ANSI__) 159 static inline UInt64_t bswap_64 __PR((UInt64_t x)); 160 static inline UInt64_t bswap_64(x) 161 UInt64_t x; 162 { 163 union { 164 UInt64_t ll; 165 UInt32_t l[2]; 166 } w, r; 167 w.ll = x; 168 r.l[0] = bswap_32(w.l[1]); 169 r.l[1] = bswap_32(w.l[0]); 170 return (r.ll); 171 } 172 #else 173 #error "bswap_64 unsupported" 174 #endif 175 176 #ifdef CPU_BIG_ENDIAN 177 # define be2me_32(x) (x) 178 # define be2me_64(x) (x) 179 # define le2me_32(x) bswap_32(x) 180 # define le2me_64(x) bswap_64(x) 181 182 # define be32_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) 183 # define le32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length)) 184 # define be64_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) 185 # define le64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length)) 186 # define me64_to_be_str(to, from, length) memcpy((to), (from), (length)) 187 # define me64_to_le_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length)) 188 189 #else /* CPU_BIG_ENDIAN */ 190 # define be2me_32(x) bswap_32(x) 191 # define be2me_64(x) bswap_64(x) 192 # define le2me_32(x) (x) 193 # define le2me_64(x) (x) 194 195 # define be32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length)) 196 # define le32_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) 197 # define be64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length)) 198 # define le64_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) 199 # define me64_to_be_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length)) 200 # define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) 201 #endif /* CPU_BIG_ENDIAN */ 202 203 /* ROTL/ROTR macros rotate a 32/64-bit word left/right by n bits */ 204 #define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n)))) 205 #define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n)))) 206 #define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) 207 #define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n)))) 208 209 #ifdef __cplusplus 210 } /* extern "C" */ 211 #endif /* __cplusplus */ 212 213 #endif /* BYTE_ORDER_H */ 214