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