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) || defined(_ARM_) 65 #define CPU_LITTLE_ENDIAN 66 #define IS_BIG_ENDIAN 0 67 #define IS_LITTLE_ENDIAN 1 68 #elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ 69 __BYTE_ORDER == __BIG_ENDIAN) || \ 70 defined(__sparc) || defined(__sparc__) || defined(sparc) || \ 71 defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \ 72 defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \ 73 defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \ 74 defined(__hpux) || defined(_MIPSEB) || defined(mc68000) || \ 75 defined(__s390__) || defined(__s390x__) || defined(sel) 76 #define CPU_BIG_ENDIAN 77 #define IS_BIG_ENDIAN 1 78 #define IS_LITTLE_ENDIAN 0 79 #else 80 error "Can't detect CPU architechture" 81 #endif 82 83 #endif /* HAVE_C_BIGENDIAN */ 84 85 #define IS_ALIGNED_32(p) (0 == (3 & ((const char *)(p) - (const char *)0))) 86 #define IS_ALIGNED_64(p) (0 == (7 & ((const char *)(p) - (const char *)0))) 87 88 #if defined(_MSC_VER) 89 #define ALIGN_ATTR(n) __declspec(align(n)) 90 #elif defined(__GNUC__) 91 #define ALIGN_ATTR(n) __attribute__((aligned(n))) 92 #else 93 #define ALIGN_ATTR(n) /* nothing */ 94 #endif 95 96 97 #ifdef PROTOTYPES 98 #if defined(_MSC_VER) || defined(__BORLANDC__) 99 #define I64(x) x##ui64 100 #define UI64(x) x##ui64 101 #else 102 #define I64(x) x##LL 103 #define UI64(x) x##ULL 104 #endif 105 #else /* !PROTOTYPES */ 106 #ifdef __hpux 107 #define I64(x) x/**/LL 108 #define UI64(x) x/**/ULL 109 #else 110 #define I64(x) ((long long)(x)) 111 #define UI64(x) ((unsigned long long)(x)) 112 #endif 113 #endif /* !PROTOTYPES */ 114 115 /* convert a hash flag to index */ 116 #if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) /* GCC < 3.4 */ 117 #define rhash_ctz(x) __builtin_ctz(x) 118 #else 119 unsigned rhash_ctz __PR((unsigned)); /* define as function */ 120 #endif 121 122 void rhash_swap_copy_str_to_u32 __PR((void* to, int idx, const void* from, size_t length)); 123 void rhash_swap_copy_str_to_u64 __PR((void* to, int idx, const void* from, size_t length)); 124 void rhash_swap_copy_u64_to_str __PR((void* to, const void* from, size_t length)); 125 void rhash_u32_mem_swap __PR((unsigned *p, int length_in_u32)); 126 127 /* define bswap_32 */ 128 #if defined(__GNUC__) && defined(CPU_IA32) && !defined(__i386__) 129 /* for intel x86 CPU */ 130 static inline UInt32_t bswap_32(UInt32_t x) { 131 __asm("bswap\t%0" : "=r" (x) : "0" (x)); 132 return (x); 133 } 134 #elif defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) 135 /* for GCC >= 4.3 */ 136 # define bswap_32(x) __builtin_bswap32(x) 137 #elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */ 138 # define bswap_32(x) _byteswap_ulong((unsigned long)x) 139 #elif !defined(__STRICT_ANSI__) 140 /* general bswap_32 definition */ 141 static inline UInt32_t bswap_32 __PR((UInt32_t x)); 142 static inline UInt32_t bswap_32(x) 143 UInt32_t x; 144 { 145 x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF); 146 return ((x >> 16) | (x << 16)); 147 } 148 #else 149 #define bswap_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ 150 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) 151 #endif /* bswap_32 */ 152 153 #if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) 154 # define bswap_64(x) __builtin_bswap64(x) 155 #elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */ 156 # define bswap_64(x) _byteswap_uint64((__int64)x) 157 #elif !defined(__STRICT_ANSI__) 158 static inline UInt64_t bswap_64 __PR((UInt64_t x)); 159 static inline UInt64_t bswap_64(x) 160 UInt64_t x; 161 { 162 union { 163 UInt64_t ll; 164 UInt32_t l[2]; 165 } w, r; 166 w.ll = x; 167 r.l[0] = bswap_32(w.l[1]); 168 r.l[1] = bswap_32(w.l[0]); 169 return (r.ll); 170 } 171 #else 172 error "bswap_64 unsupported" 173 #endif 174 175 #ifdef CPU_BIG_ENDIAN 176 # define be2me_32(x) (x) 177 # define be2me_64(x) (x) 178 # define le2me_32(x) bswap_32(x) 179 # define le2me_64(x) bswap_64(x) 180 181 # define be32_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) 182 # define le32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length)) 183 # define be64_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) 184 # define le64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length)) 185 # define me64_to_be_str(to, from, length) memcpy((to), (from), (length)) 186 # define me64_to_le_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length)) 187 188 #else /* CPU_BIG_ENDIAN */ 189 # define be2me_32(x) bswap_32(x) 190 # define be2me_64(x) bswap_64(x) 191 # define le2me_32(x) (x) 192 # define le2me_64(x) (x) 193 194 # define be32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length)) 195 # define le32_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) 196 # define be64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length)) 197 # define le64_copy(to, index, from, length) memcpy((to) + (index), (from), (length)) 198 # define me64_to_be_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length)) 199 # define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) 200 #endif /* CPU_BIG_ENDIAN */ 201 202 /* ROTL/ROTR macros rotate a 32/64-bit word left/right by n bits */ 203 #define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n)))) 204 #define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n)))) 205 #define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) 206 #define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n)))) 207 208 #ifdef __cplusplus 209 } /* extern "C" */ 210 #endif /* __cplusplus */ 211 212 #endif /* BYTE_ORDER_H */ 213