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