Line data Source code
1 : /* $Id: sph_types.h 260 2011-07-21 01:02:38Z tp $ */
2 : /**
3 : * Basic type definitions.
4 : *
5 : * This header file defines the generic integer types that will be used
6 : * for the implementation of hash functions; it also contains helper
7 : * functions which encode and decode multi-byte integer values, using
8 : * either little-endian or big-endian conventions.
9 : *
10 : * This file contains a compile-time test on the size of a byte
11 : * (the <code>unsigned char</code> C type). If bytes are not octets,
12 : * i.e. if they do not have a size of exactly 8 bits, then compilation
13 : * is aborted. Architectures where bytes are not octets are relatively
14 : * rare, even in the embedded devices market. We forbid non-octet bytes
15 : * because there is no clear convention on how octet streams are encoded
16 : * on such systems.
17 : *
18 : * ==========================(LICENSE BEGIN)============================
19 : *
20 : * Copyright (c) 2007-2010 Projet RNRT SAPHIR
21 : *
22 : * Permission is hereby granted, free of charge, to any person obtaining
23 : * a copy of this software and associated documentation files (the
24 : * "Software"), to deal in the Software without restriction, including
25 : * without limitation the rights to use, copy, modify, merge, publish,
26 : * distribute, sublicense, and/or sell copies of the Software, and to
27 : * permit persons to whom the Software is furnished to do so, subject to
28 : * the following conditions:
29 : *
30 : * The above copyright notice and this permission notice shall be
31 : * included in all copies or substantial portions of the Software.
32 : *
33 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
34 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
35 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
36 : * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
37 : * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
38 : * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
39 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 : *
41 : * ===========================(LICENSE END)=============================
42 : *
43 : * @file sph_types.h
44 : * @author Thomas Pornin <thomas.pornin@cryptolog.com>
45 : */
46 :
47 : #ifndef SPH_TYPES_H__
48 : #define SPH_TYPES_H__
49 :
50 : #include <limits.h>
51 :
52 : /*
53 : * All our I/O functions are defined over octet streams. We do not know
54 : * how to handle input data if bytes are not octets.
55 : */
56 : #if CHAR_BIT != 8
57 : #error This code requires 8-bit bytes
58 : #endif
59 :
60 : /*
61 : * On C99 implementations, we can use <stdint.h> to get an exact 64-bit
62 : * type, if any, or otherwise use a wider type (which must exist, for
63 : * C99 conformance).
64 : */
65 :
66 : #include <stdint.h>
67 :
68 : #ifdef UINT32_MAX
69 : typedef uint32_t sph_u32;
70 : typedef int32_t sph_s32;
71 : #else
72 : typedef uint_fast32_t sph_u32;
73 : typedef int_fast32_t sph_s32;
74 : #endif
75 : #ifdef UINT64_MAX
76 : typedef uint64_t sph_u64;
77 : typedef int64_t sph_s64;
78 : #else
79 : typedef uint_fast64_t sph_u64;
80 : typedef int_fast64_t sph_s64;
81 : #endif
82 :
83 : #define SPH_C32(x) ((sph_u32)(x))
84 : #define SPH_C64(x) ((sph_u64)(x))
85 :
86 : /*
87 : * Implementation note: some processors have specific opcodes to perform
88 : * a rotation. Recent versions of gcc recognize the expression above and
89 : * use the relevant opcodes, when appropriate.
90 : */
91 :
92 : #define SPH_T32(x) ((x) & SPH_C32(0xFFFFFFFF))
93 : #define SPH_ROTL32(x, n) SPH_T32(((x) << (n)) | ((x) >> (32 - (n))))
94 : #define SPH_ROTR32(x, n) SPH_ROTL32(x, (32 - (n)))
95 :
96 : #define SPH_T64(x) ((x) & SPH_C64(0xFFFFFFFFFFFFFFFF))
97 : #define SPH_ROTL64(x, n) SPH_T64(((x) << (n)) | ((x) >> (64 - (n))))
98 : #define SPH_ROTR64(x, n) SPH_ROTL64(x, (64 - (n)))
99 :
100 : /*
101 : * Define SPH_INLINE to be an "inline" qualifier, if available. We define
102 : * some small macro-like functions which benefit greatly from being inlined.
103 : */
104 : #if (defined __STDC__ && __STDC_VERSION__ >= 199901L) || defined __GNUC__
105 : #define SPH_INLINE inline
106 : #elif defined _MSC_VER
107 : #define SPH_INLINE __inline
108 : #else
109 : #define SPH_INLINE
110 : #endif
111 :
112 : /*
113 : * We define some macros which qualify the architecture. These macros
114 : * may be explicit set externally (e.g. as compiler parameters). The
115 : * code below sets those macros if they are not already defined.
116 : *
117 : * Most macros are boolean, thus evaluate to either zero or non-zero.
118 : * The SPH_UPTR macro is special, in that it evaluates to a C type,
119 : * or is not defined.
120 : *
121 : * SPH_UPTR if defined: unsigned type to cast pointers into
122 : *
123 : * SPH_UNALIGNED non-zero if unaligned accesses are efficient
124 : * SPH_LITTLE_ENDIAN non-zero if architecture is known to be little-endian
125 : * SPH_BIG_ENDIAN non-zero if architecture is known to be big-endian
126 : * SPH_LITTLE_FAST non-zero if little-endian decoding is fast
127 : * SPH_BIG_FAST non-zero if big-endian decoding is fast
128 : *
129 : * If SPH_UPTR is defined, then encoding and decoding of 32-bit and 64-bit
130 : * values will try to be "smart". Either SPH_LITTLE_ENDIAN or SPH_BIG_ENDIAN
131 : * _must_ be non-zero in those situations. The 32-bit and 64-bit types
132 : * _must_ also have an exact width.
133 : *
134 : * SPH_SPARCV9_GCC_32 UltraSPARC-compatible with gcc, 32-bit mode
135 : * SPH_SPARCV9_GCC_64 UltraSPARC-compatible with gcc, 64-bit mode
136 : * SPH_SPARCV9_GCC UltraSPARC-compatible with gcc
137 : * SPH_I386_GCC x86-compatible (32-bit) with gcc
138 : * SPH_I386_MSVC x86-compatible (32-bit) with Microsoft Visual C
139 : * SPH_AMD64_GCC x86-compatible (64-bit) with gcc
140 : * SPH_AMD64_MSVC x86-compatible (64-bit) with Microsoft Visual C
141 : * SPH_PPC32_GCC PowerPC, 32-bit, with gcc
142 : * SPH_PPC64_GCC PowerPC, 64-bit, with gcc
143 : *
144 : * TODO: enhance automatic detection, for more architectures and compilers.
145 : * Endianness is the most important. SPH_UNALIGNED and SPH_UPTR help with
146 : * some very fast functions (e.g. MD4) when using unaligned input data.
147 : * The CPU-specific-with-GCC macros are useful only for inline assembly,
148 : * normally restrained to this header file.
149 : */
150 :
151 : /*
152 : * 32-bit x86, aka "i386 compatible".
153 : */
154 : #if defined __i386__ || defined _M_IX86
155 :
156 : #define SPH_DETECT_UNALIGNED 1
157 : #define SPH_DETECT_LITTLE_ENDIAN 1
158 : #define SPH_DETECT_UPTR sph_u32
159 : #ifdef __GNUC__
160 : #define SPH_DETECT_I386_GCC 1
161 : #endif
162 : #ifdef _MSC_VER
163 : #define SPH_DETECT_I386_MSVC 1
164 : #endif
165 :
166 : /*
167 : * 64-bit x86, hereafter known as "amd64".
168 : */
169 : #elif defined __x86_64 || defined _M_X64
170 :
171 : #define SPH_DETECT_UNALIGNED 1
172 : #define SPH_DETECT_LITTLE_ENDIAN 1
173 : #define SPH_DETECT_UPTR sph_u64
174 : #ifdef __GNUC__
175 : #define SPH_DETECT_AMD64_GCC 1
176 : #endif
177 : #ifdef _MSC_VER
178 : #define SPH_DETECT_AMD64_MSVC 1
179 : #endif
180 :
181 : /*
182 : * 64-bit Sparc architecture (implies v9).
183 : */
184 : #elif ((defined __sparc__ || defined __sparc) && defined __arch64__) \
185 : || defined __sparcv9
186 :
187 : #define SPH_DETECT_BIG_ENDIAN 1
188 : #define SPH_DETECT_UPTR sph_u64
189 : #ifdef __GNUC__
190 : #define SPH_DETECT_SPARCV9_GCC_64 1
191 : #define SPH_DETECT_LITTLE_FAST 1
192 : #endif
193 :
194 : /*
195 : * 32-bit Sparc.
196 : */
197 : #elif (defined __sparc__ || defined __sparc) \
198 : && !(defined __sparcv9 || defined __arch64__)
199 :
200 : #define SPH_DETECT_BIG_ENDIAN 1
201 : #define SPH_DETECT_UPTR sph_u32
202 : #if defined __GNUC__ && defined __sparc_v9__
203 : #define SPH_DETECT_SPARCV9_GCC_32 1
204 : #define SPH_DETECT_LITTLE_FAST 1
205 : #endif
206 :
207 : /*
208 : * ARM, little-endian.
209 : */
210 : #elif defined __arm__ && __ARMEL__
211 :
212 : #define SPH_DETECT_LITTLE_ENDIAN 1
213 :
214 : /*
215 : * MIPS, little-endian.
216 : */
217 : #elif MIPSEL || _MIPSEL || __MIPSEL || __MIPSEL__
218 :
219 : #define SPH_DETECT_LITTLE_ENDIAN 1
220 :
221 : /*
222 : * MIPS, big-endian.
223 : */
224 : #elif MIPSEB || _MIPSEB || __MIPSEB || __MIPSEB__
225 :
226 : #define SPH_DETECT_BIG_ENDIAN 1
227 :
228 : /*
229 : * PowerPC.
230 : */
231 : #elif defined __powerpc__ || defined __POWERPC__ || defined __ppc__ \
232 : || defined _ARCH_PPC
233 :
234 : /*
235 : * Note: we do not declare cross-endian access to be "fast": even if
236 : * using inline assembly, implementation should still assume that
237 : * keeping the decoded word in a temporary is faster than decoding
238 : * it again.
239 : */
240 : #if defined __GNUC__
241 : #define SPH_DETECT_PPC64_GCC 1
242 : #endif
243 :
244 : #if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN
245 : #define SPH_DETECT_BIG_ENDIAN 1
246 : #elif defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN
247 : #define SPH_DETECT_LITTLE_ENDIAN 1
248 : #endif
249 :
250 : /*
251 : * Itanium, 64-bit.
252 : */
253 : #elif defined __ia64 || defined __ia64__ \
254 : || defined __itanium__ || defined _M_IA64
255 :
256 : #if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN
257 : #define SPH_DETECT_BIG_ENDIAN 1
258 : #else
259 : #define SPH_DETECT_LITTLE_ENDIAN 1
260 : #endif
261 : #if defined __LP64__ || defined _LP64
262 : #define SPH_DETECT_UPTR sph_u64
263 : #else
264 : #define SPH_DETECT_UPTR sph_u32
265 : #endif
266 :
267 : #endif
268 :
269 : #if defined SPH_DETECT_SPARCV9_GCC_32 || defined SPH_DETECT_SPARCV9_GCC_64
270 : #define SPH_DETECT_SPARCV9_GCC 1
271 : #endif
272 :
273 : #if defined SPH_DETECT_UNALIGNED && !defined SPH_UNALIGNED
274 : #define SPH_UNALIGNED SPH_DETECT_UNALIGNED
275 : #endif
276 : #if defined SPH_DETECT_UPTR && !defined SPH_UPTR
277 : #define SPH_UPTR SPH_DETECT_UPTR
278 : #endif
279 : #if defined SPH_DETECT_LITTLE_ENDIAN && !defined SPH_LITTLE_ENDIAN
280 : #define SPH_LITTLE_ENDIAN SPH_DETECT_LITTLE_ENDIAN
281 : #endif
282 : #if defined SPH_DETECT_BIG_ENDIAN && !defined SPH_BIG_ENDIAN
283 : #define SPH_BIG_ENDIAN SPH_DETECT_BIG_ENDIAN
284 : #endif
285 : #if defined SPH_DETECT_LITTLE_FAST && !defined SPH_LITTLE_FAST
286 : #define SPH_LITTLE_FAST SPH_DETECT_LITTLE_FAST
287 : #endif
288 : #if defined SPH_DETECT_BIG_FAST && !defined SPH_BIG_FAST
289 : #define SPH_BIG_FAST SPH_DETECT_BIG_FAST
290 : #endif
291 : #if defined SPH_DETECT_SPARCV9_GCC_32 && !defined SPH_SPARCV9_GCC_32
292 : #define SPH_SPARCV9_GCC_32 SPH_DETECT_SPARCV9_GCC_32
293 : #endif
294 : #if defined SPH_DETECT_SPARCV9_GCC_64 && !defined SPH_SPARCV9_GCC_64
295 : #define SPH_SPARCV9_GCC_64 SPH_DETECT_SPARCV9_GCC_64
296 : #endif
297 : #if defined SPH_DETECT_SPARCV9_GCC && !defined SPH_SPARCV9_GCC
298 : #define SPH_SPARCV9_GCC SPH_DETECT_SPARCV9_GCC
299 : #endif
300 : #if defined SPH_DETECT_I386_GCC && !defined SPH_I386_GCC
301 : #define SPH_I386_GCC SPH_DETECT_I386_GCC
302 : #endif
303 : #if defined SPH_DETECT_I386_MSVC && !defined SPH_I386_MSVC
304 : #define SPH_I386_MSVC SPH_DETECT_I386_MSVC
305 : #endif
306 : #if defined SPH_DETECT_AMD64_GCC && !defined SPH_AMD64_GCC
307 : #define SPH_AMD64_GCC SPH_DETECT_AMD64_GCC
308 : #endif
309 : #if defined SPH_DETECT_AMD64_MSVC && !defined SPH_AMD64_MSVC
310 : #define SPH_AMD64_MSVC SPH_DETECT_AMD64_MSVC
311 : #endif
312 : #if defined SPH_DETECT_PPC32_GCC && !defined SPH_PPC32_GCC
313 : #define SPH_PPC32_GCC SPH_DETECT_PPC32_GCC
314 : #endif
315 : #if defined SPH_DETECT_PPC64_GCC && !defined SPH_PPC64_GCC
316 : #define SPH_PPC64_GCC SPH_DETECT_PPC64_GCC
317 : #endif
318 :
319 : #if SPH_LITTLE_ENDIAN && !defined SPH_LITTLE_FAST
320 : #define SPH_LITTLE_FAST 1
321 : #endif
322 : #if SPH_BIG_ENDIAN && !defined SPH_BIG_FAST
323 : #define SPH_BIG_FAST 1
324 : #endif
325 :
326 : #if defined SPH_UPTR && !(SPH_LITTLE_ENDIAN || SPH_BIG_ENDIAN)
327 : #error SPH_UPTR defined, but endianness is not known.
328 : #endif
329 :
330 : #if defined(__clang__)
331 : #define SPH_NO_SANITIZE(...) __attribute__((no_sanitize(__VA_ARGS__)))
332 : #else
333 : #define SPH_NO_SANITIZE(...)
334 : #endif // __clang__
335 :
336 : // Suppress unaligned memory access warnings if supported by hardware
337 : #if defined(SPH_UPTR) && SPH_UNALIGNED
338 : #define SPH_UNALIGNED_ATTRIBS SPH_NO_SANITIZE("alignment")
339 : #else
340 : #define SPH_UNALIGNED_ATTRIBS
341 : #endif // SPH_UPTR && SPH_UNALIGNED
342 :
343 : #if SPH_I386_GCC && !SPH_NO_ASM
344 :
345 : /*
346 : * On x86 32-bit, with gcc, we use the bswapl opcode to byte-swap 32-bit
347 : * values.
348 : */
349 :
350 : static SPH_INLINE sph_u32
351 : sph_bswap32(sph_u32 x)
352 : {
353 : __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x));
354 : return x;
355 : }
356 :
357 : static SPH_INLINE sph_u64
358 : sph_bswap64(sph_u64 x)
359 : {
360 : return ((sph_u64)sph_bswap32((sph_u32)x) << 32)
361 : | (sph_u64)sph_bswap32((sph_u32)(x >> 32));
362 : }
363 :
364 : #elif SPH_AMD64_GCC && !SPH_NO_ASM
365 :
366 : /*
367 : * On x86 64-bit, with gcc, we use the bswapl opcode to byte-swap 32-bit
368 : * and 64-bit values.
369 : */
370 :
371 : static SPH_INLINE sph_u32
372 : sph_bswap32(sph_u32 x)
373 : {
374 : __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x));
375 : return x;
376 : }
377 :
378 : static SPH_INLINE sph_u64
379 : sph_bswap64(sph_u64 x)
380 : {
381 : __asm__ __volatile__ ("bswapq %0" : "=r" (x) : "0" (x));
382 : return x;
383 : }
384 :
385 : #else
386 :
387 : static SPH_INLINE sph_u32
388 : sph_bswap32(sph_u32 x)
389 : {
390 : x = SPH_T32((x << 16) | (x >> 16));
391 : x = ((x & SPH_C32(0xFF00FF00)) >> 8)
392 : | ((x & SPH_C32(0x00FF00FF)) << 8);
393 : return x;
394 : }
395 :
396 : /**
397 : * Byte-swap a 64-bit value.
398 : *
399 : * @param x the input value
400 : * @return the byte-swapped value
401 : */
402 : static SPH_INLINE sph_u64
403 : sph_bswap64(sph_u64 x)
404 : {
405 : x = SPH_T64((x << 32) | (x >> 32));
406 : x = ((x & SPH_C64(0xFFFF0000FFFF0000)) >> 16)
407 : | ((x & SPH_C64(0x0000FFFF0000FFFF)) << 16);
408 : x = ((x & SPH_C64(0xFF00FF00FF00FF00)) >> 8)
409 : | ((x & SPH_C64(0x00FF00FF00FF00FF)) << 8);
410 : return x;
411 : }
412 :
413 : #endif
414 :
415 : #if SPH_SPARCV9_GCC && !SPH_NO_ASM
416 :
417 : /*
418 : * On UltraSPARC systems, native ordering is big-endian, but it is
419 : * possible to perform little-endian read accesses by specifying the
420 : * address space 0x88 (ASI_PRIMARY_LITTLE). Basically, either we use
421 : * the opcode "lda [%reg]0x88,%dst", where %reg is the register which
422 : * contains the source address and %dst is the destination register,
423 : * or we use "lda [%reg+imm]%asi,%dst", which uses the %asi register
424 : * to get the address space name. The latter format is better since it
425 : * combines an addition and the actual access in a single opcode; but
426 : * it requires the setting (and subsequent resetting) of %asi, which is
427 : * slow. Some operations (i.e. MD5 compression function) combine many
428 : * successive little-endian read accesses, which may share the same
429 : * %asi setting. The macros below contain the appropriate inline
430 : * assembly.
431 : */
432 :
433 : #define SPH_SPARCV9_SET_ASI \
434 : sph_u32 sph_sparcv9_asi; \
435 : __asm__ __volatile__ ( \
436 : "rd %%asi,%0\n\twr %%g0,0x88,%%asi" : "=r" (sph_sparcv9_asi));
437 :
438 : #define SPH_SPARCV9_RESET_ASI \
439 : __asm__ __volatile__ ("wr %%g0,%0,%%asi" : : "r" (sph_sparcv9_asi));
440 :
441 : #define SPH_SPARCV9_DEC32LE(base, idx) ({ \
442 : sph_u32 sph_sparcv9_tmp; \
443 : __asm__ __volatile__ ("lda [%1+" #idx "*4]%%asi,%0" \
444 : : "=r" (sph_sparcv9_tmp) : "r" (base)); \
445 : sph_sparcv9_tmp; \
446 : })
447 :
448 : #endif
449 :
450 : static SPH_INLINE void
451 : sph_enc16be(void *dst, unsigned val)
452 : {
453 : ((unsigned char *)dst)[0] = (val >> 8);
454 : ((unsigned char *)dst)[1] = val;
455 : }
456 :
457 : static SPH_INLINE unsigned
458 : sph_dec16be(const void *src)
459 : {
460 : return ((unsigned)(((const unsigned char *)src)[0]) << 8)
461 : | (unsigned)(((const unsigned char *)src)[1]);
462 : }
463 :
464 : static SPH_INLINE void
465 6239580 : sph_enc16le(void *dst, unsigned val)
466 : {
467 6239580 : ((unsigned char *)dst)[0] = val;
468 6239580 : ((unsigned char *)dst)[1] = val >> 8;
469 6239580 : }
470 :
471 : static SPH_INLINE unsigned
472 : sph_dec16le(const void *src)
473 : {
474 : return (unsigned)(((const unsigned char *)src)[0])
475 : | ((unsigned)(((const unsigned char *)src)[1]) << 8);
476 : }
477 :
478 : /**
479 : * Encode a 32-bit value into the provided buffer (big endian convention).
480 : *
481 : * @param dst the destination buffer
482 : * @param val the 32-bit value to encode
483 : */
484 : static SPH_INLINE void
485 : SPH_UNALIGNED_ATTRIBS
486 : sph_enc32be(void *dst, sph_u32 val)
487 : {
488 : #if defined SPH_UPTR
489 : #if SPH_UNALIGNED
490 : #if SPH_LITTLE_ENDIAN
491 : val = sph_bswap32(val);
492 : #endif
493 : *(sph_u32 *)dst = val;
494 : #else
495 : if (((SPH_UPTR)dst & 3) == 0) {
496 : #if SPH_LITTLE_ENDIAN
497 : val = sph_bswap32(val);
498 : #endif
499 : *(sph_u32 *)dst = val;
500 : } else {
501 : ((unsigned char *)dst)[0] = (val >> 24);
502 : ((unsigned char *)dst)[1] = (val >> 16);
503 : ((unsigned char *)dst)[2] = (val >> 8);
504 : ((unsigned char *)dst)[3] = val;
505 : }
506 : #endif
507 : #else
508 : ((unsigned char *)dst)[0] = (val >> 24);
509 : ((unsigned char *)dst)[1] = (val >> 16);
510 : ((unsigned char *)dst)[2] = (val >> 8);
511 : ((unsigned char *)dst)[3] = val;
512 : #endif
513 : }
514 :
515 : /**
516 : * Encode a 32-bit value into the provided buffer (big endian convention).
517 : * The destination buffer must be properly aligned.
518 : *
519 : * @param dst the destination buffer (32-bit aligned)
520 : * @param val the value to encode
521 : */
522 : static SPH_INLINE void
523 : sph_enc32be_aligned(void *dst, sph_u32 val)
524 : {
525 : #if SPH_LITTLE_ENDIAN
526 : *(sph_u32 *)dst = sph_bswap32(val);
527 : #elif SPH_BIG_ENDIAN
528 : *(sph_u32 *)dst = val;
529 : #else
530 : ((unsigned char *)dst)[0] = (val >> 24);
531 : ((unsigned char *)dst)[1] = (val >> 16);
532 : ((unsigned char *)dst)[2] = (val >> 8);
533 : ((unsigned char *)dst)[3] = val;
534 : #endif
535 : }
536 :
537 : /**
538 : * Decode a 32-bit value from the provided buffer (big endian convention).
539 : *
540 : * @param src the source buffer
541 : * @return the decoded value
542 : */
543 : static SPH_INLINE sph_u32
544 : SPH_UNALIGNED_ATTRIBS
545 : sph_dec32be(const void *src)
546 : {
547 : #if defined SPH_UPTR
548 : #if SPH_UNALIGNED
549 : #if SPH_LITTLE_ENDIAN
550 : return sph_bswap32(*(const sph_u32 *)src);
551 : #else
552 : return *(const sph_u32 *)src;
553 : #endif
554 : #else
555 : if (((SPH_UPTR)src & 3) == 0) {
556 : #if SPH_LITTLE_ENDIAN
557 : return sph_bswap32(*(const sph_u32 *)src);
558 : #else
559 : return *(const sph_u32 *)src;
560 : #endif
561 : } else {
562 : return ((sph_u32)(((const unsigned char *)src)[0]) << 24)
563 : | ((sph_u32)(((const unsigned char *)src)[1]) << 16)
564 : | ((sph_u32)(((const unsigned char *)src)[2]) << 8)
565 : | (sph_u32)(((const unsigned char *)src)[3]);
566 : }
567 : #endif
568 : #else
569 : return ((sph_u32)(((const unsigned char *)src)[0]) << 24)
570 : | ((sph_u32)(((const unsigned char *)src)[1]) << 16)
571 : | ((sph_u32)(((const unsigned char *)src)[2]) << 8)
572 : | (sph_u32)(((const unsigned char *)src)[3]);
573 : #endif
574 : }
575 :
576 : /**
577 : * Decode a 32-bit value from the provided buffer (big endian convention).
578 : * The source buffer must be properly aligned.
579 : *
580 : * @param src the source buffer (32-bit aligned)
581 : * @return the decoded value
582 : */
583 : static SPH_INLINE sph_u32
584 : sph_dec32be_aligned(const void *src)
585 : {
586 : #if SPH_LITTLE_ENDIAN
587 : return sph_bswap32(*(const sph_u32 *)src);
588 : #elif SPH_BIG_ENDIAN
589 : return *(const sph_u32 *)src;
590 : #else
591 : return ((sph_u32)(((const unsigned char *)src)[0]) << 24)
592 : | ((sph_u32)(((const unsigned char *)src)[1]) << 16)
593 : | ((sph_u32)(((const unsigned char *)src)[2]) << 8)
594 : | (sph_u32)(((const unsigned char *)src)[3]);
595 : #endif
596 : }
597 :
598 : /**
599 : * Encode a 32-bit value into the provided buffer (little endian convention).
600 : *
601 : * @param dst the destination buffer
602 : * @param val the 32-bit value to encode
603 : */
604 : static SPH_INLINE void
605 : SPH_UNALIGNED_ATTRIBS
606 124791528 : sph_enc32le(void *dst, sph_u32 val)
607 : {
608 : #if defined SPH_UPTR
609 : #if SPH_UNALIGNED
610 : #if SPH_BIG_ENDIAN
611 : val = sph_bswap32(val);
612 : #endif
613 : *(sph_u32 *)dst = val;
614 : #else
615 : if (((SPH_UPTR)dst & 3) == 0) {
616 : #if SPH_BIG_ENDIAN
617 : val = sph_bswap32(val);
618 : #endif
619 : *(sph_u32 *)dst = val;
620 : } else {
621 : ((unsigned char *)dst)[0] = val;
622 : ((unsigned char *)dst)[1] = (val >> 8);
623 : ((unsigned char *)dst)[2] = (val >> 16);
624 : ((unsigned char *)dst)[3] = (val >> 24);
625 : }
626 : #endif
627 : #else
628 124791528 : ((unsigned char *)dst)[0] = val;
629 124791528 : ((unsigned char *)dst)[1] = (val >> 8);
630 124791528 : ((unsigned char *)dst)[2] = (val >> 16);
631 124791528 : ((unsigned char *)dst)[3] = (val >> 24);
632 : #endif
633 124791528 : }
634 :
635 : /**
636 : * Encode a 32-bit value into the provided buffer (little endian convention).
637 : * The destination buffer must be properly aligned.
638 : *
639 : * @param dst the destination buffer (32-bit aligned)
640 : * @param val the value to encode
641 : */
642 : static SPH_INLINE void
643 24958480 : sph_enc32le_aligned(void *dst, sph_u32 val)
644 : {
645 : #if SPH_LITTLE_ENDIAN
646 : *(sph_u32 *)dst = val;
647 : #elif SPH_BIG_ENDIAN
648 : *(sph_u32 *)dst = sph_bswap32(val);
649 : #else
650 24958480 : ((unsigned char *)dst)[0] = val;
651 24958480 : ((unsigned char *)dst)[1] = (val >> 8);
652 24958480 : ((unsigned char *)dst)[2] = (val >> 16);
653 24958480 : ((unsigned char *)dst)[3] = (val >> 24);
654 : #endif
655 24958480 : }
656 :
657 : /**
658 : * Decode a 32-bit value from the provided buffer (little endian convention).
659 : *
660 : * @param src the source buffer
661 : * @return the decoded value
662 : */
663 : static SPH_INLINE sph_u32
664 : SPH_UNALIGNED_ATTRIBS
665 : sph_dec32le(const void *src)
666 : {
667 : #if defined SPH_UPTR
668 : #if SPH_UNALIGNED
669 : #if SPH_BIG_ENDIAN
670 : return sph_bswap32(*(const sph_u32 *)src);
671 : #else
672 : return *(const sph_u32 *)src;
673 : #endif
674 : #else
675 : if (((SPH_UPTR)src & 3) == 0) {
676 : #if SPH_BIG_ENDIAN
677 : #if SPH_SPARCV9_GCC && !SPH_NO_ASM
678 : sph_u32 tmp;
679 :
680 : /*
681 : * "__volatile__" is needed here because without it,
682 : * gcc-3.4.3 miscompiles the code and performs the
683 : * access before the test on the address, thus triggering
684 : * a bus error...
685 : */
686 : __asm__ __volatile__ (
687 : "lda [%1]0x88,%0" : "=r" (tmp) : "r" (src));
688 : return tmp;
689 : #else
690 : return sph_bswap32(*(const sph_u32 *)src);
691 : #endif
692 : #else
693 : return *(const sph_u32 *)src;
694 : #endif
695 : } else {
696 : return (sph_u32)(((const unsigned char *)src)[0])
697 : | ((sph_u32)(((const unsigned char *)src)[1]) << 8)
698 : | ((sph_u32)(((const unsigned char *)src)[2]) << 16)
699 : | ((sph_u32)(((const unsigned char *)src)[3]) << 24);
700 : }
701 : #endif
702 : #else
703 : return (sph_u32)(((const unsigned char *)src)[0])
704 : | ((sph_u32)(((const unsigned char *)src)[1]) << 8)
705 : | ((sph_u32)(((const unsigned char *)src)[2]) << 16)
706 : | ((sph_u32)(((const unsigned char *)src)[3]) << 24);
707 : #endif
708 : }
709 :
710 : /**
711 : * Decode a 32-bit value from the provided buffer (little endian convention).
712 : * The source buffer must be properly aligned.
713 : *
714 : * @param src the source buffer (32-bit aligned)
715 : * @return the decoded value
716 : */
717 : static SPH_INLINE sph_u32
718 199657573 : sph_dec32le_aligned(const void *src)
719 : {
720 : #if SPH_LITTLE_ENDIAN
721 : return *(const sph_u32 *)src;
722 : #elif SPH_BIG_ENDIAN
723 : #if SPH_SPARCV9_GCC && !SPH_NO_ASM
724 : sph_u32 tmp;
725 :
726 : __asm__ __volatile__ ("lda [%1]0x88,%0" : "=r" (tmp) : "r" (src));
727 : return tmp;
728 : #else
729 : return sph_bswap32(*(const sph_u32 *)src);
730 : #endif
731 : #else
732 399315146 : return (sph_u32)(((const unsigned char *)src)[0])
733 199657573 : | ((sph_u32)(((const unsigned char *)src)[1]) << 8)
734 199657573 : | ((sph_u32)(((const unsigned char *)src)[2]) << 16)
735 199657573 : | ((sph_u32)(((const unsigned char *)src)[3]) << 24);
736 : #endif
737 : }
738 :
739 : /**
740 : * Encode a 64-bit value into the provided buffer (big endian convention).
741 : *
742 : * @param dst the destination buffer
743 : * @param val the 64-bit value to encode
744 : */
745 : static SPH_INLINE void
746 : SPH_UNALIGNED_ATTRIBS
747 : sph_enc64be(void *dst, sph_u64 val)
748 : {
749 : #if defined SPH_UPTR
750 : #if SPH_UNALIGNED
751 : #if SPH_LITTLE_ENDIAN
752 : val = sph_bswap64(val);
753 : #endif
754 : *(sph_u64 *)dst = val;
755 : #else
756 : if (((SPH_UPTR)dst & 7) == 0) {
757 : #if SPH_LITTLE_ENDIAN
758 : val = sph_bswap64(val);
759 : #endif
760 : *(sph_u64 *)dst = val;
761 : } else {
762 : ((unsigned char *)dst)[0] = (val >> 56);
763 : ((unsigned char *)dst)[1] = (val >> 48);
764 : ((unsigned char *)dst)[2] = (val >> 40);
765 : ((unsigned char *)dst)[3] = (val >> 32);
766 : ((unsigned char *)dst)[4] = (val >> 24);
767 : ((unsigned char *)dst)[5] = (val >> 16);
768 : ((unsigned char *)dst)[6] = (val >> 8);
769 : ((unsigned char *)dst)[7] = val;
770 : }
771 : #endif
772 : #else
773 : ((unsigned char *)dst)[0] = (val >> 56);
774 : ((unsigned char *)dst)[1] = (val >> 48);
775 : ((unsigned char *)dst)[2] = (val >> 40);
776 : ((unsigned char *)dst)[3] = (val >> 32);
777 : ((unsigned char *)dst)[4] = (val >> 24);
778 : ((unsigned char *)dst)[5] = (val >> 16);
779 : ((unsigned char *)dst)[6] = (val >> 8);
780 : ((unsigned char *)dst)[7] = val;
781 : #endif
782 : }
783 :
784 : /**
785 : * Encode a 64-bit value into the provided buffer (big endian convention).
786 : * The destination buffer must be properly aligned.
787 : *
788 : * @param dst the destination buffer (64-bit aligned)
789 : * @param val the value to encode
790 : */
791 : static SPH_INLINE void
792 : sph_enc64be_aligned(void *dst, sph_u64 val)
793 : {
794 : #if SPH_LITTLE_ENDIAN
795 : *(sph_u64 *)dst = sph_bswap64(val);
796 : #elif SPH_BIG_ENDIAN
797 : *(sph_u64 *)dst = val;
798 : #else
799 : ((unsigned char *)dst)[0] = (val >> 56);
800 : ((unsigned char *)dst)[1] = (val >> 48);
801 : ((unsigned char *)dst)[2] = (val >> 40);
802 : ((unsigned char *)dst)[3] = (val >> 32);
803 : ((unsigned char *)dst)[4] = (val >> 24);
804 : ((unsigned char *)dst)[5] = (val >> 16);
805 : ((unsigned char *)dst)[6] = (val >> 8);
806 : ((unsigned char *)dst)[7] = val;
807 : #endif
808 : }
809 :
810 : /**
811 : * Decode a 64-bit value from the provided buffer (big endian convention).
812 : *
813 : * @param src the source buffer
814 : * @return the decoded value
815 : */
816 : static SPH_INLINE sph_u64
817 : SPH_UNALIGNED_ATTRIBS
818 : sph_dec64be(const void *src)
819 : {
820 : #if defined SPH_UPTR
821 : #if SPH_UNALIGNED
822 : #if SPH_LITTLE_ENDIAN
823 : return sph_bswap64(*(const sph_u64 *)src);
824 : #else
825 : return *(const sph_u64 *)src;
826 : #endif
827 : #else
828 : if (((SPH_UPTR)src & 7) == 0) {
829 : #if SPH_LITTLE_ENDIAN
830 : return sph_bswap64(*(const sph_u64 *)src);
831 : #else
832 : return *(const sph_u64 *)src;
833 : #endif
834 : } else {
835 : return ((sph_u64)(((const unsigned char *)src)[0]) << 56)
836 : | ((sph_u64)(((const unsigned char *)src)[1]) << 48)
837 : | ((sph_u64)(((const unsigned char *)src)[2]) << 40)
838 : | ((sph_u64)(((const unsigned char *)src)[3]) << 32)
839 : | ((sph_u64)(((const unsigned char *)src)[4]) << 24)
840 : | ((sph_u64)(((const unsigned char *)src)[5]) << 16)
841 : | ((sph_u64)(((const unsigned char *)src)[6]) << 8)
842 : | (sph_u64)(((const unsigned char *)src)[7]);
843 : }
844 : #endif
845 : #else
846 : return ((sph_u64)(((const unsigned char *)src)[0]) << 56)
847 : | ((sph_u64)(((const unsigned char *)src)[1]) << 48)
848 : | ((sph_u64)(((const unsigned char *)src)[2]) << 40)
849 : | ((sph_u64)(((const unsigned char *)src)[3]) << 32)
850 : | ((sph_u64)(((const unsigned char *)src)[4]) << 24)
851 : | ((sph_u64)(((const unsigned char *)src)[5]) << 16)
852 : | ((sph_u64)(((const unsigned char *)src)[6]) << 8)
853 : | (sph_u64)(((const unsigned char *)src)[7]);
854 : #endif
855 : }
856 :
857 : /**
858 : * Decode a 64-bit value from the provided buffer (big endian convention).
859 : * The source buffer must be properly aligned.
860 : *
861 : * @param src the source buffer (64-bit aligned)
862 : * @return the decoded value
863 : */
864 : static SPH_INLINE sph_u64
865 : sph_dec64be_aligned(const void *src)
866 : {
867 : #if SPH_LITTLE_ENDIAN
868 : return sph_bswap64(*(const sph_u64 *)src);
869 : #elif SPH_BIG_ENDIAN
870 : return *(const sph_u64 *)src;
871 : #else
872 : return ((sph_u64)(((const unsigned char *)src)[0]) << 56)
873 : | ((sph_u64)(((const unsigned char *)src)[1]) << 48)
874 : | ((sph_u64)(((const unsigned char *)src)[2]) << 40)
875 : | ((sph_u64)(((const unsigned char *)src)[3]) << 32)
876 : | ((sph_u64)(((const unsigned char *)src)[4]) << 24)
877 : | ((sph_u64)(((const unsigned char *)src)[5]) << 16)
878 : | ((sph_u64)(((const unsigned char *)src)[6]) << 8)
879 : | (sph_u64)(((const unsigned char *)src)[7]);
880 : #endif
881 : }
882 :
883 : /**
884 : * Encode a 64-bit value into the provided buffer (little endian convention).
885 : *
886 : * @param dst the destination buffer
887 : * @param val the 64-bit value to encode
888 : */
889 : static SPH_INLINE void
890 : SPH_UNALIGNED_ATTRIBS
891 : sph_enc64le(void *dst, sph_u64 val)
892 : {
893 : #if defined SPH_UPTR
894 : #if SPH_UNALIGNED
895 : #if SPH_BIG_ENDIAN
896 : val = sph_bswap64(val);
897 : #endif
898 : *(sph_u64 *)dst = val;
899 : #else
900 : if (((SPH_UPTR)dst & 7) == 0) {
901 : #if SPH_BIG_ENDIAN
902 : val = sph_bswap64(val);
903 : #endif
904 : *(sph_u64 *)dst = val;
905 : } else {
906 : ((unsigned char *)dst)[0] = val;
907 : ((unsigned char *)dst)[1] = (val >> 8);
908 : ((unsigned char *)dst)[2] = (val >> 16);
909 : ((unsigned char *)dst)[3] = (val >> 24);
910 : ((unsigned char *)dst)[4] = (val >> 32);
911 : ((unsigned char *)dst)[5] = (val >> 40);
912 : ((unsigned char *)dst)[6] = (val >> 48);
913 : ((unsigned char *)dst)[7] = (val >> 56);
914 : }
915 : #endif
916 : #else
917 : ((unsigned char *)dst)[0] = val;
918 : ((unsigned char *)dst)[1] = (val >> 8);
919 : ((unsigned char *)dst)[2] = (val >> 16);
920 : ((unsigned char *)dst)[3] = (val >> 24);
921 : ((unsigned char *)dst)[4] = (val >> 32);
922 : ((unsigned char *)dst)[5] = (val >> 40);
923 : ((unsigned char *)dst)[6] = (val >> 48);
924 : ((unsigned char *)dst)[7] = (val >> 56);
925 : #endif
926 : }
927 :
928 : /**
929 : * Encode a 64-bit value into the provided buffer (little endian convention).
930 : * The destination buffer must be properly aligned.
931 : *
932 : * @param dst the destination buffer (64-bit aligned)
933 : * @param val the value to encode
934 : */
935 : static SPH_INLINE void
936 49918904 : sph_enc64le_aligned(void *dst, sph_u64 val)
937 : {
938 : #if SPH_LITTLE_ENDIAN
939 : *(sph_u64 *)dst = val;
940 : #elif SPH_BIG_ENDIAN
941 : *(sph_u64 *)dst = sph_bswap64(val);
942 : #else
943 49918904 : ((unsigned char *)dst)[0] = val;
944 49918904 : ((unsigned char *)dst)[1] = (val >> 8);
945 49918904 : ((unsigned char *)dst)[2] = (val >> 16);
946 49918904 : ((unsigned char *)dst)[3] = (val >> 24);
947 49918904 : ((unsigned char *)dst)[4] = (val >> 32);
948 49918904 : ((unsigned char *)dst)[5] = (val >> 40);
949 49918904 : ((unsigned char *)dst)[6] = (val >> 48);
950 49918904 : ((unsigned char *)dst)[7] = (val >> 56);
951 : #endif
952 49918904 : }
953 :
954 : /**
955 : * Decode a 64-bit value from the provided buffer (little endian convention).
956 : *
957 : * @param src the source buffer
958 : * @return the decoded value
959 : */
960 : static SPH_INLINE sph_u64
961 : SPH_UNALIGNED_ATTRIBS
962 : sph_dec64le(const void *src)
963 : {
964 : #if defined SPH_UPTR
965 : #if SPH_UNALIGNED
966 : #if SPH_BIG_ENDIAN
967 : return sph_bswap64(*(const sph_u64 *)src);
968 : #else
969 : return *(const sph_u64 *)src;
970 : #endif
971 : #else
972 : if (((SPH_UPTR)src & 7) == 0) {
973 : #if SPH_BIG_ENDIAN
974 : #if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM
975 : sph_u64 tmp;
976 :
977 : __asm__ __volatile__ (
978 : "ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src));
979 : return tmp;
980 : #else
981 : return sph_bswap64(*(const sph_u64 *)src);
982 : #endif
983 : #else
984 : return *(const sph_u64 *)src;
985 : #endif
986 : } else {
987 : return (sph_u64)(((const unsigned char *)src)[0])
988 : | ((sph_u64)(((const unsigned char *)src)[1]) << 8)
989 : | ((sph_u64)(((const unsigned char *)src)[2]) << 16)
990 : | ((sph_u64)(((const unsigned char *)src)[3]) << 24)
991 : | ((sph_u64)(((const unsigned char *)src)[4]) << 32)
992 : | ((sph_u64)(((const unsigned char *)src)[5]) << 40)
993 : | ((sph_u64)(((const unsigned char *)src)[6]) << 48)
994 : | ((sph_u64)(((const unsigned char *)src)[7]) << 56);
995 : }
996 : #endif
997 : #else
998 : return (sph_u64)(((const unsigned char *)src)[0])
999 : | ((sph_u64)(((const unsigned char *)src)[1]) << 8)
1000 : | ((sph_u64)(((const unsigned char *)src)[2]) << 16)
1001 : | ((sph_u64)(((const unsigned char *)src)[3]) << 24)
1002 : | ((sph_u64)(((const unsigned char *)src)[4]) << 32)
1003 : | ((sph_u64)(((const unsigned char *)src)[5]) << 40)
1004 : | ((sph_u64)(((const unsigned char *)src)[6]) << 48)
1005 : | ((sph_u64)(((const unsigned char *)src)[7]) << 56);
1006 : #endif
1007 : }
1008 :
1009 : /**
1010 : * Decode a 64-bit value from the provided buffer (little endian convention).
1011 : * The source buffer must be properly aligned.
1012 : *
1013 : * @param src the source buffer (64-bit aligned)
1014 : * @return the decoded value
1015 : */
1016 : static SPH_INLINE sph_u64
1017 199665568 : sph_dec64le_aligned(const void *src)
1018 : {
1019 : #if SPH_LITTLE_ENDIAN
1020 : return *(const sph_u64 *)src;
1021 : #elif SPH_BIG_ENDIAN
1022 : #if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM
1023 : sph_u64 tmp;
1024 :
1025 : __asm__ __volatile__ ("ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src));
1026 : return tmp;
1027 : #else
1028 : return sph_bswap64(*(const sph_u64 *)src);
1029 : #endif
1030 : #else
1031 399331136 : return (sph_u64)(((const unsigned char *)src)[0])
1032 199665568 : | ((sph_u64)(((const unsigned char *)src)[1]) << 8)
1033 199665568 : | ((sph_u64)(((const unsigned char *)src)[2]) << 16)
1034 199665568 : | ((sph_u64)(((const unsigned char *)src)[3]) << 24)
1035 199665568 : | ((sph_u64)(((const unsigned char *)src)[4]) << 32)
1036 199665568 : | ((sph_u64)(((const unsigned char *)src)[5]) << 40)
1037 199665568 : | ((sph_u64)(((const unsigned char *)src)[6]) << 48)
1038 199665568 : | ((sph_u64)(((const unsigned char *)src)[7]) << 56);
1039 : #endif
1040 : }
1041 :
1042 : #endif
|