1 /* 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef VPX_VPX_PORTS_BITOPS_H_ 12 #define VPX_VPX_PORTS_BITOPS_H_ 13 14 #include <assert.h> 15 16 #ifdef _MSC_VER 17 #if defined(_M_X64) || defined(_M_IX86) 18 #include <intrin.h> 19 #define USE_MSC_INTRINSICS 20 #endif 21 #endif 22 23 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 // These versions of get_lsb() and get_msb() are only valid when n != 0 28 // because all of the optimized versions are undefined when n == 0: 29 // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html 30 31 // use GNU builtins where available. 32 #if defined(__GNUC__) && \ 33 ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) get_lsb(unsigned int n)34static INLINE int get_lsb(unsigned int n) { 35 assert(n != 0); 36 return __builtin_ctz(n); 37 } 38 get_msb(unsigned int n)39static INLINE int get_msb(unsigned int n) { 40 assert(n != 0); 41 return 31 ^ __builtin_clz(n); 42 } 43 #elif defined(USE_MSC_INTRINSICS) 44 #pragma intrinsic(_BitScanForward) 45 #pragma intrinsic(_BitScanReverse) 46 47 static INLINE int get_lsb(unsigned int n) { 48 unsigned long first_set_bit; // NOLINT(runtime/int) 49 _BitScanForward(&first_set_bit, n); 50 return first_set_bit; 51 } 52 53 static INLINE int get_msb(unsigned int n) { 54 unsigned long first_set_bit; 55 assert(n != 0); 56 _BitScanReverse(&first_set_bit, n); 57 return first_set_bit; 58 } 59 #undef USE_MSC_INTRINSICS 60 #else 61 static INLINE int get_lsb(unsigned int n) { 62 int i; 63 assert(n != 0); 64 for (i = 0; i < 32 && !(n & 1); ++i) n >>= 1; 65 return i; 66 } 67 68 // Returns (int)floor(log2(n)). n must be > 0. 69 static INLINE int get_msb(unsigned int n) { 70 int log = 0; 71 unsigned int value = n; 72 int i; 73 74 assert(n != 0); 75 76 for (i = 4; i >= 0; --i) { 77 const int shift = (1 << i); 78 const unsigned int x = value >> shift; 79 if (x != 0) { 80 value = x; 81 log += shift; 82 } 83 } 84 return log; 85 } 86 #endif 87 88 #ifdef __cplusplus 89 } // extern "C" 90 #endif 91 92 #endif // VPX_VPX_PORTS_BITOPS_H_ 93