1 /* @(#)byte_order.h	1.4 20/05/11 2015-2020 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-2020 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_) || defined(_M_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 */
bswap_32(UInt32_t x)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));
bswap_32(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));
bswap_64(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