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