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 #define INLINE __inline 15 16 #include <assert.h> 17 #include <stdint.h> 18 19 #if defined(_WIN32) && (defined(_M_X64) || defined(_M_IX86)) 20 #include <intrin.h> 21 #define USE_MSC_INTRINSICS 22 #endif 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 // These versions of get_msb() are only valid when n != 0 because all 29 // of the optimized versions are undefined when n == 0: 30 // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html 31 32 // use GNU builtins where available. 33 #if defined(__GNUC__) && \ 34 ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) get_msb(unsigned int n)35static INLINE int get_msb(unsigned int n) { 36 assert(n != 0); 37 return 31 ^ __builtin_clz(n); 38 } 39 #elif defined(USE_MSC_INTRINSICS) 40 #pragma intrinsic(_BitScanReverse) 41 42 static INLINE int get_msb(unsigned int n) { 43 unsigned long first_set_bit; 44 assert(n != 0); 45 _BitScanReverse(&first_set_bit, n); 46 return first_set_bit; 47 } 48 #undef USE_MSC_INTRINSICS 49 #else 50 // Returns (int)floor(log2(n)). n must be > 0. 51 static INLINE int get_msb(unsigned int n) { 52 int log = 0; 53 unsigned int value = n; 54 int i; 55 56 assert(n != 0); 57 58 for (i = 4; i >= 0; --i) { 59 const int shift = (1 << i); 60 const unsigned int x = value >> shift; 61 if (x != 0) { 62 value = x; 63 log += shift; 64 } 65 } 66 return log; 67 } 68 #endif 69 70 #ifdef __cplusplus 71 } // extern "C" 72 #endif 73 74 #endif // VPX_VPX_PORTS_BITOPS_H_ 75