Documentation updates
[runtime.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/Types and Definitions
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 /****d* silcutil/SilcBool
48  *
49  * NAME
50  *
51  *    typedef unigned char SilcBool;
52  *
53  * DESCRIPTION
54  *
55  *    Boolean value, and is always 8-bits.  Represents value 0 or 1.
56  *
57  ***/
58 typedef unsigned char SilcBool;
59
60 /****d* silcutil/TRUE
61  *
62  * NAME
63  *
64  *    #define TRUE ...
65  *
66  * DESCRIPTION
67  *
68  *    Boolean true value indicator.
69  *
70  * SOURCE
71  */
72 #ifndef TRUE
73 #define TRUE 1
74 #endif
75 /***/
76
77 /****d* silcutil/FALSE
78  *
79  * NAME
80  *
81  *    #define FALSE ...
82  *
83  * DESCRIPTION
84  *
85  *    Boolean false value indicator.
86  *
87  * SOURCE
88  */
89 #ifndef FALSE
90 #define FALSE 0
91 #endif
92 /***/
93
94 /****d* silcutil/SilcUInt8
95  *
96  * NAME
97  *
98  *    typedef unsigned char SilcUInt8;
99  *
100  * DESCRIPTION
101  *
102  *    8-bit unsigned integer.
103  *
104  * SOURCE
105  */
106 typedef unsigned char SilcUInt8;
107 /***/
108
109 /****d* silcutil/SilcInt8
110  *
111  * NAME
112  *
113  *    typedef signed char SilcInt8;
114  *
115  * DESCRIPTION
116  *
117  *    8-bit signed integer.
118  *
119  * SOURCE
120  */
121 typedef signed char SilcInt8;
122 /***/
123
124 /****d* silcutil/SilcUInt16
125  *
126  * NAME
127  *
128  *    typedef unsigned short SilcUInt16;
129  *
130  * DESCRIPTION
131  *
132  *    16-bit unsigned integer.  Guaranteed to be 16-bits.
133  *
134  * SOURCE
135  */
136 typedef unsigned short SilcUInt16;
137 /***/
138
139 /****d* silcutil/SilcInt16
140  *
141  * NAME
142  *
143  *    typedef signed short SilcInt16;
144  *
145  * DESCRIPTION
146  *
147  *    16-bit signed integer.  Guaranteed to be 16-bits.
148  *
149  * SOURCE
150  */
151 typedef signed short SilcInt16;
152 /***/
153
154 /****d* silcutil/SilcUInt32
155  *
156  * NAME
157  *
158  *    typedef unsigned long SilcUInt32;
159  *
160  * DESCRIPTION
161  *
162  *    32-bit unsigned integer.  Guaranteed to be 32-bits.
163  *
164  * SOURCE
165  */
166 #if SILC_SIZEOF_LONG == 4
167 typedef unsigned long SilcUInt32;
168 typedef signed long SilcInt32;
169 #else
170 #if SILC_SIZEOF_INT == 4
171 typedef unsigned int SilcUInt32;
172 typedef signed int SilcInt32;
173 #else
174 #if SILC_SIZEOF_LONG_LONG >= 4
175 #ifndef WIN32
176 typedef unsigned long long SilcUInt32;
177 typedef signed long long SilcInt32;
178 #endif
179 #endif
180 #endif
181 #endif
182 /***/
183
184 /****d* silcutil/SilcInt32
185  *
186  * NAME
187  *
188  *    typedef signed long SilcInt32;
189  *
190  * DESCRIPTION
191  *
192  *    32-bit signed integer.  Guaranteed to be 32-bits.
193  *
194  ***/
195
196 /****d* silcutil/SilcUInt64
197  *
198  * NAME
199  *
200  *    typedef unsigned long long SilcUInt64;
201  *
202  * DESCRIPTION
203  *
204  *    64-bit unsigned integer.  Guaranteed to be 64-bits on systems that
205  *    support it.
206  *
207  * SOURCE
208  */
209 #if SILC_SIZEOF_LONG >= 8
210 typedef unsigned long SilcUInt64;
211 typedef signed long SilcInt64;
212 #else
213 #if SILC_SIZEOF_LONG_LONG >= 8
214 #ifndef WIN32
215 typedef unsigned long long SilcUInt64;
216 typedef signed long long SilcInt64;
217 #else
218 typedef unsigned __int64 SilcUInt64;
219 typedef signed __int64 SilcInt64;
220 #endif
221 #else
222 typedef SilcUInt32 SilcUInt64;
223 typedef SilcInt32 SilcInt64;
224 #endif
225 #endif
226 /***/
227
228 /****d* silcutil/SilcInt64
229  *
230  * NAME
231  *
232  *    typedef signed long long SilcInt64;
233  *
234  * DESCRIPTION
235  *
236  *    64-bit signed integer.  Guaranteed to be 64-bits on systems that
237  *    support it.
238  *
239  ***/
240
241 /****d* silcutil/SilcFloat32
242  *
243  * NAME
244  *
245  *    typedef float SilcFloat32;
246  *
247  * DESCRIPTION
248  *
249  *    32-bit floating point number.
250  *
251  ***/
252 typedef float SilcFloat32;
253
254 /****d* silcutil/SilcFloat64
255  *
256  * NAME
257  *
258  *    typedef double SilcFloat64;
259  *
260  * DESCRIPTION
261  *
262  *    64-bit floating point number.
263  *
264  ***/
265 typedef double SilcFloat64;
266
267 #if SILC_SIZEOF_VOID_P < 4
268 typedef SilcUInt32 * void *;
269 #endif
270
271 /****d* silcutil/SilcSocket
272  *
273  * NAME
274  *
275  *    SilcSocket
276  *
277  * DESCRIPTION
278  *
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.
283  *
284  * SOURCE
285  */
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;
292 #endif
293 /***/
294
295 /****d* silcutil/SilcParam
296  *
297  * NAME
298  *
299  *    typedef SilcUInt32 SilcParam;
300  *
301  * DESCRIPTION
302  *
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,
305  *    etc.
306  *
307  * SOURCE
308  */
309 typedef SilcUInt32 SilcParam;
310
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 */
324 /***/
325
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 */
343
344 /* Macros */
345
346 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
347 #define SILC_GET_WORD(cp)                                               \
348 ({                                                                      \
349   SilcUInt32 _result_;                                                  \
350   asm volatile ("movl (%1), %0; bswapl %0"                              \
351                 : "=q" (_result_) : "q" (cp));                          \
352   _result_;                                                             \
353 })
354 #else
355 #define SILC_GET_WORD(cp) ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24        \
356                     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
357                     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
358                     | ((SilcUInt32)(SilcUInt8)(cp)[3])
359 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
360
361 /****d* silcutil/SILC_GET16_MSB
362  *
363  * NAME
364  *
365  *    #define SILC_GET16_MSB(dest, src)
366  *
367  * DESCRIPTION
368  *
369  *    Return two 8-bit bytes, most significant bytes first.
370  *
371  * SOURCE
372  */
373 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
374 #define SILC_GET16_MSB(l, cp)                           \
375 asm volatile ("movw (%1), %w0; rolw $8, %w0"            \
376               : "=q" (l) : "q" (cp) : "memory", "cc");
377 #else
378 #define SILC_GET16_MSB(l, cp)                           \
379 do {                                                    \
380   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0] << 8)           \
381     | ((SilcUInt32)(SilcUInt8)(cp)[1]);                 \
382 } while(0)
383 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
384 /***/
385
386 /****d* silcutil/SILC_GET32_MSB
387  *
388  * NAME
389  *
390  *    #define SILC_GET32_MSB(dest, src)
391  *
392  * DESCRIPTION
393  *
394  *    Return four 8-bit bytes, most significant bytes first.
395  *
396  * SOURCE
397  */
398 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
399 #define SILC_GET32_MSB(l, cp)                           \
400 asm volatile ("movl (%1), %0; bswapl %0"                \
401               : "=q" (l) : "q" (cp) : "memory", "cc");
402 #else
403 #define SILC_GET32_MSB(l, cp)                           \
404 do {                                                    \
405   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24          \
406     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
407     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
408     | ((SilcUInt32)(SilcUInt8)(cp)[3]);                 \
409 } while(0)
410 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
411 /***/
412
413 /* Same as upper but XOR the result always. Special purpose macro. */
414 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
415 #define SILC_GET32_X_MSB(l, cp)                                         \
416 do {                                                                    \
417   register volatile SilcUInt32 _x_;                                     \
418   asm volatile ("movl %1, %3; movl (%2), %0;\n\t"                       \
419                 "bswapl %0; xorl %3, %0"                                \
420                 : "=r" (l) : "0" (l), "r" (cp), "r" (_x_)               \
421                 : "memory", "cc");                                      \
422 } while(0)
423 #else
424 #define SILC_GET32_X_MSB(l, cp)                         \
425   (l) ^= ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24         \
426     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
427     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
428     | ((SilcUInt32)(SilcUInt8)(cp)[3]);
429 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
430
431 /****d* silcutil/SILC_GET64_MSB
432  *
433  * NAME
434  *
435  *    #define SILC_GET64_MSB(dest, src)
436  *
437  * DESCRIPTION
438  *
439  *    Return eight 8-bit bytes, most significant bytes first.
440  *
441  * SOURCE
442  */
443 #if defined(SILC_X86_64) && defined(__GNUC__)
444 #define SILC_GET64_MSB(l, cp)                                   \
445 asm volatile ("movq (%1), %0; bswapq %0"                        \
446               : "=r" (l) : "r" (cp) : "memory", "cc");
447 #else
448 #define SILC_GET64_MSB(l, cp)                                   \
449 do {                                                            \
450   (l) = ((((SilcUInt64)SILC_GET_WORD((cp))) << 32) |            \
451          ((SilcUInt64)SILC_GET_WORD((cp) + 4)));                \
452 } while(0)
453 #endif /* SILC_X86_64 && __GNUC__ */
454 /***/
455
456 /****d* silcutil/SILC_GET16_LSB
457  *
458  * NAME
459  *
460  *    #define SILC_GET16_MSB(dest, src)
461  *
462  * DESCRIPTION
463  *
464  *    Return two 8-bit bytes, least significant bytes first.
465  *
466  * SOURCE
467  */
468 #if defined(SILC_I386) || defined(SILC_X86_64)
469 #define SILC_GET16_LSB(l, cp) (l) = (*(SilcUInt16 *)(cp))
470 #else
471 #define SILC_GET16_LSB(l, cp)                           \
472 do {                                                    \
473   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0])                \
474     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8);            \
475 } while(0)
476 #endif /* SILC_I386 || SILC_X86_64 */
477 /***/
478
479 /****d* silcutil/SILC_GET32_LSB
480  *
481  * NAME
482  *
483  *    #define SILC_GET32_LSB(dest, src)
484  *
485  * DESCRIPTION
486  *
487  *    Return four 8-bit bytes, least significant bytes first.
488  *
489  * SOURCE
490  */
491 #if defined(SILC_I386) || defined(SILC_X86_64)
492 #define SILC_GET32_LSB(l, cp) (l) = (*(SilcUInt32 *)(cp))
493 #else
494 #define SILC_GET32_LSB(l, cp)                           \
495 do {                                                    \
496   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0])                \
497     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8)             \
498     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 16)            \
499     | ((SilcUInt32)(SilcUInt8)(cp)[3] << 24);           \
500 } while(0)
501 #endif /* SILC_I386 || SILC_X86_64 */
502 /***/
503
504 /* Same as upper but XOR the result always. Special purpose macro. */
505 #if defined(SILC_I386) || defined(SILC_X86_64)
506 #define SILC_GET32_X_LSB(l, cp) (l) ^= (*(SilcUInt32 *)(cp))
507 #else
508 #define SILC_GET32_X_LSB(l, cp)                         \
509   (l) ^= ((SilcUInt32)(SilcUInt8)(cp)[0])               \
510     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8)             \
511     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 16)            \
512     | ((SilcUInt32)(SilcUInt8)(cp)[3] << 24)
513 #endif /* SILC_I386 || SILC_X86_64 */
514
515 /****d* silcutil/SILC_PUT16_MSB
516  *
517  * NAME
518  *
519  *    #define SILC_PUT16_MSB(dest, src)
520  *
521  * DESCRIPTION
522  *
523  *    Put two 8-bit bytes, most significant bytes first.
524  *
525  * SOURCE
526  */
527 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
528 #define SILC_PUT16_MSB(l, cp)                           \
529 asm volatile ("rolw $8, %w1; movw %w1, (%0)"            \
530               : : "q" (cp), "q" (l) : "memory", "cc");
531 #else
532 #define SILC_PUT16_MSB(l, cp)                   \
533 do {                                            \
534   (cp)[0] = (SilcUInt8)((l) >> 8);              \
535   (cp)[1] = (SilcUInt8)(l);                     \
536 } while(0)
537 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
538 /***/
539
540 /****d* silcutil/SILC_PUT32_MSB
541  *
542  * NAME
543  *
544  *    #define SILC_PUT32_MSB(dest, src)
545  *
546  * DESCRIPTION
547  *
548  *    Put four 8-bit bytes, most significant bytes first.
549  *
550  * SOURCE
551  */
552 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
553 #define SILC_PUT32_MSB(l, cp)                           \
554 asm volatile ("bswapl %1; movl %1, (%0); bswapl %1"     \
555               : : "q" (cp), "q" (l) : "memory", "cc");
556 #else
557 #define SILC_PUT32_MSB(l, cp)                   \
558 do {                                            \
559   (cp)[0] = (SilcUInt8)((l) >> 24);             \
560   (cp)[1] = (SilcUInt8)((l) >> 16);             \
561   (cp)[2] = (SilcUInt8)((l) >> 8);              \
562   (cp)[3] = (SilcUInt8)(l);                     \
563 } while(0)
564 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
565 /***/
566
567 /****d* silcutil/SILC_PUT64_MSB
568  *
569  * NAME
570  *
571  *    #define SILC_PUT64_MSB(dest, src)
572  *
573  * DESCRIPTION
574  *
575  *    Put eight 8-bit bytes, most significant bytes first.
576  *
577  * SOURCE
578  */
579 #if defined(SILC_X86_64) && defined(__GNUC__)
580 #define SILC_PUT64_MSB(l, cp)                           \
581 asm volatile ("bswapq %1; movq %1, (%0); bswapq %1"     \
582               : : "r" (cp), "r" (l) : "memory", "cc");
583 #else
584 #define SILC_PUT64_MSB(l, cp)                                   \
585 do {                                                            \
586   SILC_PUT32_MSB((SilcUInt32)((SilcUInt64)(l) >> 32), (cp));    \
587   SILC_PUT32_MSB((SilcUInt32)(l), (cp) + 4);                    \
588 } while(0)
589 #endif /* SILC_X86_64 && __GNUC__ */
590 /***/
591
592 /****d* silcutil/SILC_PUT16_LSB
593  *
594  * NAME
595  *
596  *    #define SILC_PUT16_LSB(dest, src)
597  *
598  * DESCRIPTION
599  *
600  *    Put two 8-bit bytes, least significant bytes first.
601  *
602  * SOURCE
603  */
604 #if defined(SILC_I386) || defined(SILC_X86_64)
605 #define SILC_PUT16_LSB(l, cp) (*(SilcUInt16 *)(cp)) = (l)
606 #else
607 #define SILC_PUT16_LSB(l, cp)                   \
608 do  {                                           \
609   (cp)[0] = (SilcUInt8)(l);                     \
610   (cp)[1] = (SilcUInt8)((l) >> 8);              \
611 } while(0)
612 #endif /* SILC_I386 || SILC_X86_64 */
613 /***/
614
615 /****d* silcutil/SILC_PUT32_LSB
616  *
617  * NAME
618  *
619  *    #define SILC_PUT32_LSB(dest, src)
620  *
621  * DESCRIPTION
622  *
623  *    Put four 8-bit bytes, least significant bytes first.
624  *
625  * SOURCE
626  */
627 #if defined(SILC_I386) || defined(SILC_X86_64)
628 #define SILC_PUT32_LSB(l, cp) (*(SilcUInt32 *)(cp)) = (l)
629 #else
630 #define SILC_PUT32_LSB(l, cp)                   \
631 do {                                            \
632   (cp)[0] = (SilcUInt8)(l);                     \
633   (cp)[1] = (SilcUInt8)((l) >> 8);              \
634   (cp)[2] = (SilcUInt8)((l) >> 16);             \
635   (cp)[3] = (SilcUInt8)((l) >> 24);             \
636 } while(0)
637 #endif /* SILC_I386 || SILC_X86_64 */
638 /***/
639
640 /****d* silcutil/SILC_SWAB_16
641  *
642  * NAME
643  *
644  *    #define SILC_SWAB_16(integer)
645  *
646  * DESCRIPTION
647  *
648  *    Swabs 16-bit unsigned integer byte order.  Returns the new value.
649  *
650  * SOURCE
651  */
652 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
653 #define SILC_SWAB_16(l)                         \
654 ({                                              \
655   SilcUInt16 _result_;                          \
656   asm volatile ("movw %w1, %w0; rolw $8, %w0"   \
657                 : "=q" (_result_) : "q" (l));   \
658   _result_;                                     \
659 })
660 #else
661 #define SILC_SWAB_16(l)                                         \
662   ((SilcUInt16)(((SilcUInt16)(l) & (SilcUInt16)0x00FFU) << 8) | \
663                (((SilcUInt16)(l) & (SilcUInt16)0xFF00U) >> 8))
664 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
665 /***/
666
667 /****d* silcutil/SILC_SWAB_32
668  *
669  * NAME
670  *
671  *    #define SILC_SWAB_32(integer)
672  *
673  * DESCRIPTION
674  *
675  *    Swabs 32-bit unsigned integer byte order.  Returns the new value.
676  *
677  * SOURCE
678  */
679 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
680 #define SILC_SWAB_32(l)                         \
681 ({                                              \
682   SilcUInt32 _result_;                          \
683   asm volatile ("movl %1, %0; bswapl %0"        \
684                 : "=q" (_result_) : "q" (l));   \
685   _result_;                                     \
686 })
687 #else
688 #define SILC_SWAB_32(l)                                                 \
689   ((SilcUInt32)(((SilcUInt32)(l) & (SilcUInt32)0x000000FFUL) << 24) |   \
690                (((SilcUInt32)(l) & (SilcUInt32)0x0000FF00UL) << 8)  |   \
691                (((SilcUInt32)(l) & (SilcUInt32)0x00FF0000UL) >> 8)  |   \
692                (((SilcUInt32)(l) & (SilcUInt32)0xFF000000UL) >> 24))
693 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
694 /***/
695
696 /****d* silcutil/SILC_PTR_TO_32
697  *
698  * NAME
699  *
700  *    #define SILC_PTR_TO_32(ptr)
701  *
702  * DESCRIPTION
703  *
704  *    Type casts a pointer's value into a 32-bit integer.  Use this to
705  *    avoid compiler warnings when type casting pointers to integers
706  *    of different size.
707  *
708  * SOURCE
709  */
710 #if SILC_SIZEOF_VOID_P < 8
711 #define SILC_PTR_TO_32(_ptr__) ((SilcUInt32)(_ptr__))
712 #else
713 #define SILC_PTR_TO_32(_ptr__)                                          \
714   ((SilcUInt32)((SilcUInt64)(_ptr__) & (SilcUInt32)0xFFFFFFFFUL))
715 #endif
716 /***/
717
718 /****d* silcutil/SILC_PTR_TO_64
719  *
720  * NAME
721  *
722  *    #define SILC_PTR_TO_64(ptr)
723  *
724  * DESCRIPTION
725  *
726  *    Type casts a pointer's value into a 64-bit integer.  Use this to
727  *    avoid compiler warnings when type casting pointers to integers
728  *    of different size.
729  *
730  * SOURCE
731  */
732 #if SILC_SIZEOF_VOID_P < 8
733 #define SILC_PTR_TO_64(_ptr__) ((SilcUInt64)((SilcUInt32)(_ptr__)))
734 #else
735 #define SILC_PTR_TO_64(_ptr__) ((SilcUInt64)((SilcUInt64)(_ptr__)))
736 #endif
737 /***/
738
739 /****d* silcutil/SILC_32_TO_PTR
740  *
741  * NAME
742  *
743  *    #define SILC_32_TO_PTR(ptr)
744  *
745  * DESCRIPTION
746  *
747  *    Type casts a 32-bit integer value into a pointer.  Use this to
748  *    avoid compiler warnings when type casting integers to pointers of
749  *    different size.
750  *
751  * SOURCE
752  */
753 #if SILC_SIZEOF_VOID_P < 8
754 #define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt32)(_ival__)))
755 #else
756 #define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
757 #endif
758 /***/
759
760 /****d* silcutil/SILC_64_TO_PTR
761  *
762  * NAME
763  *
764  *    #define SILC_64_TO_PTR(ptr)
765  *
766  * DESCRIPTION
767  *
768  *    Type casts a 64-bit integer value into a pointer.  Use this to
769  *    avoid compiler warnings when type casting integers to pointers of
770  *    different size.
771  *
772  * SOURCE
773  */
774 #if SILC_SIZEOF_VOID_P < 8
775 #define SILC_64_TO_PTR(_ival__)                                         \
776   ((void *)((SilcUInt32)((SilcUInt64)(_ival__) & (SilcUInt32)0xFFFFFFFFUL)))
777 #else
778 #define SILC_64_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
779 #endif
780 /***/
781
782 /****d* silcutil/SILC_ASSERT
783  *
784  * NAME
785  *
786  *    #define SILC_ASSERT(experssion)
787  *
788  * DESCRIPTION
789  *
790  *    Assert macro that prints error message to stderr and calls abort()
791  *    if the `expression' is false (ie. compares equal to zero).  If
792  *    SILC_DEBUG is not defined this macro has no effect.
793  *
794  * SOURCE
795  */
796 #if defined(SILC_DEBUG)
797 #define SILC_ASSERT(expr) assert((expr));
798 #else
799 #define SILC_ASSERT(expr) do { } while(0)
800 #endif /* SILC_DEBUG */
801 /***/
802
803 /****d* silcutil/SILC_VERIFY
804  *
805  * NAME
806  *
807  *    #define SILC_VERIFY(experssion)
808  *
809  * DESCRIPTION
810  *
811  *    Verification macro that prints error message to stderr and calls
812  *    abort() if the `expression' is false (ie. compares equal to zero)
813  *    on debug builds (SILC_DEBUG defined), and prints error message to
814  *    stderr on release builds (SILC_DEBUG undefined) but does not abort().
815  *    This macro is always compiled even if debugging (SILC_DEBUG) is not
816  *    defined.
817  *
818  * SOURCE
819  */
820 #if defined(SILC_DEBUG)
821 #define SILC_VERIFY(expr) assert((expr));
822 #else
823 #define SILC_VERIFY(expr)                                               \
824   if (silc_unlikely(!(expr))) {                                         \
825     SILC_LOG_ERROR(("SILC_VERIFY %s:%s:%d",                             \
826                     __FILE__, __FUNCTION__, __LINE__));                 \
827     silc_set_errno_reason_nofail(SILC_ERR_ASSERT, "SILC_VERIFY %s:%s:%d", \
828                                  __FILE__, __FUNCTION__, __LINE__);     \
829   }
830 #endif /* SILC_DEBUG */
831 /***/
832
833 /****d* silcutil/silc_rol
834  *
835  * NAME
836  *
837  *    static inline SilcUInt32 silc_rol(SilcUInt32 val, int num);
838  *
839  * DESCRIPTION
840  *
841  *    Rotate 32-bit integer's bits to left `num' times.  Bits pushed to the
842  *    left will appear from the right side of the integer, thus rotating.
843  *    Returns the rotated value.
844  *
845  ***/
846 static inline SilcUInt32 silc_rol(SilcUInt32 val, int num)
847 {
848 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
849   asm volatile ("roll %%cl, %0"
850                 : "=r" (val) : "0" (val), "c" (num));
851   return val;
852 #else
853   return ((val << (SilcUInt32)num) | (val >> (32 - (SilcUInt32)num)));
854 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
855 }
856
857 /****d* silcutil/silc_rolc
858  *
859  * NAME
860  *
861  *    static inline SilcUInt32 silc_rolc(SilcUInt32 val, const int num);
862  *
863  * DESCRIPTION
864  *
865  *    Rotate 32-bit integer's bits to left `num' times.  Bits pushed to the
866  *    left will appear from the right side of the integer, thus rotating.
867  *    Returns the rotated value.
868  *
869  ***/
870 static inline SilcUInt32 silc_rolc(SilcUInt32 val, const int num)
871 {
872 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
873   asm volatile ("roll %2, %0"
874                 : "=r" (val) : "0" (val), "I" (num));
875   return val;
876 #else
877   return ((val << (SilcUInt32)num) | (val >> (32 - (SilcUInt32)num)));
878 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
879 }
880
881 /****d* silcutil/silc_ror
882  *
883  * NAME
884  *
885  *    static inline SilcUInt32 silc_ror(SilcUInt32 val, int num);
886  *
887  * DESCRIPTION
888  *
889  *    Rotate 32-bit integer's bits to right `num' times.  Bits pushed to the
890  *    right will appear from the left side of the integer, thus rotating.
891  *    Returns the rotated value.
892  *
893  ***/
894 static inline SilcUInt32 silc_ror(SilcUInt32 val, int num)
895 {
896 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
897   asm volatile ("rorl %%cl, %0"
898                 : "=r" (val) : "0" (val), "c" (num));
899   return val;
900 #else
901   return ((val >> (SilcUInt32)num) | (val << (32 - (SilcUInt32)num)));
902 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
903 }
904
905 /****d* silcutil/silc_rorc
906  *
907  * NAME
908  *
909  *    static inline SilcUInt32 silc_ror(SilcUInt32 val, const int num);
910  *
911  * DESCRIPTION
912  *
913  *    Rotate 32-bit integer's bits to right `num' times.  Bits pushed to the
914  *    right will appear from the left side of the integer, thus rotating.
915  *    Returns the rotated value.
916  *
917  ***/
918 static inline SilcUInt32 silc_rorc(SilcUInt32 val, const int num)
919 {
920 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
921   asm volatile ("rorl %2, %0"
922                 : "=r" (val) : "0" (val), "I" (num));
923   return val;
924 #else
925   return ((val >> (SilcUInt32)num) | (val << (32 - (SilcUInt32)num)));
926 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
927 }
928
929 /****d* silcutil/silc_rol64
930  *
931  * NAME
932  *
933  *    static inline SilcUInt64 silc_rol64(SilcUInt64 val, int num);
934  *
935  * DESCRIPTION
936  *
937  *    Rotate 64-bit integer's bits to left `num' times.  Bits pushed to the
938  *    left will appear from the right side of the integer, thus rotating.
939  *    Returns the rotated value.
940  *
941  ***/
942 static inline SilcUInt64 silc_rol64(SilcUInt64 val, int num)
943 {
944 #if defined(SILC_X86_64) && defined(__GNUC__)
945   asm volatile ("rolq %%cl, %0"
946                 : "=r" (val) : "0" (val), "c" (num));
947   return val;
948 #else
949   return ((val << (SilcUInt64)num) | (val >> (64 - (SilcUInt64)num)));
950 #endif /* SILC_X86_64 && __GNUC__ */
951 }
952
953 /****d* silcutil/silc_rolc64
954  *
955  * NAME
956  *
957  *    static inline SilcUInt64 silc_rolc64(SilcUInt64 val, const int num);
958  *
959  * DESCRIPTION
960  *
961  *    Rotate 64-bit integer's bits to left `num' times.  Bits pushed to the
962  *    left will appear from the right side of the integer, thus rotating.
963  *    Returns the rotated value.
964  *
965  ***/
966 static inline SilcUInt64 silc_rolc64(SilcUInt64 val, const int num)
967 {
968 #if defined(SILC_X86_64) && defined(__GNUC__)
969   asm volatile ("rolq %2, %0"
970                 : "=r" (val) : "0" (val), "J" (num));
971   return val;
972 #else
973   return ((val << (SilcUInt64)num) | (val >> (64 - (SilcUInt64)num)));
974 #endif /* SILC_X86_64 && __GNUC__ */
975 }
976
977 /****d* silcutil/silc_ror64
978  *
979  * NAME
980  *
981  *    static inline SilcUInt64 silc_ror64(SilcUInt64 val, int num);
982  *
983  * DESCRIPTION
984  *
985  *    Rotate 64-bit integer's bits to right `num' times.  Bits pushed to the
986  *    right will appear from the left side of the integer, thus rotating.
987  *    Returns the rotated value.
988  *
989  ***/
990 static inline SilcUInt64 silc_ror64(SilcUInt64 val, int num)
991 {
992 #if defined(SILC_X86_64) && defined(__GNUC__)
993   asm volatile ("rorq %%cl, %0"
994                 : "=r" (val) : "0" (val), "c" (num));
995   return val;
996 #else
997   return ((val >> (SilcUInt64)num) | (val << (64 - (SilcUInt64)num)));
998 #endif /* SILC_X86_64 && __GNUC__ */
999 }
1000
1001 /****d* silcutil/silc_rorc64
1002  *
1003  * NAME
1004  *
1005  *    static inline SilcUInt64 silc_rorc64(SilcUInt64 val, const int num);
1006  *
1007  * DESCRIPTION
1008  *
1009  *    Rotate 64-bit integer's bits to right `num' times.  Bits pushed to the
1010  *    right will appear from the left side of the integer, thus rotating.
1011  *    Returns the rotated value.
1012  *
1013  ***/
1014 static inline SilcUInt64 silc_rorc64(SilcUInt64 val, const int num)
1015 {
1016 #if defined(SILC_X86_64) && defined(__GNUC__)
1017   asm volatile ("rorq %2, %0"
1018                 : "=r" (val) : "0" (val), "J" (num));
1019   return val;
1020 #else
1021   return ((val >> (SilcUInt64)num) | (val << (64 - (SilcUInt64)num)));
1022 #endif /* SILC_X86_64 && __GNUC__ */
1023 }
1024
1025 /****d* silcutil/silc_offsetof
1026  *
1027  * NAME
1028  *
1029  *    #define silc_offsetof(TYPE, MEMBER)
1030  *
1031  * DESCRIPTION
1032  *
1033  *    offsetof() macro replacement.  Use this instead of offsetof().
1034  *
1035  ***/
1036 #define silc_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
1037
1038 /****d* silcutil/silc_attribute
1039  *
1040  * NAME
1041  *
1042  *    #define silc_attribute(attrlist)
1043  *
1044  * DESCRIPTION
1045  *
1046  *    Compiler attributes.  If compiler doesn't support attributes this macro
1047  *    doesn't do anything.  Currently this works only with GCC compiler.
1048  *    See GCC documentation for specified attributes.
1049  *
1050  * EXAMPLE
1051  *
1052  *    int printf(const char *fmt, ...) silc_attribute((format(printf, 1, 2)));
1053  *
1054  ***/
1055 #if defined(__GNUC__)
1056 #define silc_attribute(attrlist) __attribute__ (attrlist)
1057 #else
1058 #define silc_attribute(attrlist)
1059 #endif /* __GNUC__ */
1060
1061 /****d* silcutil/silc_likely
1062  *
1063  * NAME
1064  *
1065  *    #define silc_likely(expression)
1066  *
1067  * DESCRIPTION
1068  *
1069  *    Branch prediction macro.  It specifies that it is likely that the branch
1070  *    where silc_likely is applied is taken.  Compiler will optimize the
1071  *    code based on this prediction.  Never use this before you have profiled
1072  *    the code first.
1073  *
1074  ***/
1075
1076 /****d* silcutil/silc_unlikely
1077  *
1078  * NAME
1079  *
1080  *    #define silc_unlikely(expression)
1081  *
1082  * DESCRIPTION
1083  *
1084  *    Branch prediction macro.  It specifies that it is unlikely that the
1085  *    branch where silc_unlikely is applied is taken.  Compiler will optimize
1086  *    the code based on this prediction.  Never use this before you have
1087  *    profiled the code first.
1088  *
1089  ***/
1090 #if __GNUC__ >= 3
1091 #define silc_likely(expr) __builtin_expect(!!(expr), 1)
1092 #define silc_unlikely(expr) __builtin_expect(!!(expr), 0)
1093 #else
1094 #define silc_likely(expr) (expr)
1095 #define silc_unlikely(expr) (expr)
1096 #endif /* __GNUC__ >= 3 */
1097
1098 /* Prefetch operations.  Use these to prefetch data to CPU cache before
1099    reading or writing if you think that the data will be needed soon after
1100    prefetching. */
1101
1102 /****d* silcutil/silc_prefetch
1103  *
1104  * NAME
1105  *
1106  *    static inline void silc_prefetch(void *addr, int rw, int locality);
1107  *
1108  * DESCRIPTION
1109  *
1110  *    Simple prefetch.  Loads memory from specified address to CPU cache.
1111  *    The amount of data loaded is CPU dependant (cache line length).  The
1112  *    `rw' argument defines the reason for prefetch: 0=read, 1=write.  The
1113  *    `locality' argument defines the locality of the prefetch, 0=non-temporal
1114  *    (non-temporal cache, cache closest to CPU, data will not stay long in
1115  *    the cache), 1=temporal (L2+ cache), 2=temporal (L2, L3+ cache),
1116  *    3=temporal (fetch to all caches, data stays longer time in cache).
1117  *
1118  * NOTES
1119  *
1120  *    This produces only a hint for CPU.  CPU doesn't have to actually
1121  *    prefetch the data.  Use silc_prefetch_block to ensure CPU always
1122  *    prefetches.
1123  *
1124  ***/
1125
1126 static inline silc_attribute((always_inline))
1127 void silc_prefetch(void *addr, int rw, int locality)
1128 {
1129 #if __GNUC__ > 3
1130   __builtin_prefetch(addr, rw, locality);
1131 #endif /* __GNUC__ */
1132 }
1133
1134 /****d* silcutil/silc_prefetch_block
1135  *
1136  * NAME
1137  *
1138  *    static inline void silc_prefetch_block(void *addr,
1139  *                                           int prefetch_length,
1140  *                                           const int cache_line_length)
1141  *
1142  * DESCRIPTION
1143  *
1144  *    Enforced block prefetch.  This function loads the specified amount
1145  *    `prefetch_length' of memory from the specified address `addr' to CPU
1146  *    cache with each loaded cache line being the size of `cache_line_length'.
1147  *    If you don't know the cache line size use 64 bytes.  Note that, the
1148  *    `cache_line_length' is a const int.  In this context this mean its
1149  *    value must not come from a variable but must be a constant (the code
1150  *    won't compile if it comes from a variable).
1151  *
1152  *    The `prefetch_length' must be multiple of twice of the
1153  *    `cache_line_length' or 128 if you don't know the cache line size, hence
1154  *    the minimum length for `prefetch_length' is 128 bytes when the
1155  *    `cache_line_length' is 64 bytes.  Shorter cache line length (32 bytes)
1156  *    can be used too.
1157  *
1158  *    You should use the correct `cache_line_length' value for your CPU or
1159  *    the value of the CPU for which you want to optimize your code.  Intel
1160  *    CPUs usually have cache size of 32 or 64 bytes.  The most optimal
1161  *    prefetch is achieved if the `cache_line_length' is the actual CPU cache
1162  *    line size.  Always do performance testing with and without prefetching
1163  *    to make sure the prefetch actually helps.  If used improperly, it may
1164  *    slow down your program.
1165  *
1166  *    The difference to silc_prefetch is that this function always performs
1167  *    the prefetch and has the ability to prefetch more than one cache line
1168  *    worth of memory, whereas silc_prefetch can prefetch only one cache line
1169  *    and may not do the prefetch at all.
1170  *
1171  ***/
1172
1173 static inline silc_attribute((always_inline))
1174 void silc_prefetch_block(void *addr,
1175                          int prefetch_length,
1176                          const int cache_line_length)
1177 {
1178 #if 0
1179   SILC_ASSERT(cache_line_length >= 32);
1180   SILC_ASSERT(cache_line_length % 32 == 0);
1181   SILC_ASSERT(prefetch_length >= cache_line_length);
1182   SILC_ASSERT(prefetch_length % (cache_line_length * 2) == 0);
1183 #endif
1184
1185 #if SILC_SIZEOF_VOID_P < 8
1186 #define SILC_PREFETCH_UINT SilcUInt32
1187 #else
1188 #define SILC_PREFETCH_UINT SilcUInt64
1189 #endif /* SILC_SIZEOF_VOID_P < 8 */
1190
1191 #if defined(__GNUC__) && (defined(SILC_I386) || defined(SILC_X86_64))
1192
1193   /* Assembler implementation.
1194
1195      The idea here is to simply enforce the CPU to load the requested amount
1196      of bytes to cache.  We simply mov data from the memory to a register.
1197      Each mov will load a full cache line worth of data from the memory.
1198
1199      We expect the `cache_line_length' to be the actual cache line size.
1200      It doesn't matter if it is.  If it is smaller the prefetch is a bit
1201      slower as there is redundancy.  If it is larger we skip some of the
1202      data and don't prefetch everything.
1203
1204      The loop is unrolled to handle two mov's at once, this why we expect
1205      the `prefetch_length' to be multiple of twice the length of
1206      `cache_line_length`.  We also mov the data from end to beginning instead
1207      of from the beginning to assure CPU doesn't prefetch the data before
1208      we actually want to do it.
1209
1210      This technique is described by AMD in:
1211      http://cdrom.amd.com/devconn/events/AMD_block_prefetch_paper.pdf */
1212
1213   {
1214     SILC_PREFETCH_UINT temp;
1215
1216 #define SILC_PREFETCH_ASM(ip, rp)                                       \
1217     asm volatile ("1:                                   \n\t"           \
1218                   "mov" ip " -%c4(%2, %" rp "3), %0     \n\t"           \
1219                   "mov" ip " -%c5(%2, %" rp "3), %0     \n\t"           \
1220                   "sub" ip " %5, %" rp "3               \n\t"           \
1221                   "jnz 1b                               "               \
1222                   : "=&r" (temp), "=r" (prefetch_length)                \
1223                   : "r" (addr), "1" (prefetch_length),                  \
1224                     "Z" (cache_line_length),                            \
1225                     "Z" (cache_line_length * 2)                         \
1226                   : "memory", "cc");
1227
1228 #if defined(SILC_I386)
1229     /* 32-bit prefetch */
1230     SILC_PREFETCH_ASM("l", "");
1231 #else
1232     /* 64-bit prefetch */
1233     SILC_PREFETCH_ASM("q", "q");
1234 #endif /* SILC_I386 */
1235   }
1236
1237 #else
1238   /* C implementation.  Yes, you can do it in C too.  In fact, we'll try to
1239      make the compiler generate nearly identical code to the above assembler
1240      code.  Note that, the memory access must be volatile, otherwise the
1241      compiler will optimize them away because the temp variable isn't actually
1242      used for anything.  This should be as fast as the assembler code above,
1243      unless the compiler decides to start meddling with it (don't use
1244      -funroll-loops with this code). */
1245
1246   {
1247     register unsigned char *a = addr;
1248     register int len = prefetch_length;
1249     register SILC_PREFETCH_UINT temp;
1250
1251     do {
1252       temp = *(SILC_PREFETCH_UINT volatile *)
1253         (a + (len - cache_line_length));
1254       temp = *(SILC_PREFETCH_UINT volatile *)
1255         (a + (len - (cache_line_length * 2)));
1256       len -= (cache_line_length * 2);
1257     } while (len != 0);
1258   }
1259 #endif /* __GNUC__ */
1260 #undef SILC_PREFETCH_UINT
1261 #undef SILC_PREFETCH_ASM
1262 }
1263
1264 #endif /* SILCTYPES_H */