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