5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2002 - 2008 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 /****h* silcutil/Types and Definitions
24 * This header file includes basic types and definitions, and various system
25 * specific macros and functions used in SILC Toolkits. Application programmer
26 * may use them when needed.
33 /* The bool macro is deprecated. Use SilcBool instead. */
39 #define bool unsigned char
43 #if SILC_SIZEOF_SHORT > 2
44 #error "size of the short must be 2 bytes"
47 /****d* silcutil/SilcBool
51 * typedef unigned char SilcBool;
55 * Boolean value, and is always 8-bits. Represents value 0 or 1.
58 typedef unsigned char SilcBool;
68 * Boolean true value indicator.
77 /****d* silcutil/FALSE
85 * Boolean false value indicator.
94 /****d* silcutil/SilcUInt8
98 * typedef unsigned char SilcUInt8;
102 * 8-bit unsigned integer.
106 typedef unsigned char SilcUInt8;
109 /****d* silcutil/SilcInt8
113 * typedef signed char SilcInt8;
117 * 8-bit signed integer.
121 typedef signed char SilcInt8;
124 /****d* silcutil/SilcUInt16
128 * typedef unsigned short SilcUInt16;
132 * 16-bit unsigned integer. Guaranteed to be 16-bits.
136 typedef unsigned short SilcUInt16;
139 /****d* silcutil/SilcInt16
143 * typedef signed short SilcInt16;
147 * 16-bit signed integer. Guaranteed to be 16-bits.
151 typedef signed short SilcInt16;
154 /****d* silcutil/SilcUInt32
158 * typedef unsigned long SilcUInt32;
162 * 32-bit unsigned integer. Guaranteed to be 32-bits.
166 #if SILC_SIZEOF_LONG == 4
167 typedef unsigned long SilcUInt32;
168 typedef signed long SilcInt32;
170 #if SILC_SIZEOF_INT == 4
171 typedef unsigned int SilcUInt32;
172 typedef signed int SilcInt32;
174 #if SILC_SIZEOF_LONG_LONG >= 4
176 typedef unsigned long long SilcUInt32;
177 typedef signed long long SilcInt32;
184 /****d* silcutil/SilcInt32
188 * typedef signed long SilcInt32;
192 * 32-bit signed integer. Guaranteed to be 32-bits.
196 /****d* silcutil/SilcUInt64
200 * typedef unsigned long long SilcUInt64;
204 * 64-bit unsigned integer. Guaranteed to be 64-bits on systems that
209 #if SILC_SIZEOF_LONG >= 8
210 typedef unsigned long SilcUInt64;
211 typedef signed long SilcInt64;
213 #if SILC_SIZEOF_LONG_LONG >= 8
215 typedef unsigned long long SilcUInt64;
216 typedef signed long long SilcInt64;
218 typedef unsigned __int64 SilcUInt64;
219 typedef signed __int64 SilcInt64;
222 typedef SilcUInt32 SilcUInt64;
223 typedef SilcInt32 SilcInt64;
228 /****d* silcutil/SilcInt64
232 * typedef signed long long SilcInt64;
236 * 64-bit signed integer. Guaranteed to be 64-bits on systems that
241 /****d* silcutil/SilcFloat32
245 * typedef float SilcFloat32;
249 * 32-bit floating point number.
252 typedef float SilcFloat32;
254 /****d* silcutil/SilcFloat64
258 * typedef double SilcFloat64;
262 * 64-bit floating point number.
265 typedef double SilcFloat64;
267 #if SILC_SIZEOF_VOID_P < 4
268 typedef SilcUInt32 * void *;
271 /****d* silcutil/SilcSocket
279 * Platform specific socket. On POSIX compliant systems this is simply
280 * an integer, representing the socket. On other systems it is platform
281 * specific socket context. Access it only through routines that can
282 * handle SilcSocket types.
286 #if defined(SILC_UNIX)
287 typedef int SilcSocket;
288 #elif defined(SILC_WIN32)
289 typedef SOCKET SilcSocket;
290 #elif defined(SILC_SYMBIAN)
291 typedef void * SilcSocket;
295 /****d* silcutil/SilcParam
299 * typedef SilcUInt32 SilcParam;
303 * A generic parameters that describe the type of an parameter or argument.
304 * They can be used to describe function arguments, buffer encoding format,
309 typedef SilcUInt32 SilcParam;
311 #define SILC_PARAM_SINT8 1 /* SilcInt8 */
312 #define SILC_PARAM_UINT8 2 /* SilcUInt8 */
313 #define SILC_PARAM_SINT16 3 /* SilcInt16 */
314 #define SILC_PARAM_UINT16 4 /* SilcUInt16 */
315 #define SILC_PARAM_SINT32 5 /* SilcInt32 */
316 #define SILC_PARAM_UINT32 6 /* SilcUInt32 */
317 #define SILC_PARAM_SINT64 7 /* SilcInt64 */
318 #define SILC_PARAM_UINT64 8 /* SilcUInt64 */
319 #define SILC_PARAM_SICHAR 9 /* signed char * */
320 #define SILC_PARAM_UICHAR 10 /* unsigned char * */
321 #define SILC_PARAM_BUFFER 11 /* SilcBuffer */
322 #define SILC_PARAM_PTR 12 /* void * */
323 #define SILC_PARAM_END 0xfeeefff1 /* End of parameters */
326 /* Internal parameter types, not publicly documented, used mainly by the
327 SILC Buffer Format API (silcbuffmt.h). */
328 #define SILC_PARAM_UI8_STRING 100 /* String (max len 8-bits) */
329 #define SILC_PARAM_UI16_STRING 101 /* String (max len 16-bits) */
330 #define SILC_PARAM_UI32_STRING 102 /* String (max len 32-bits) */
331 #define SILC_PARAM_UI8_NSTRING 103 /* String (max len 8-bits) */
332 #define SILC_PARAM_UI16_NSTRING 104 /* String (max len 16-bits) */
333 #define SILC_PARAM_UI32_NSTRING 105 /* String (max len 32-bits) */
334 #define SILC_PARAM_OFFSET 106
335 #define SILC_PARAM_ADVANCE 107
336 #define SILC_PARAM_FUNC 108
337 #define SILC_PARAM_REGEX 109
338 #define SILC_PARAM_OFFSET_START 110
339 #define SILC_PARAM_OFFSET_END 111
340 #define SILC_PARAM_DELETE 112
341 #define SILC_PARAM_ALLOC 0x00010000 /* Allocate, bitmask */
342 #define SILC_PARAM_REPLACE 0x00020000 /* Replace, bitmask */
344 /****d* silcutil/SilcCompareValue
348 * typedef enum { ... } SilcCompareValue
352 * Values that can be returned by the SilcCompare function. Note that
353 * not all routines may respect all of the return values.
358 SILC_COMPARE_LESS_THAN_EQUAL_TO = -2, /* Value 1 <= value 2 */
359 SILC_COMPARE_LESS_THAN = -1, /* Value 1 < value 2 */
360 SILC_COMPARE_EQUAL_TO = 0, /* Value 1 == value 2 */
361 SILC_COMPARE_GREATER_THAN = 1, /* Value 1 > value 2 */
362 SILC_COMPARE_GREATER_THAN_EQUAL_TO = 2, /* Value 1 >= value 2 */
363 SILC_COMPARE_STOP = 3, /* Stop comparison */
367 /****f* silcutil/SilcCompare
371 * typedef SilcCompareValue (*SilcCompare)(void *value1, void *value2,
376 * A comparison function used by many routines in SILC Runtime Toolkit.
379 typedef SilcCompareValue (*SilcCompare)(void *value1, void *value2,
384 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
385 #define SILC_GET_WORD(cp) \
387 SilcUInt32 _result_; \
388 asm volatile ("movl (%1), %0; bswapl %0" \
389 : "=q" (_result_) : "q" (cp)); \
393 #define SILC_GET_WORD(cp) ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24 \
394 | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16) \
395 | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8) \
396 | ((SilcUInt32)(SilcUInt8)(cp)[3])
397 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
399 /****d* silcutil/SILC_MAX
403 * #define SILC_MAX(a, b)
407 * Return `a' if it is bigger than `b', otherwise return `b'.
410 #define SILC_MAX(a, b) ((a) > (b) ? (a) : (b))
412 /****d* silcutil/SILC_MIN
416 * #define SILC_MIN(a, b)
420 * Return `a' if it is smaller than `b', otherwise return `b'.
423 #define SILC_MIN(a, b) ((a) < (b) ? (a) : (b))
425 /****d* silcutil/SILC_GET16_MSB
429 * #define SILC_GET16_MSB(dest, src)
433 * Return two 8-bit bytes, most significant bytes first.
437 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
438 #define SILC_GET16_MSB(l, cp) \
439 asm volatile ("movw (%1), %w0; rolw $8, %w0" \
440 : "=q" (l) : "q" (cp) : "memory", "cc");
442 #define SILC_GET16_MSB(l, cp) \
444 (l) = ((SilcUInt32)(SilcUInt8)(cp)[0] << 8) \
445 | ((SilcUInt32)(SilcUInt8)(cp)[1]); \
447 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
450 /****d* silcutil/SILC_GET32_MSB
454 * #define SILC_GET32_MSB(dest, src)
458 * Return four 8-bit bytes, most significant bytes first.
462 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
463 #define SILC_GET32_MSB(l, cp) \
464 asm volatile ("movl (%1), %0; bswapl %0" \
465 : "=q" (l) : "q" (cp) : "memory", "cc");
467 #define SILC_GET32_MSB(l, cp) \
469 (l) = ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24 \
470 | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16) \
471 | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8) \
472 | ((SilcUInt32)(SilcUInt8)(cp)[3]); \
474 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
477 /* Same as upper but XOR the result always. Special purpose macro. */
478 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
479 #define SILC_GET32_X_MSB(l, cp) \
481 register volatile SilcUInt32 _x_; \
482 asm volatile ("movl %1, %3; movl (%2), %0;\n\t" \
483 "bswapl %0; xorl %3, %0" \
484 : "=r" (l) : "0" (l), "r" (cp), "r" (_x_) \
488 #define SILC_GET32_X_MSB(l, cp) \
489 (l) ^= ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24 \
490 | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16) \
491 | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8) \
492 | ((SilcUInt32)(SilcUInt8)(cp)[3]);
493 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
495 /****d* silcutil/SILC_GET64_MSB
499 * #define SILC_GET64_MSB(dest, src)
503 * Return eight 8-bit bytes, most significant bytes first.
507 #if defined(SILC_X86_64) && defined(__GNUC__)
508 #define SILC_GET64_MSB(l, cp) \
509 asm volatile ("movq (%1), %0; bswapq %0" \
510 : "=r" (l) : "r" (cp) : "memory", "cc");
512 #define SILC_GET64_MSB(l, cp) \
514 (l) = ((((SilcUInt64)SILC_GET_WORD((cp))) << 32) | \
515 ((SilcUInt64)SILC_GET_WORD((cp) + 4))); \
517 #endif /* SILC_X86_64 && __GNUC__ */
520 /****d* silcutil/SILC_GET16_LSB
524 * #define SILC_GET16_MSB(dest, src)
528 * Return two 8-bit bytes, least significant bytes first.
532 #if defined(SILC_I386) || defined(SILC_X86_64)
533 #define SILC_GET16_LSB(l, cp) (l) = (*(SilcUInt16 *)(cp))
535 #define SILC_GET16_LSB(l, cp) \
537 (l) = ((SilcUInt32)(SilcUInt8)(cp)[0]) \
538 | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8); \
540 #endif /* SILC_I386 || SILC_X86_64 */
543 /****d* silcutil/SILC_GET32_LSB
547 * #define SILC_GET32_LSB(dest, src)
551 * Return four 8-bit bytes, least significant bytes first.
555 #if defined(SILC_I386) || defined(SILC_X86_64)
556 #define SILC_GET32_LSB(l, cp) (l) = (*(SilcUInt32 *)(cp))
558 #define SILC_GET32_LSB(l, cp) \
560 (l) = ((SilcUInt32)(SilcUInt8)(cp)[0]) \
561 | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8) \
562 | ((SilcUInt32)(SilcUInt8)(cp)[2] << 16) \
563 | ((SilcUInt32)(SilcUInt8)(cp)[3] << 24); \
565 #endif /* SILC_I386 || SILC_X86_64 */
568 /* Same as upper but XOR the result always. Special purpose macro. */
569 #if defined(SILC_I386) || defined(SILC_X86_64)
570 #define SILC_GET32_X_LSB(l, cp) (l) ^= (*(SilcUInt32 *)(cp))
572 #define SILC_GET32_X_LSB(l, cp) \
573 (l) ^= ((SilcUInt32)(SilcUInt8)(cp)[0]) \
574 | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8) \
575 | ((SilcUInt32)(SilcUInt8)(cp)[2] << 16) \
576 | ((SilcUInt32)(SilcUInt8)(cp)[3] << 24)
577 #endif /* SILC_I386 || SILC_X86_64 */
579 /****d* silcutil/SILC_PUT16_MSB
583 * #define SILC_PUT16_MSB(dest, src)
587 * Put two 8-bit bytes, most significant bytes first.
591 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
592 #define SILC_PUT16_MSB(l, cp) \
593 asm volatile ("rolw $8, %w1; movw %w1, (%0)" \
594 : : "q" (cp), "q" (l) : "memory", "cc");
596 #define SILC_PUT16_MSB(l, cp) \
598 (cp)[0] = (SilcUInt8)((l) >> 8); \
599 (cp)[1] = (SilcUInt8)(l); \
601 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
604 /****d* silcutil/SILC_PUT32_MSB
608 * #define SILC_PUT32_MSB(dest, src)
612 * Put four 8-bit bytes, most significant bytes first.
616 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
617 #define SILC_PUT32_MSB(l, cp) \
618 asm volatile ("bswapl %1; movl %1, (%0); bswapl %1" \
619 : : "q" (cp), "q" (l) : "memory", "cc");
621 #define SILC_PUT32_MSB(l, cp) \
623 (cp)[0] = (SilcUInt8)((l) >> 24); \
624 (cp)[1] = (SilcUInt8)((l) >> 16); \
625 (cp)[2] = (SilcUInt8)((l) >> 8); \
626 (cp)[3] = (SilcUInt8)(l); \
628 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
631 /****d* silcutil/SILC_PUT64_MSB
635 * #define SILC_PUT64_MSB(dest, src)
639 * Put eight 8-bit bytes, most significant bytes first.
643 #if defined(SILC_X86_64) && defined(__GNUC__)
644 #define SILC_PUT64_MSB(l, cp) \
645 asm volatile ("bswapq %1; movq %1, (%0); bswapq %1" \
646 : : "r" (cp), "r" (l) : "memory", "cc");
648 #define SILC_PUT64_MSB(l, cp) \
650 SILC_PUT32_MSB((SilcUInt32)((SilcUInt64)(l) >> 32), (cp)); \
651 SILC_PUT32_MSB((SilcUInt32)(l), (cp) + 4); \
653 #endif /* SILC_X86_64 && __GNUC__ */
656 /****d* silcutil/SILC_PUT16_LSB
660 * #define SILC_PUT16_LSB(dest, src)
664 * Put two 8-bit bytes, least significant bytes first.
668 #if defined(SILC_I386) || defined(SILC_X86_64)
669 #define SILC_PUT16_LSB(l, cp) (*(SilcUInt16 *)(cp)) = (l)
671 #define SILC_PUT16_LSB(l, cp) \
673 (cp)[0] = (SilcUInt8)(l); \
674 (cp)[1] = (SilcUInt8)((l) >> 8); \
676 #endif /* SILC_I386 || SILC_X86_64 */
679 /****d* silcutil/SILC_PUT32_LSB
683 * #define SILC_PUT32_LSB(dest, src)
687 * Put four 8-bit bytes, least significant bytes first.
691 #if defined(SILC_I386) || defined(SILC_X86_64)
692 #define SILC_PUT32_LSB(l, cp) (*(SilcUInt32 *)(cp)) = (l)
694 #define SILC_PUT32_LSB(l, cp) \
696 (cp)[0] = (SilcUInt8)(l); \
697 (cp)[1] = (SilcUInt8)((l) >> 8); \
698 (cp)[2] = (SilcUInt8)((l) >> 16); \
699 (cp)[3] = (SilcUInt8)((l) >> 24); \
701 #endif /* SILC_I386 || SILC_X86_64 */
704 /****d* silcutil/SILC_SWAB_16
708 * #define SILC_SWAB_16(integer)
712 * Swabs 16-bit unsigned integer byte order. Returns the new value.
716 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
717 #define SILC_SWAB_16(l) \
719 SilcUInt16 _result_; \
720 asm volatile ("movw %w1, %w0; rolw $8, %w0" \
721 : "=q" (_result_) : "q" (l)); \
725 #define SILC_SWAB_16(l) \
726 ((SilcUInt16)(((SilcUInt16)(l) & (SilcUInt16)0x00FFU) << 8) | \
727 (((SilcUInt16)(l) & (SilcUInt16)0xFF00U) >> 8))
728 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
731 /****d* silcutil/SILC_SWAB_32
735 * #define SILC_SWAB_32(integer)
739 * Swabs 32-bit unsigned integer byte order. Returns the new value.
743 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
744 #define SILC_SWAB_32(l) \
746 SilcUInt32 _result_; \
747 asm volatile ("movl %1, %0; bswapl %0" \
748 : "=q" (_result_) : "q" (l)); \
752 #define SILC_SWAB_32(l) \
753 ((SilcUInt32)(((SilcUInt32)(l) & (SilcUInt32)0x000000FFUL) << 24) | \
754 (((SilcUInt32)(l) & (SilcUInt32)0x0000FF00UL) << 8) | \
755 (((SilcUInt32)(l) & (SilcUInt32)0x00FF0000UL) >> 8) | \
756 (((SilcUInt32)(l) & (SilcUInt32)0xFF000000UL) >> 24))
757 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
760 /****d* silcutil/SILC_PTR_TO_32
764 * #define SILC_PTR_TO_32(ptr)
768 * Type casts a pointer's value into a 32-bit integer. Use this to
769 * avoid compiler warnings when type casting pointers to integers
774 #if SILC_SIZEOF_VOID_P < 8
775 #define SILC_PTR_TO_32(_ptr__) ((SilcUInt32)(_ptr__))
777 #define SILC_PTR_TO_32(_ptr__) \
778 ((SilcUInt32)((SilcUInt64)(_ptr__) & (SilcUInt32)0xFFFFFFFFUL))
782 /****d* silcutil/SILC_PTR_TO_64
786 * #define SILC_PTR_TO_64(ptr)
790 * Type casts a pointer's value into a 64-bit integer. Use this to
791 * avoid compiler warnings when type casting pointers to integers
796 #if SILC_SIZEOF_VOID_P < 8
797 #define SILC_PTR_TO_64(_ptr__) ((SilcUInt64)((SilcUInt32)(_ptr__)))
799 #define SILC_PTR_TO_64(_ptr__) ((SilcUInt64)((SilcUInt64)(_ptr__)))
803 /****d* silcutil/SILC_32_TO_PTR
807 * #define SILC_32_TO_PTR(ptr)
811 * Type casts a 32-bit integer value into a pointer. Use this to
812 * avoid compiler warnings when type casting integers to pointers of
817 #if SILC_SIZEOF_VOID_P < 8
818 #define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt32)(_ival__)))
820 #define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
824 /****d* silcutil/SILC_64_TO_PTR
828 * #define SILC_64_TO_PTR(ptr)
832 * Type casts a 64-bit integer value into a pointer. Use this to
833 * avoid compiler warnings when type casting integers to pointers of
838 #if SILC_SIZEOF_VOID_P < 8
839 #define SILC_64_TO_PTR(_ival__) \
840 ((void *)((SilcUInt32)((SilcUInt64)(_ival__) & (SilcUInt32)0xFFFFFFFFUL)))
842 #define SILC_64_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
846 /****d* silcutil/SILC_ASSERT
850 * #define SILC_ASSERT(experssion)
854 * Assert macro that prints error message to stderr and calls abort()
855 * if the `expression' is false (ie. compares equal to zero). If
856 * SILC_DEBUG is not defined this macro has no effect.
860 #if defined(SILC_DEBUG)
861 #define SILC_ASSERT(expr) assert((expr));
863 #define SILC_ASSERT(expr) do { } while(0)
864 #endif /* SILC_DEBUG */
867 /****d* silcutil/SILC_VERIFY
871 * #define SILC_VERIFY(experssion)
875 * Verification macro that prints error message to stderr and calls
876 * abort() if the `expression' is false (ie. compares equal to zero)
877 * on debug builds (SILC_DEBUG defined), and prints error message to
878 * stderr on release builds (SILC_DEBUG undefined) but does not abort().
879 * This macro is always compiled even if debugging (SILC_DEBUG) is not
884 #if defined(SILC_DEBUG)
885 #define SILC_VERIFY(expr) assert((expr));
887 #define SILC_VERIFY(expr) \
888 if (silc_unlikely(!(expr))) { \
889 SILC_LOG_ERROR(("SILC_VERIFY %s:%s:%d", \
890 __FILE__, __FUNCTION__, __LINE__)); \
891 silc_set_errno_reason_nofail(SILC_ERR_ASSERT, "SILC_VERIFY %s:%s:%d", \
892 __FILE__, __FUNCTION__, __LINE__); \
894 #endif /* SILC_DEBUG */
897 /****d* silcutil/silc_rol
901 * static inline SilcUInt32 silc_rol(SilcUInt32 val, int num);
905 * Rotate 32-bit integer's bits to left `num' times. Bits pushed to the
906 * left will appear from the right side of the integer, thus rotating.
907 * Returns the rotated value.
910 static inline SilcUInt32 silc_rol(SilcUInt32 val, int num)
912 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
913 asm volatile ("roll %%cl, %0"
914 : "=r" (val) : "0" (val), "c" (num));
917 return ((val << (SilcUInt32)num) | (val >> (32 - (SilcUInt32)num)));
918 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
921 /****d* silcutil/silc_rolc
925 * static inline SilcUInt32 silc_rolc(SilcUInt32 val, const int num);
929 * Rotate 32-bit integer's bits to left `num' times. Bits pushed to the
930 * left will appear from the right side of the integer, thus rotating.
931 * Returns the rotated value.
934 static inline SilcUInt32 silc_rolc(SilcUInt32 val, const int num)
936 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
937 asm volatile ("roll %2, %0"
938 : "=r" (val) : "0" (val), "I" (num));
941 return ((val << (SilcUInt32)num) | (val >> (32 - (SilcUInt32)num)));
942 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
945 /****d* silcutil/silc_ror
949 * static inline SilcUInt32 silc_ror(SilcUInt32 val, int num);
953 * Rotate 32-bit integer's bits to right `num' times. Bits pushed to the
954 * right will appear from the left side of the integer, thus rotating.
955 * Returns the rotated value.
958 static inline SilcUInt32 silc_ror(SilcUInt32 val, int num)
960 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
961 asm volatile ("rorl %%cl, %0"
962 : "=r" (val) : "0" (val), "c" (num));
965 return ((val >> (SilcUInt32)num) | (val << (32 - (SilcUInt32)num)));
966 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
969 /****d* silcutil/silc_rorc
973 * static inline SilcUInt32 silc_ror(SilcUInt32 val, const int num);
977 * Rotate 32-bit integer's bits to right `num' times. Bits pushed to the
978 * right will appear from the left side of the integer, thus rotating.
979 * Returns the rotated value.
982 static inline SilcUInt32 silc_rorc(SilcUInt32 val, const int num)
984 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
985 asm volatile ("rorl %2, %0"
986 : "=r" (val) : "0" (val), "I" (num));
989 return ((val >> (SilcUInt32)num) | (val << (32 - (SilcUInt32)num)));
990 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
993 /****d* silcutil/silc_rol64
997 * static inline SilcUInt64 silc_rol64(SilcUInt64 val, int num);
1001 * Rotate 64-bit integer's bits to left `num' times. Bits pushed to the
1002 * left will appear from the right side of the integer, thus rotating.
1003 * Returns the rotated value.
1006 static inline SilcUInt64 silc_rol64(SilcUInt64 val, int num)
1008 #if defined(SILC_X86_64) && defined(__GNUC__)
1009 asm volatile ("rolq %%cl, %0"
1010 : "=r" (val) : "0" (val), "c" (num));
1013 return ((val << (SilcUInt64)num) | (val >> (64 - (SilcUInt64)num)));
1014 #endif /* SILC_X86_64 && __GNUC__ */
1017 /****d* silcutil/silc_rolc64
1021 * static inline SilcUInt64 silc_rolc64(SilcUInt64 val, const int num);
1025 * Rotate 64-bit integer's bits to left `num' times. Bits pushed to the
1026 * left will appear from the right side of the integer, thus rotating.
1027 * Returns the rotated value.
1030 static inline SilcUInt64 silc_rolc64(SilcUInt64 val, const int num)
1032 #if defined(SILC_X86_64) && defined(__GNUC__)
1033 asm volatile ("rolq %2, %0"
1034 : "=r" (val) : "0" (val), "J" (num));
1037 return ((val << (SilcUInt64)num) | (val >> (64 - (SilcUInt64)num)));
1038 #endif /* SILC_X86_64 && __GNUC__ */
1041 /****d* silcutil/silc_ror64
1045 * static inline SilcUInt64 silc_ror64(SilcUInt64 val, int num);
1049 * Rotate 64-bit integer's bits to right `num' times. Bits pushed to the
1050 * right will appear from the left side of the integer, thus rotating.
1051 * Returns the rotated value.
1054 static inline SilcUInt64 silc_ror64(SilcUInt64 val, int num)
1056 #if defined(SILC_X86_64) && defined(__GNUC__)
1057 asm volatile ("rorq %%cl, %0"
1058 : "=r" (val) : "0" (val), "c" (num));
1061 return ((val >> (SilcUInt64)num) | (val << (64 - (SilcUInt64)num)));
1062 #endif /* SILC_X86_64 && __GNUC__ */
1065 /****d* silcutil/silc_rorc64
1069 * static inline SilcUInt64 silc_rorc64(SilcUInt64 val, const int num);
1073 * Rotate 64-bit integer's bits to right `num' times. Bits pushed to the
1074 * right will appear from the left side of the integer, thus rotating.
1075 * Returns the rotated value.
1078 static inline SilcUInt64 silc_rorc64(SilcUInt64 val, const int num)
1080 #if defined(SILC_X86_64) && defined(__GNUC__)
1081 asm volatile ("rorq %2, %0"
1082 : "=r" (val) : "0" (val), "J" (num));
1085 return ((val >> (SilcUInt64)num) | (val << (64 - (SilcUInt64)num)));
1086 #endif /* SILC_X86_64 && __GNUC__ */
1089 /****d* silcutil/silc_offsetof
1093 * #define silc_offsetof(TYPE, MEMBER)
1097 * offsetof() macro replacement. Use this instead of offsetof().
1100 #define silc_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
1102 /****d* silcutil/silc_attribute
1106 * #define silc_attribute(attrlist)
1110 * Compiler attributes. If compiler doesn't support attributes this macro
1111 * doesn't do anything. Currently this works only with GCC compiler.
1112 * See GCC documentation for specified attributes.
1116 * int printf(const char *fmt, ...) silc_attribute((format(printf, 1, 2)));
1119 #if defined(__GNUC__)
1120 #define silc_attribute(attrlist) __attribute__ (attrlist)
1122 #define silc_attribute(attrlist)
1123 #endif /* __GNUC__ */
1125 /****d* silcutil/silc_likely
1129 * #define silc_likely(expression)
1133 * Branch prediction macro. It specifies that it is likely that the branch
1134 * where silc_likely is applied is taken. Compiler will optimize the
1135 * code based on this prediction. Never use this before you have profiled
1140 /****d* silcutil/silc_unlikely
1144 * #define silc_unlikely(expression)
1148 * Branch prediction macro. It specifies that it is unlikely that the
1149 * branch where silc_unlikely is applied is taken. Compiler will optimize
1150 * the code based on this prediction. Never use this before you have
1151 * profiled the code first.
1155 #define silc_likely(expr) __builtin_expect(!!(expr), 1)
1156 #define silc_unlikely(expr) __builtin_expect(!!(expr), 0)
1158 #define silc_likely(expr) (expr)
1159 #define silc_unlikely(expr) (expr)
1160 #endif /* __GNUC__ >= 3 */
1162 /* Prefetch operations. Use these to prefetch data to CPU cache before
1163 reading or writing if you think that the data will be needed soon after
1166 /****d* silcutil/silc_prefetch
1170 * static inline void silc_prefetch(void *addr, int rw, int locality);
1174 * Simple prefetch. Loads memory from specified address to CPU cache.
1175 * The amount of data loaded is CPU dependant (cache line length). The
1176 * `rw' argument defines the reason for prefetch: 0=read, 1=write. The
1177 * `locality' argument defines the locality of the prefetch, 0=non-temporal
1178 * (non-temporal cache, cache closest to CPU, data will not stay long in
1179 * the cache), 1=temporal (L2+ cache), 2=temporal (L2, L3+ cache),
1180 * 3=temporal (fetch to all caches, data stays longer time in cache).
1184 * This produces only a hint for CPU. CPU doesn't have to actually
1185 * prefetch the data. Use silc_prefetch_block to ensure CPU always
1190 static inline silc_attribute((always_inline))
1191 void silc_prefetch(void *addr, int rw, int locality)
1194 __builtin_prefetch(addr, rw, locality);
1195 #endif /* __GNUC__ */
1198 /****d* silcutil/silc_prefetch_block
1202 * static inline void silc_prefetch_block(void *addr,
1203 * int prefetch_length,
1204 * const int cache_line_length)
1208 * Enforced block prefetch. This function loads the specified amount
1209 * `prefetch_length' of memory from the specified address `addr' to CPU
1210 * cache with each loaded cache line being the size of `cache_line_length'.
1211 * If you don't know the cache line size use 64 bytes. Note that, the
1212 * `cache_line_length' is a const int. In this context this mean its
1213 * value must not come from a variable but must be a constant (the code
1214 * won't compile if it comes from a variable).
1216 * The `prefetch_length' must be multiple of twice of the
1217 * `cache_line_length' or 128 if you don't know the cache line size, hence
1218 * the minimum length for `prefetch_length' is 128 bytes when the
1219 * `cache_line_length' is 64 bytes. Shorter cache line length (32 bytes)
1222 * You should use the correct `cache_line_length' value for your CPU or
1223 * the value of the CPU for which you want to optimize your code. Intel
1224 * CPUs usually have cache size of 32 or 64 bytes. The most optimal
1225 * prefetch is achieved if the `cache_line_length' is the actual CPU cache
1226 * line size. Always do performance testing with and without prefetching
1227 * to make sure the prefetch actually helps. If used improperly, it may
1228 * slow down your program.
1230 * The difference to silc_prefetch is that this function always performs
1231 * the prefetch and has the ability to prefetch more than one cache line
1232 * worth of memory, whereas silc_prefetch can prefetch only one cache line
1233 * and may not do the prefetch at all.
1237 static inline silc_attribute((always_inline))
1238 void silc_prefetch_block(void *addr,
1239 int prefetch_length,
1240 const int cache_line_length)
1243 SILC_ASSERT(cache_line_length >= 32);
1244 SILC_ASSERT(cache_line_length % 32 == 0);
1245 SILC_ASSERT(prefetch_length >= cache_line_length);
1246 SILC_ASSERT(prefetch_length % (cache_line_length * 2) == 0);
1249 #if SILC_SIZEOF_VOID_P < 8
1250 #define SILC_PREFETCH_UINT SilcUInt32
1252 #define SILC_PREFETCH_UINT SilcUInt64
1253 #endif /* SILC_SIZEOF_VOID_P < 8 */
1255 #if defined(__GNUC__) && (defined(SILC_I386) || defined(SILC_X86_64))
1257 /* Assembler implementation.
1259 The idea here is to simply enforce the CPU to load the requested amount
1260 of bytes to cache. We simply mov data from the memory to a register.
1261 Each mov will load a full cache line worth of data from the memory.
1263 We expect the `cache_line_length' to be the actual cache line size.
1264 It doesn't matter if it is. If it is smaller the prefetch is a bit
1265 slower as there is redundancy. If it is larger we skip some of the
1266 data and don't prefetch everything.
1268 The loop is unrolled to handle two mov's at once, this why we expect
1269 the `prefetch_length' to be multiple of twice the length of
1270 `cache_line_length`. We also mov the data from end to beginning instead
1271 of from the beginning to assure CPU doesn't prefetch the data before
1272 we actually want to do it.
1274 This technique is described by AMD in:
1275 http://cdrom.amd.com/devconn/events/AMD_block_prefetch_paper.pdf */
1278 SILC_PREFETCH_UINT temp;
1280 #define SILC_PREFETCH_ASM(ip, rp) \
1281 asm volatile ("1: \n\t" \
1282 "mov" ip " -%c4(%2, %" rp "3), %0 \n\t" \
1283 "mov" ip " -%c5(%2, %" rp "3), %0 \n\t" \
1284 "sub" ip " %5, %" rp "3 \n\t" \
1286 : "=&r" (temp), "=r" (prefetch_length) \
1287 : "r" (addr), "1" (prefetch_length), \
1288 "Z" (cache_line_length), \
1289 "Z" (cache_line_length * 2) \
1292 #if defined(SILC_I386)
1293 /* 32-bit prefetch */
1294 SILC_PREFETCH_ASM("l", "");
1296 /* 64-bit prefetch */
1297 SILC_PREFETCH_ASM("q", "q");
1298 #endif /* SILC_I386 */
1302 /* C implementation. Yes, you can do it in C too. In fact, we'll try to
1303 make the compiler generate nearly identical code to the above assembler
1304 code. Note that, the memory access must be volatile, otherwise the
1305 compiler will optimize them away because the temp variable isn't actually
1306 used for anything. This should be as fast as the assembler code above,
1307 unless the compiler decides to start meddling with it (don't use
1308 -funroll-loops with this code). */
1311 register unsigned char *a = addr;
1312 register int len = prefetch_length;
1313 register SILC_PREFETCH_UINT temp;
1316 temp = *(SILC_PREFETCH_UINT volatile *)
1317 (a + (len - cache_line_length));
1318 temp = *(SILC_PREFETCH_UINT volatile *)
1319 (a + (len - (cache_line_length * 2)));
1320 len -= (cache_line_length * 2);
1323 #endif /* __GNUC__ */
1324 #undef SILC_PREFETCH_UINT
1325 #undef SILC_PREFETCH_ASM
1328 #endif /* SILCTYPES_H */