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