Added SILC Thread Queue API
[silc.git] / lib / silcutil / silctypes.h
1 /*
2
3   silctypes.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2002 - 2008 Pekka Riikonen
8
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.
12
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.
17
18 */
19
20 /****h* silcutil/SILC Types
21  *
22  * DESCRIPTION
23  *
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.
27  *
28  ***/
29
30 #ifndef SILCTYPES_H
31 #define SILCTYPES_H
32
33 /* The bool macro is deprecated.  Use SilcBool instead. */
34 #ifdef SILC_MACOSX
35 #define bool _Bool
36 #endif
37 #ifndef __cplusplus
38 #ifndef bool
39 #define bool unsigned char
40 #endif
41 #endif
42
43 #if SILC_SIZEOF_SHORT > 2
44 #error "size of the short must be 2 bytes"
45 #endif
46
47 /******************************* Public API *********************************/
48
49 /****d* silcutil/SILCTypes/SilcBool
50  *
51  * NAME
52  *
53  *    typedef unigned char SilcBool;
54  *
55  * DESCRIPTION
56  *
57  *    Boolean value, and is always 8-bits.  Represents value 0 or 1.
58  *
59  ***/
60 typedef unsigned char SilcBool;
61
62 /****d* silcutil/SILCTypes/TRUE
63  *
64  * NAME
65  *
66  *    #define TRUE ...
67  *
68  * DESCRIPTION
69  *
70  *    Boolean true value indicator.
71  *
72  * SOURCE
73  */
74 #ifndef TRUE
75 #define TRUE 1
76 #endif
77 /***/
78
79 /****d* silcutil/SILCTypes/FALSE
80  *
81  * NAME
82  *
83  *    #define FALSE ...
84  *
85  * DESCRIPTION
86  *
87  *    Boolean false value indicator.
88  *
89  * SOURCE
90  */
91 #ifndef FALSE
92 #define FALSE 0
93 #endif
94 /***/
95
96 /****d* silcutil/SILCTypes/SilcUInt8
97  *
98  * NAME
99  *
100  *    typedef unsigned char SilcUInt8;
101  *
102  * DESCRIPTION
103  *
104  *    8-bit unsigned integer.
105  *
106  * SOURCE
107  */
108 typedef unsigned char SilcUInt8;
109 /***/
110
111 /****d* silcutil/SILCTypes/SilcInt8
112  *
113  * NAME
114  *
115  *    typedef signed char SilcInt8;
116  *
117  * DESCRIPTION
118  *
119  *    8-bit signed integer.
120  *
121  * SOURCE
122  */
123 typedef signed char SilcInt8;
124 /***/
125
126 /****d* silcutil/SILCTypes/SilcUInt16
127  *
128  * NAME
129  *
130  *    typedef unsigned short SilcUInt16;
131  *
132  * DESCRIPTION
133  *
134  *    16-bit unsigned integer.  Guaranteed to be 16-bits.
135  *
136  * SOURCE
137  */
138 typedef unsigned short SilcUInt16;
139 /***/
140
141 /****d* silcutil/SILCTypes/SilcInt16
142  *
143  * NAME
144  *
145  *    typedef signed short SilcInt16;
146  *
147  * DESCRIPTION
148  *
149  *    16-bit signed integer.  Guaranteed to be 16-bits.
150  *
151  * SOURCE
152  */
153 typedef signed short SilcInt16;
154 /***/
155
156 /****d* silcutil/SILCTypes/SilcUInt32
157  *
158  * NAME
159  *
160  *    typedef unsigned long SilcUInt32;
161  *
162  * DESCRIPTION
163  *
164  *    32-bit unsigned integer.  Guaranteed to be 32-bits.
165  *
166  * SOURCE
167  */
168 #if SILC_SIZEOF_LONG == 4
169 typedef unsigned long SilcUInt32;
170 typedef signed long SilcInt32;
171 #else
172 #if SILC_SIZEOF_INT == 4
173 typedef unsigned int SilcUInt32;
174 typedef signed int SilcInt32;
175 #else
176 #if SILC_SIZEOF_LONG_LONG >= 4
177 #ifndef WIN32
178 typedef unsigned long long SilcUInt32;
179 typedef signed long long SilcInt32;
180 #endif
181 #endif
182 #endif
183 #endif
184 /***/
185
186 /****d* silcutil/SILCTypes/SilcInt32
187  *
188  * NAME
189  *
190  *    typedef signed long SilcInt32;
191  *
192  * DESCRIPTION
193  *
194  *    32-bit signed integer.  Guaranteed to be 32-bits.
195  *
196  ***/
197
198 /****d* silcutil/SILCTypes/SilcUInt64
199  *
200  * NAME
201  *
202  *    typedef unsigned long long SilcUInt64;
203  *
204  * DESCRIPTION
205  *
206  *    64-bit unsigned integer.  Guaranteed to be 64-bits on systems that
207  *    support it.
208  *
209  * SOURCE
210  */
211 #if SILC_SIZEOF_LONG >= 8
212 typedef unsigned long SilcUInt64;
213 typedef signed long SilcInt64;
214 #else
215 #if SILC_SIZEOF_LONG_LONG >= 8
216 #ifndef WIN32
217 typedef unsigned long long SilcUInt64;
218 typedef signed long long SilcInt64;
219 #else
220 typedef unsigned __int64 SilcUInt64;
221 typedef signed __int64 SilcInt64;
222 #endif
223 #else
224 typedef SilcUInt32 SilcUInt64;
225 typedef SilcInt32 SilcInt64;
226 #endif
227 #endif
228 /***/
229
230 /****d* silcutil/SILCTypes/SilcInt64
231  *
232  * NAME
233  *
234  *    typedef signed long long SilcInt64;
235  *
236  * DESCRIPTION
237  *
238  *    64-bit signed integer.  Guaranteed to be 64-bits on systems that
239  *    support it.
240  *
241  ***/
242
243 #if SILC_SIZEOF_VOID_P < 4
244 typedef SilcUInt32 * void *;
245 #endif
246
247 /****d* silcutil/SILCTypes/SilcSocket
248  *
249  * NAME
250  *
251  *    SilcSocket
252  *
253  * DESCRIPTION
254  *
255  *    Platform specific socket.  On POSIX compliant systems this is simply
256  *    an integer, representing the socket. On other systems it is platform
257  *    specific socket context.  Access it only through routines that can
258  *    handle SilcSocket types, unless you know what you are doing.
259  *
260  * SOURCE
261  */
262 #if defined(SILC_UNIX)
263 typedef int SilcSocket;
264 #elif defined(SILC_WIN32)
265 typedef SOCKET SilcSocket;
266 #elif defined(SILC_SYMBIAN)
267 typedef void * SilcSocket;
268 #endif
269 /***/
270
271 /****d* silcutil/SILCTypes/SilcParam
272  *
273  * NAME
274  *
275  *    typedef SilcUInt32 SilcParam;
276  *
277  * DESCRIPTION
278  *
279  *    A generic parameters that describe the type of an parameter or argument.
280  *    They can be used to describe function arguments, buffer encoding format,
281  *    etc.
282  *
283  * SOURCE
284  */
285 typedef SilcUInt32 SilcParam;
286
287 #define SILC_PARAM_SINT8         1              /* SilcInt8 */
288 #define SILC_PARAM_UINT8         2              /* SilcUInt8 */
289 #define SILC_PARAM_SINT16        3              /* SilcInt16 */
290 #define SILC_PARAM_UINT16        4              /* SilcUInt16 */
291 #define SILC_PARAM_SINT32        5              /* SilcInt32 */
292 #define SILC_PARAM_UINT32        6              /* SilcUInt32 */
293 #define SILC_PARAM_SINT64        7              /* SilcInt64 */
294 #define SILC_PARAM_UINT64        8              /* SilcUInt64 */
295 #define SILC_PARAM_SICHAR        9              /* signed char * */
296 #define SILC_PARAM_UICHAR        10             /* unsigned char * */
297 #define SILC_PARAM_BUFFER        11             /* SilcBuffer */
298 #define SILC_PARAM_PTR           12             /* void * */
299 #define SILC_PARAM_END           0xfeeefff1     /* End of parameters */
300 /***/
301
302 /* Internal parameter types, not publicly documented, used mainly by the
303    SILC Buffer Format API (silcbuffmt.h). */
304 #define SILC_PARAM_UI8_STRING    100            /* String (max len 8-bits) */
305 #define SILC_PARAM_UI16_STRING   101            /* String (max len 16-bits) */
306 #define SILC_PARAM_UI32_STRING   102            /* String (max len 32-bits) */
307 #define SILC_PARAM_UI8_NSTRING   103            /* String (max len 8-bits) */
308 #define SILC_PARAM_UI16_NSTRING  104            /* String (max len 16-bits) */
309 #define SILC_PARAM_UI32_NSTRING  105            /* String (max len 32-bits) */
310 #define SILC_PARAM_OFFSET        106
311 #define SILC_PARAM_ADVANCE       107
312 #define SILC_PARAM_FUNC          108
313 #define SILC_PARAM_REGEX         109
314 #define SILC_PARAM_OFFSET_START  110
315 #define SILC_PARAM_OFFSET_END    111
316 #define SILC_PARAM_DELETE        112
317 #define SILC_PARAM_ALLOC         0x00010000     /* Allocate, bitmask */
318 #define SILC_PARAM_REPLACE       0x00020000     /* Replace, bitmask */
319
320 /* Macros */
321
322 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
323 #define SILC_GET_WORD(cp)                                               \
324 ({                                                                      \
325   SilcUInt32 _result_;                                                  \
326   asm volatile ("movl (%1), %0; bswapl %0"                              \
327                 : "=q" (_result_) : "q" (cp));                          \
328   _result_;                                                             \
329 })
330 #else
331 #define SILC_GET_WORD(cp) ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24        \
332                     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
333                     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
334                     | ((SilcUInt32)(SilcUInt8)(cp)[3])
335 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
336
337 /****d* silcutil/SILCTypes/SILC_GET16_MSB
338  *
339  * NAME
340  *
341  *    #define SILC_GET16_MSB(dest, src)
342  *
343  * DESCRIPTION
344  *
345  *    Return two 8-bit bytes, most significant bytes first.
346  *
347  * SOURCE
348  */
349 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
350 #define SILC_GET16_MSB(l, cp)                           \
351 asm volatile ("movw (%1), %w0; rolw $8, %w0"            \
352               : "=q" (l) : "q" (cp) : "memory", "cc");
353 #else
354 #define SILC_GET16_MSB(l, cp)                           \
355 do {                                                    \
356   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0] << 8)           \
357     | ((SilcUInt32)(SilcUInt8)(cp)[1]);                 \
358 } while(0)
359 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
360 /***/
361
362 /****d* silcutil/SILCTypes/SILC_GET32_MSB
363  *
364  * NAME
365  *
366  *    #define SILC_GET32_MSB(dest, src)
367  *
368  * DESCRIPTION
369  *
370  *    Return four 8-bit bytes, most significant bytes first.
371  *
372  * SOURCE
373  */
374 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
375 #define SILC_GET32_MSB(l, cp)                           \
376 asm volatile ("movl (%1), %0; bswapl %0"                \
377               : "=q" (l) : "q" (cp) : "memory", "cc");
378 #else
379 #define SILC_GET32_MSB(l, cp)                           \
380 do {                                                    \
381   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24          \
382     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
383     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
384     | ((SilcUInt32)(SilcUInt8)(cp)[3]);                 \
385 } while(0)
386 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
387 /***/
388
389 /* Same as upper but XOR the result always. Special purpose macro. */
390 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
391 #define SILC_GET32_X_MSB(l, cp)                                         \
392 do {                                                                    \
393   register volatile SilcUInt32 _x_;                                     \
394   asm volatile ("movl %1, %3; movl (%2), %0;\n\t"                       \
395                 "bswapl %0; xorl %3, %0"                                \
396                 : "=r" (l) : "0" (l), "r" (cp), "r" (_x_)               \
397                 : "memory", "cc");                                      \
398 } while(0)
399 #else
400 #define SILC_GET32_X_MSB(l, cp)                         \
401   (l) ^= ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24         \
402     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
403     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
404     | ((SilcUInt32)(SilcUInt8)(cp)[3]);
405 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
406
407 /****d* silcutil/SILCTypes/SILC_GET64_MSB
408  *
409  * NAME
410  *
411  *    #define SILC_GET64_MSB(dest, src)
412  *
413  * DESCRIPTION
414  *
415  *    Return eight 8-bit bytes, most significant bytes first.
416  *
417  * SOURCE
418  */
419 #if defined(SILC_X86_64) && defined(__GNUC__)
420 #define SILC_GET64_MSB(l, cp)                                   \
421 asm volatile ("movq (%1), %0; bswapq %0"                        \
422               : "=r" (l) : "r" (cp) : "memory", "cc");
423 #else
424 #define SILC_GET64_MSB(l, cp)                                   \
425 do {                                                            \
426   (l) = ((((SilcUInt64)SILC_GET_WORD((cp))) << 32) |            \
427          ((SilcUInt64)SILC_GET_WORD((cp) + 4)));                \
428 } while(0)
429 #endif /* SILC_X86_64 && __GNUC__ */
430 /***/
431
432 /****d* silcutil/SILCTypes/SILC_GET16_LSB
433  *
434  * NAME
435  *
436  *    #define SILC_GET16_MSB(dest, src)
437  *
438  * DESCRIPTION
439  *
440  *    Return two 8-bit bytes, least significant bytes first.
441  *
442  * SOURCE
443  */
444 #if defined(SILC_I386) || defined(SILC_X86_64)
445 #define SILC_GET16_LSB(l, cp) (l) = (*(SilcUInt16 *)(cp))
446 #else
447 #define SILC_GET16_LSB(l, cp)                           \
448 do {                                                    \
449   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0])                \
450     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8);            \
451 } while(0)
452 #endif /* SILC_I386 || SILC_X86_64 */
453 /***/
454
455 /****d* silcutil/SILCTypes/SILC_GET32_LSB
456  *
457  * NAME
458  *
459  *    #define SILC_GET32_LSB(dest, src)
460  *
461  * DESCRIPTION
462  *
463  *    Return four 8-bit bytes, least significant bytes first.
464  *
465  * SOURCE
466  */
467 #if defined(SILC_I386) || defined(SILC_X86_64)
468 #define SILC_GET32_LSB(l, cp) (l) = (*(SilcUInt32 *)(cp))
469 #else
470 #define SILC_GET32_LSB(l, cp)                           \
471 do {                                                    \
472   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0])                \
473     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8)             \
474     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 16)            \
475     | ((SilcUInt32)(SilcUInt8)(cp)[3] << 24);           \
476 } while(0)
477 #endif /* SILC_I386 || SILC_X86_64 */
478 /***/
479
480 /* Same as upper but XOR the result always. Special purpose macro. */
481 #if defined(SILC_I386) || defined(SILC_X86_64)
482 #define SILC_GET32_X_LSB(l, cp) (l) ^= (*(SilcUInt32 *)(cp))
483 #else
484 #define SILC_GET32_X_LSB(l, cp)                         \
485   (l) ^= ((SilcUInt32)(SilcUInt8)(cp)[0])               \
486     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8)             \
487     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 16)            \
488     | ((SilcUInt32)(SilcUInt8)(cp)[3] << 24)
489 #endif /* SILC_I386 || SILC_X86_64 */
490
491 /****d* silcutil/SILCTypes/SILC_PUT16_MSB
492  *
493  * NAME
494  *
495  *    #define SILC_PUT16_MSB(dest, src)
496  *
497  * DESCRIPTION
498  *
499  *    Put two 8-bit bytes, most significant bytes first.
500  *
501  * SOURCE
502  */
503 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
504 #define SILC_PUT16_MSB(l, cp)                           \
505 asm volatile ("rolw $8, %w1; movw %w1, (%0)"            \
506               : : "q" (cp), "q" (l) : "memory", "cc");
507 #else
508 #define SILC_PUT16_MSB(l, cp)                   \
509 do {                                            \
510   (cp)[0] = (SilcUInt8)((l) >> 8);              \
511   (cp)[1] = (SilcUInt8)(l);                     \
512 } while(0)
513 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
514 /***/
515
516 /****d* silcutil/SILCTypes/SILC_PUT32_MSB
517  *
518  * NAME
519  *
520  *    #define SILC_PUT32_MSB(dest, src)
521  *
522  * DESCRIPTION
523  *
524  *    Put four 8-bit bytes, most significant bytes first.
525  *
526  * SOURCE
527  */
528 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
529 #define SILC_PUT32_MSB(l, cp)                           \
530 asm volatile ("bswapl %1; movl %1, (%0); bswapl %1"     \
531               : : "q" (cp), "q" (l) : "memory", "cc");
532 #else
533 #define SILC_PUT32_MSB(l, cp)                   \
534 do {                                            \
535   (cp)[0] = (SilcUInt8)((l) >> 24);             \
536   (cp)[1] = (SilcUInt8)((l) >> 16);             \
537   (cp)[2] = (SilcUInt8)((l) >> 8);              \
538   (cp)[3] = (SilcUInt8)(l);                     \
539 } while(0)
540 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
541 /***/
542
543 /****d* silcutil/SILCTypes/SILC_PUT64_MSB
544  *
545  * NAME
546  *
547  *    #define SILC_PUT64_MSB(dest, src)
548  *
549  * DESCRIPTION
550  *
551  *    Put eight 8-bit bytes, most significant bytes first.
552  *
553  * SOURCE
554  */
555 #if defined(SILC_X86_64) && defined(__GNUC__)
556 #define SILC_PUT64_MSB(l, cp)                           \
557 asm volatile ("bswapq %1; movq %1, (%0); bswapq %1"     \
558               : : "r" (cp), "r" (l) : "memory", "cc");
559 #else
560 #define SILC_PUT64_MSB(l, cp)                                   \
561 do {                                                            \
562   SILC_PUT32_MSB((SilcUInt32)((SilcUInt64)(l) >> 32), (cp));    \
563   SILC_PUT32_MSB((SilcUInt32)(l), (cp) + 4);                    \
564 } while(0)
565 #endif /* SILC_X86_64 && __GNUC__ */
566 /***/
567
568 /****d* silcutil/SILCTypes/SILC_PUT16_LSB
569  *
570  * NAME
571  *
572  *    #define SILC_PUT16_LSB(dest, src)
573  *
574  * DESCRIPTION
575  *
576  *    Put two 8-bit bytes, least significant bytes first.
577  *
578  * SOURCE
579  */
580 #if defined(SILC_I386) || defined(SILC_X86_64)
581 #define SILC_PUT16_LSB(l, cp) (*(SilcUInt16 *)(cp)) = (l)
582 #else
583 #define SILC_PUT16_LSB(l, cp)                   \
584 do  {                                           \
585   (cp)[0] = (SilcUInt8)(l);                     \
586   (cp)[1] = (SilcUInt8)((l) >> 8);              \
587 } while(0)
588 #endif /* SILC_I386 || SILC_X86_64 */
589 /***/
590
591 /****d* silcutil/SILCTypes/SILC_PUT32_LSB
592  *
593  * NAME
594  *
595  *    #define SILC_PUT32_LSB(dest, src)
596  *
597  * DESCRIPTION
598  *
599  *    Put four 8-bit bytes, least significant bytes first.
600  *
601  * SOURCE
602  */
603 #if defined(SILC_I386) || defined(SILC_X86_64)
604 #define SILC_PUT32_LSB(l, cp) (*(SilcUInt32 *)(cp)) = (l)
605 #else
606 #define SILC_PUT32_LSB(l, cp)                   \
607 do {                                            \
608   (cp)[0] = (SilcUInt8)(l);                     \
609   (cp)[1] = (SilcUInt8)((l) >> 8);              \
610   (cp)[2] = (SilcUInt8)((l) >> 16);             \
611   (cp)[3] = (SilcUInt8)((l) >> 24);             \
612 } while(0)
613 #endif /* SILC_I386 || SILC_X86_64 */
614 /***/
615
616 /****d* silcutil/SILCTypes/SILC_SWAB_16
617  *
618  * NAME
619  *
620  *    #define SILC_SWAB_16(integer)
621  *
622  * DESCRIPTION
623  *
624  *    Swabs 16-bit unsigned integer byte order.  Returns the new value.
625  *
626  * SOURCE
627  */
628 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
629 #define SILC_SWAB_16(l)                         \
630 ({                                              \
631   SilcUInt16 _result_;                          \
632   asm volatile ("movw %w1, %w0; rolw $8, %w0"   \
633                 : "=q" (_result_) : "q" (l));   \
634   _result_;                                     \
635 })
636 #else
637 #define SILC_SWAB_16(l)                                         \
638   ((SilcUInt16)(((SilcUInt16)(l) & (SilcUInt16)0x00FFU) << 8) | \
639                (((SilcUInt16)(l) & (SilcUInt16)0xFF00U) >> 8))
640 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
641 /***/
642
643 /****d* silcutil/SILCTypes/SILC_SWAB_32
644  *
645  * NAME
646  *
647  *    #define SILC_SWAB_32(integer)
648  *
649  * DESCRIPTION
650  *
651  *    Swabs 32-bit unsigned integer byte order.  Returns the new value.
652  *
653  * SOURCE
654  */
655 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
656 #define SILC_SWAB_32(l)                         \
657 ({                                              \
658   SilcUInt32 _result_;                          \
659   asm volatile ("movl %1, %0; bswapl %0"        \
660                 : "=q" (_result_) : "q" (l));   \
661   _result_;                                     \
662 })
663 #else
664 #define SILC_SWAB_32(l)                                                 \
665   ((SilcUInt32)(((SilcUInt32)(l) & (SilcUInt32)0x000000FFUL) << 24) |   \
666                (((SilcUInt32)(l) & (SilcUInt32)0x0000FF00UL) << 8)  |   \
667                (((SilcUInt32)(l) & (SilcUInt32)0x00FF0000UL) >> 8)  |   \
668                (((SilcUInt32)(l) & (SilcUInt32)0xFF000000UL) >> 24))
669 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
670 /***/
671
672 /****d* silcutil/SILCTypes/SILC_PTR_TO_32
673  *
674  * NAME
675  *
676  *    #define SILC_PTR_TO_32(ptr)
677  *
678  * DESCRIPTION
679  *
680  *    Type casts a pointer's value into a 32-bit integer.  Use this to
681  *    avoid compiler warnings when type casting pointers to integers
682  *    of different size.
683  *
684  * SOURCE
685  */
686 #if SILC_SIZEOF_VOID_P < 8
687 #define SILC_PTR_TO_32(_ptr__) ((SilcUInt32)(_ptr__))
688 #else
689 #define SILC_PTR_TO_32(_ptr__)                                          \
690   ((SilcUInt32)((SilcUInt64)(_ptr__) & (SilcUInt32)0xFFFFFFFFUL))
691 #endif
692 /***/
693
694 /****d* silcutil/SILCTypes/SILC_PTR_TO_64
695  *
696  * NAME
697  *
698  *    #define SILC_PTR_TO_64(ptr)
699  *
700  * DESCRIPTION
701  *
702  *    Type casts a pointer's value into a 64-bit integer.  Use this to
703  *    avoid compiler warnings when type casting pointers to integers
704  *    of different size.
705  *
706  * SOURCE
707  */
708 #if SILC_SIZEOF_VOID_P < 8
709 #define SILC_PTR_TO_64(_ptr__) ((SilcUInt64)((SilcUInt32)(_ptr__)))
710 #else
711 #define SILC_PTR_TO_64(_ptr__) ((SilcUInt64)((SilcUInt64)(_ptr__)))
712 #endif
713 /***/
714
715 /****d* silcutil/SILCTypes/SILC_32_TO_PTR
716  *
717  * NAME
718  *
719  *    #define SILC_32_TO_PTR(ptr)
720  *
721  * DESCRIPTION
722  *
723  *    Type casts a 32-bit integer value into a pointer.  Use this to
724  *    avoid compiler warnings when type casting integers to pointers of
725  *    different size.
726  *
727  * SOURCE
728  */
729 #if SILC_SIZEOF_VOID_P < 8
730 #define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt32)(_ival__)))
731 #else
732 #define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
733 #endif
734 /***/
735
736 /****d* silcutil/SILCTypes/SILC_64_TO_PTR
737  *
738  * NAME
739  *
740  *    #define SILC_64_TO_PTR(ptr)
741  *
742  * DESCRIPTION
743  *
744  *    Type casts a 64-bit integer value into a pointer.  Use this to
745  *    avoid compiler warnings when type casting integers to pointers of
746  *    different size.
747  *
748  * SOURCE
749  */
750 #if SILC_SIZEOF_VOID_P < 8
751 #define SILC_64_TO_PTR(_ival__)                                         \
752   ((void *)((SilcUInt32)((SilcUInt64)(_ival__) & (SilcUInt32)0xFFFFFFFFUL)))
753 #else
754 #define SILC_64_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
755 #endif
756 /***/
757
758 /****d* silcutil/SILCTypes/silc_rol
759  *
760  * NAME
761  *
762  *    static inline SilcUInt32 silc_rol(SilcUInt32 val, int num);
763  *
764  * DESCRIPTION
765  *
766  *    Rotate 32-bit integer's bits to left `num' times.  Bits pushed to the
767  *    left will appear from the right side of the integer, thus rotating.
768  *    Returns the rotated value.
769  *
770  ***/
771 static inline SilcUInt32 silc_rol(SilcUInt32 val, int num)
772 {
773 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
774   asm volatile ("roll %%cl, %0"
775                 : "=q" (val) : "0" (val), "c" (num));
776   return val;
777 #else
778   return ((val << (SilcUInt32)num) | (val >> (32 - (SilcUInt32)num)));
779 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
780 }
781
782 /****d* silcutil/SILCTypes/silc_ror
783  *
784  * NAME
785  *
786  *    static inline SilcUInt32 silc_ror(SilcUInt32 val, int num);
787  *
788  * DESCRIPTION
789  *
790  *    Rotate 32-bit integer's bits to right `num' times.  Bits pushed to the
791  *    right will appear from the left side of the integer, thus rotating.
792  *    Returns the rotated value.
793  *
794  ***/
795 static inline SilcUInt32 silc_ror(SilcUInt32 val, int num)
796 {
797 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
798   asm volatile ("rorl %%cl, %0"
799                 : "=q" (val) : "0" (val), "c" (num));
800   return val;
801 #else
802   return ((val >> (SilcUInt32)num) | (val << (32 - (SilcUInt32)num)));
803 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
804 }
805
806 /****d* silcutil/SILCTypes/silc_rol64
807  *
808  * NAME
809  *
810  *    static inline SilcUInt64 silc_rol64(SilcUInt64 val, int num);
811  *
812  * DESCRIPTION
813  *
814  *    Rotate 64-bit integer's bits to left `num' times.  Bits pushed to the
815  *    left will appear from the right side of the integer, thus rotating.
816  *    Returns the rotated value.
817  *
818  ***/
819 static inline SilcUInt64 silc_rol64(SilcUInt64 val, int num)
820 {
821 #if defined(SILC_X86_64) && defined(__GNUC__)
822   asm volatile ("rolq %%cl, %0"
823                 : "=q" (val) : "0" (val), "c" (num));
824   return val;
825 #else
826   return ((val << (SilcUInt64)num) | (val >> (64 - (SilcUInt64)num)));
827 #endif /* SILC_X86_64 && __GNUC__ */
828 }
829
830 /****d* silcutil/SILCTypes/silc_ror64
831  *
832  * NAME
833  *
834  *    static inline SilcUInt64 silc_ror64(SilcUInt64 val, int num);
835  *
836  * DESCRIPTION
837  *
838  *    Rotate 64-bit integer's bits to right `num' times.  Bits pushed to the
839  *    right will appear from the left side of the integer, thus rotating.
840  *    Returns the rotated value.
841  *
842  ***/
843 static inline SilcUInt64 silc_ror64(SilcUInt64 val, int num)
844 {
845 #if defined(SILC_X86_64) && defined(__GNUC__)
846   asm volatile ("rorq %%cl, %0"
847                 : "=q" (val) : "0" (val), "c" (num));
848   return val;
849 #else
850   return ((val >> (SilcUInt64)num) | (val << (64 - (SilcUInt64)num)));
851 #endif /* SILC_X86_64 && __GNUC__ */
852 }
853
854 /****d* silcutil/SILCTypes/silc_offsetof
855  *
856  * NAME
857  *
858  *    #define silc_offsetof(TYPE, MEMBER)
859  *
860  * DESCRIPTION
861  *
862  *    offsetof() macro replacement.  Use this instead of offsetof().
863  *
864  ***/
865 #define silc_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
866
867 /****d* silcutil/SILCTypes/silc_attribute
868  *
869  * NAME
870  *
871  *    #define silc_attribute(attrlist)
872  *
873  * DESCRIPTION
874  *
875  *    Compiler attributes.  If compiler doesn't support attributes this macro
876  *    doesn't do anything.  Currently this works only with GCC compiler.
877  *    See GCC documentation for specified attributes.
878  *
879  * EXAMPLE
880  *
881  *    int printf(const char *fmt, ...) silc_attribute((format(printf, 1, 2)));
882  *
883  ***/
884 #if defined(__GNUC__)
885 #define silc_attribute(attrlist) __attribute__(attrlist)
886 #else
887 #define silc_attribute(attrlist)
888 #endif /* __GNUC__ */
889
890 /****d* silcutil/SILCTypes/silc_likely
891  *
892  * NAME
893  *
894  *    #define silc_likely(expression)
895  *
896  * DESCRIPTION
897  *
898  *    Branch prediction macro.  It specifies that it is likely that the branch
899  *    where silc_likely is applied is taken.  Compiler will optimize the
900  *    code based on this prediction.  Never use this before you have profiled
901  *    the code first.
902  *
903  ***/
904
905 /****d* silcutil/SILCTypes/silc_unlikely
906  *
907  * NAME
908  *
909  *    #define silc_unlikely(expression)
910  *
911  * DESCRIPTION
912  *
913  *    Branch prediction macro.  It specifies that it is unlikely that the
914  *    branch where silc_unlikely is applied is taken.  Compiler will optimize
915  *    the code based on this prediction.  Never use this before you have
916  *    profiled the code first.
917  *
918  ***/
919 #if __GNUC__ >= 3
920 #define silc_likely(expr) __builtin_expect(!!(expr), 1)
921 #define silc_unlikely(expr) __builtin_expect(!!(expr), 0)
922 #else
923 #define silc_likely(expr) (expr)
924 #define silc_unlikely(expr) (expr)
925 #endif /* __GNUC__ >= 3 */
926
927 /* Prefetch operations.  Use these to prefetch data to CPU cache before
928    reading or writing if you think that the data will be needed soon after
929    prefetching. */
930
931 /****d* silcutil/SILCTypes/silc_prefetch
932  *
933  * NAME
934  *
935  *    static inline void silc_prefetch(void *addr, int rw, int locality);
936  *
937  * DESCRIPTION
938  *
939  *    Simple prefetch.  Loads memory from specified address to CPU cache.
940  *    The amount of data loaded is CPU dependant (cache line length).  The
941  *    `rw' argument defines the reason for prefetch: 0=read, 1=write.  The
942  *    `locality' argument defines the locality of the prefetch, 0=non-temporal
943  *    (non-temporal cache, cache closest to CPU, data will not stay long in
944  *    the cache), 1=temporal (L2+ cache), 2=temporal (L2, L3+ cache),
945  *    3=temporal (fetch to all caches, data stays longer time in cache).
946  *
947  * NOTES
948  *
949  *    This produces only a hint for CPU.  CPU doesn't have to actually
950  *    prefetch the data.  Use silc_prefetch_block to ensure CPU always
951  *    prefetches.
952  *
953  ***/
954
955 static inline silc_attribute((always_inline))
956 void silc_prefetch(void *addr, int rw, int locality)
957 {
958 #if __GNUC__ > 3
959   __builtin_prefetch(addr, rw, locality);
960 #endif /* __GNUC__ */
961 }
962
963 /****d* silcutil/SILCTypes/silc_prefetch_block
964  *
965  * NAME
966  *
967  *    static inline void silc_prefetch_block(void *addr,
968  *                                           int prefetch_length,
969  *                                           const int cache_line_length)
970  *
971  * DESCRIPTION
972  *
973  *    Enforced block prefetch.  This function loads the specified amount
974  *    `prefetch_length' of memory from the specified address `addr' to CPU
975  *    cache with each loaded cache line being the size of `cache_line_length'.
976  *    If you don't know the cache line size use 64 bytes.  Note that, the
977  *    `cache_line_length' is a const int.  In this context this mean its
978  *    value must not come from a variable but must be a constant (the code
979  *    won't compile if it comes from a variable).
980  *
981  *    The `prefetch_length' must be multiple of twice of the
982  *    `cache_line_length' or 128 if you don't know the cache line size, hence
983  *    the minimum length for `prefetch_length' is 128 bytes when the
984  *    `cache_line_length' is 64 bytes.  Shorter cache line length (32 bytes)
985  *    can be used too.
986  *
987  *    You should use the correct `cache_line_length' value for your CPU or
988  *    the value of the CPU for which you want to optimize your code.  Intel
989  *    CPUs usually have cache size of 32 or 64 bytes.  The most optimal
990  *    prefetch is achieved if the `cache_line_length' is the actual CPU cache
991  *    line size.  Always do performance testing with and without prefetching
992  *    to make sure the prefetch actually helps.  If used improperly, it may
993  *    slow down your program.
994  *
995  *    The difference to silc_prefetch is that this function always performs
996  *    the prefetch and has the ability to prefetch more than one cache line
997  *    worth of memory, whereas silc_prefetch can prefetch only one cache line
998  *    and may not do the prefetch at all.
999  *
1000  ***/
1001
1002 static inline silc_attribute((always_inline))
1003 void silc_prefetch_block(void *addr,
1004                          int prefetch_length,
1005                          const int cache_line_length)
1006 {
1007 #if 0
1008   SILC_ASSERT(cache_line_length >= 32);
1009   SILC_ASSERT(cache_line_length % 32 == 0);
1010   SILC_ASSERT(prefetch_length >= cache_line_length);
1011   SILC_ASSERT(prefetch_length % (cache_line_length * 2) == 0);
1012 #endif
1013
1014 #if SILC_SIZEOF_VOID_P < 8
1015 #define SILC_PREFETCH_UINT SilcUInt32
1016 #else
1017 #define SILC_PREFETCH_UINT SilcUInt64
1018 #endif /* SILC_SIZEOF_VOID_P < 8 */
1019
1020 #if defined(__GNUC__) && (defined(SILC_I386) || defined(SILC_X86_64))
1021
1022   /* Assembler implementation.
1023
1024      The idea here is to simply enforce the CPU to load the requested amount
1025      of bytes to cache.  We simply mov data from the memory to a register.
1026      Each mov will load a full cache line worth of data from the memory.
1027
1028      We expect the `cache_line_length' to be the actual cache line size.
1029      It doesn't matter if it is.  If it is smaller the prefetch is a bit
1030      slower as there is redundancy.  If it is larger we skip some of the
1031      data and don't prefetch everything.
1032
1033      The loop is unrolled to handle two mov's at once, this why we expect
1034      the `prefetch_length' to be multiple of twice the length of
1035      `cache_line_length`.  We also mov the data from end to beginning instead
1036      of from the beginning to assure CPU doesn't prefetch the data before
1037      we actually want to do it.
1038
1039      This technique is described by AMD in:
1040      http://cdrom.amd.com/devconn/events/AMD_block_prefetch_paper.pdf */
1041
1042   {
1043     SILC_PREFETCH_UINT temp;
1044
1045 #define SILC_PREFETCH_ASM(ip, rp)                                       \
1046     asm volatile ("1:                                   \n\t"           \
1047                   "mov" ip " -%c4(%2, %" rp "3), %0     \n\t"           \
1048                   "mov" ip " -%c5(%2, %" rp "3), %0     \n\t"           \
1049                   "sub" ip " %5, %" rp "3               \n\t"           \
1050                   "jnz 1b                               "               \
1051                   : "=&r" (temp), "=r" (prefetch_length)                \
1052                   : "r" (addr), "1" (prefetch_length),                  \
1053                     "Z" (cache_line_length),                            \
1054                     "Z" (cache_line_length * 2)                         \
1055                   : "memory", "cc");
1056
1057 #if defined(SILC_I386)
1058     /* 32-bit prefetch */
1059     SILC_PREFETCH_ASM("l", "");
1060 #else
1061     /* 64-bit prefetch */
1062     SILC_PREFETCH_ASM("q", "q");
1063 #endif /* SILC_I386 */
1064   }
1065
1066 #else
1067   /* C implementation.  Yes, you can do it in C too.  In fact, we'll try to
1068      make the compiler generate nearly identical code to the above assembler
1069      code.  Note that, the memory access must be volatile, otherwise the
1070      compiler will optimize them away because the temp variable isn't actually
1071      used for anything.  This should be as fast as the assembler code above,
1072      unless the compiler decides to start meddling with it (don't use
1073      -funroll-loops with this code). */
1074
1075   {
1076     register unsigned char *a = addr;
1077     register int len = prefetch_length;
1078     register SILC_PREFETCH_UINT temp;
1079
1080     do {
1081       temp = *(SILC_PREFETCH_UINT volatile *)
1082         (a + (len - cache_line_length));
1083       temp = *(SILC_PREFETCH_UINT volatile *)
1084         (a + (len - (cache_line_length * 2)));
1085       len -= (cache_line_length * 2);
1086     } while (len != 0);
1087   }
1088 #endif /* __GNUC__ */
1089 #undef SILC_PREFETCH_UINT
1090 #undef SILC_PREFETCH_ASM
1091 }
1092
1093 #endif /* SILCTYPES_H */