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