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 */
bswap_32(UInt32_t x)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));
bswap_32(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));
bswap_64(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