1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/include/prbit.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,151 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef prbit_h___ 1.10 +#define prbit_h___ 1.11 + 1.12 +#include "prtypes.h" 1.13 +PR_BEGIN_EXTERN_C 1.14 + 1.15 +/* 1.16 +** Replace compare/jump/add/shift sequence with compiler built-in/intrinsic 1.17 +** functions. 1.18 +*/ 1.19 +#if defined(_WIN32) && (_MSC_VER >= 1300) && \ 1.20 + (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_ARM)) 1.21 + unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask); 1.22 + unsigned char _BitScanReverse(unsigned long * Index, unsigned long Mask); 1.23 +# pragma intrinsic(_BitScanForward,_BitScanReverse) 1.24 + __forceinline static int __prBitScanForward32(unsigned int val) 1.25 + { 1.26 + unsigned long idx; 1.27 + _BitScanForward(&idx, (unsigned long)val); 1.28 + return( (int)idx ); 1.29 + } 1.30 + __forceinline static int __prBitScanReverse32(unsigned int val) 1.31 + { 1.32 + unsigned long idx; 1.33 + _BitScanReverse(&idx, (unsigned long)val); 1.34 + return( (int)(31-idx) ); 1.35 + } 1.36 +# define pr_bitscan_ctz32(val) __prBitScanForward32(val) 1.37 +# define pr_bitscan_clz32(val) __prBitScanReverse32(val) 1.38 +# define PR_HAVE_BUILTIN_BITSCAN32 1.39 +#elif ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && \ 1.40 + (defined(__i386__) || defined(__x86_64__) || defined(__arm__)) 1.41 +# define pr_bitscan_ctz32(val) __builtin_ctz(val) 1.42 +# define pr_bitscan_clz32(val) __builtin_clz(val) 1.43 +# define PR_HAVE_BUILTIN_BITSCAN32 1.44 +#endif /* MSVC || GCC */ 1.45 + 1.46 +/* 1.47 +** A prbitmap_t is a long integer that can be used for bitmaps 1.48 +*/ 1.49 +typedef unsigned long prbitmap_t; 1.50 + 1.51 +#define PR_TEST_BIT(_map,_bit) \ 1.52 + ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] & (1L << ((_bit) & (PR_BITS_PER_LONG-1)))) 1.53 +#define PR_SET_BIT(_map,_bit) \ 1.54 + ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] |= (1L << ((_bit) & (PR_BITS_PER_LONG-1)))) 1.55 +#define PR_CLEAR_BIT(_map,_bit) \ 1.56 + ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] &= ~(1L << ((_bit) & (PR_BITS_PER_LONG-1)))) 1.57 + 1.58 +/* 1.59 +** Compute the log of the least power of 2 greater than or equal to n 1.60 +*/ 1.61 +NSPR_API(PRIntn) PR_CeilingLog2(PRUint32 i); 1.62 + 1.63 +/* 1.64 +** Compute the log of the greatest power of 2 less than or equal to n 1.65 +*/ 1.66 +NSPR_API(PRIntn) PR_FloorLog2(PRUint32 i); 1.67 + 1.68 +/* 1.69 +** Macro version of PR_CeilingLog2: Compute the log of the least power of 1.70 +** 2 greater than or equal to _n. The result is returned in _log2. 1.71 +*/ 1.72 +#ifdef PR_HAVE_BUILTIN_BITSCAN32 1.73 +#define PR_CEILING_LOG2(_log2,_n) \ 1.74 + PR_BEGIN_MACRO \ 1.75 + PRUint32 j_ = (PRUint32)(_n); \ 1.76 + (_log2) = (j_ <= 1 ? 0 : 32 - pr_bitscan_clz32(j_ - 1)); \ 1.77 + PR_END_MACRO 1.78 +#else 1.79 +#define PR_CEILING_LOG2(_log2,_n) \ 1.80 + PR_BEGIN_MACRO \ 1.81 + PRUint32 j_ = (PRUint32)(_n); \ 1.82 + (_log2) = 0; \ 1.83 + if ((j_) & ((j_)-1)) \ 1.84 + (_log2) += 1; \ 1.85 + if ((j_) >> 16) \ 1.86 + (_log2) += 16, (j_) >>= 16; \ 1.87 + if ((j_) >> 8) \ 1.88 + (_log2) += 8, (j_) >>= 8; \ 1.89 + if ((j_) >> 4) \ 1.90 + (_log2) += 4, (j_) >>= 4; \ 1.91 + if ((j_) >> 2) \ 1.92 + (_log2) += 2, (j_) >>= 2; \ 1.93 + if ((j_) >> 1) \ 1.94 + (_log2) += 1; \ 1.95 + PR_END_MACRO 1.96 +#endif /* PR_HAVE_BUILTIN_BITSCAN32 */ 1.97 + 1.98 +/* 1.99 +** Macro version of PR_FloorLog2: Compute the log of the greatest power of 1.100 +** 2 less than or equal to _n. The result is returned in _log2. 1.101 +** 1.102 +** This is equivalent to finding the highest set bit in the word. 1.103 +*/ 1.104 +#ifdef PR_HAVE_BUILTIN_BITSCAN32 1.105 +#define PR_FLOOR_LOG2(_log2,_n) \ 1.106 + PR_BEGIN_MACRO \ 1.107 + PRUint32 j_ = (PRUint32)(_n); \ 1.108 + (_log2) = 31 - pr_bitscan_clz32((j_) | 1); \ 1.109 + PR_END_MACRO 1.110 +#else 1.111 +#define PR_FLOOR_LOG2(_log2,_n) \ 1.112 + PR_BEGIN_MACRO \ 1.113 + PRUint32 j_ = (PRUint32)(_n); \ 1.114 + (_log2) = 0; \ 1.115 + if ((j_) >> 16) \ 1.116 + (_log2) += 16, (j_) >>= 16; \ 1.117 + if ((j_) >> 8) \ 1.118 + (_log2) += 8, (j_) >>= 8; \ 1.119 + if ((j_) >> 4) \ 1.120 + (_log2) += 4, (j_) >>= 4; \ 1.121 + if ((j_) >> 2) \ 1.122 + (_log2) += 2, (j_) >>= 2; \ 1.123 + if ((j_) >> 1) \ 1.124 + (_log2) += 1; \ 1.125 + PR_END_MACRO 1.126 +#endif /* PR_HAVE_BUILTIN_BITSCAN32 */ 1.127 + 1.128 +/* 1.129 +** Macros for rotate left and right. The argument 'a' must be an unsigned 1.130 +** 32-bit integer type such as PRUint32. 1.131 +** 1.132 +** There is no rotate operation in the C Language, so the construct 1.133 +** (a << 4) | (a >> 28) is frequently used instead. Most compilers convert 1.134 +** this to a rotate instruction, but MSVC doesn't without a little help. 1.135 +** To get MSVC to generate a rotate instruction, we have to use the _rotl 1.136 +** or _rotr intrinsic and use a pragma to make it inline. 1.137 +** 1.138 +** Note: MSVC in VS2005 will do an inline rotate instruction on the above 1.139 +** construct. 1.140 +*/ 1.141 + 1.142 +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \ 1.143 + defined(_M_X64) || defined(_M_ARM)) 1.144 +#include <stdlib.h> 1.145 +#pragma intrinsic(_rotl, _rotr) 1.146 +#define PR_ROTATE_LEFT32(a, bits) _rotl(a, bits) 1.147 +#define PR_ROTATE_RIGHT32(a, bits) _rotr(a, bits) 1.148 +#else 1.149 +#define PR_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits)))) 1.150 +#define PR_ROTATE_RIGHT32(a, bits) (((a) >> (bits)) | ((a) << (32 - (bits)))) 1.151 +#endif 1.152 + 1.153 +PR_END_EXTERN_C 1.154 +#endif /* prbit_h___ */