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