1*77c1e3ccSAndroid Build Coastguard Worker /* 2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3*77c1e3ccSAndroid Build Coastguard Worker * 4*77c1e3ccSAndroid Build Coastguard Worker * This source code is subject to the terms of the BSD 2 Clause License and 5*77c1e3ccSAndroid Build Coastguard Worker * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6*77c1e3ccSAndroid Build Coastguard Worker * was not distributed with this source code in the LICENSE file, you can 7*77c1e3ccSAndroid Build Coastguard Worker * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8*77c1e3ccSAndroid Build Coastguard Worker * Media Patent License 1.0 was not distributed with this source code in the 9*77c1e3ccSAndroid Build Coastguard Worker * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10*77c1e3ccSAndroid Build Coastguard Worker */ 11*77c1e3ccSAndroid Build Coastguard Worker 12*77c1e3ccSAndroid Build Coastguard Worker #ifndef AOM_AOM_PORTS_BITOPS_H_ 13*77c1e3ccSAndroid Build Coastguard Worker #define AOM_AOM_PORTS_BITOPS_H_ 14*77c1e3ccSAndroid Build Coastguard Worker 15*77c1e3ccSAndroid Build Coastguard Worker #include <assert.h> 16*77c1e3ccSAndroid Build Coastguard Worker #include <stdint.h> 17*77c1e3ccSAndroid Build Coastguard Worker 18*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_config.h" 19*77c1e3ccSAndroid Build Coastguard Worker 20*77c1e3ccSAndroid Build Coastguard Worker #ifdef _MSC_VER 21*77c1e3ccSAndroid Build Coastguard Worker #if defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64) || defined(_M_ARM) 22*77c1e3ccSAndroid Build Coastguard Worker #include <intrin.h> 23*77c1e3ccSAndroid Build Coastguard Worker #define USE_MSC_INTRINSICS 24*77c1e3ccSAndroid Build Coastguard Worker #endif 25*77c1e3ccSAndroid Build Coastguard Worker #endif 26*77c1e3ccSAndroid Build Coastguard Worker 27*77c1e3ccSAndroid Build Coastguard Worker #ifdef __cplusplus 28*77c1e3ccSAndroid Build Coastguard Worker extern "C" { 29*77c1e3ccSAndroid Build Coastguard Worker #endif 30*77c1e3ccSAndroid Build Coastguard Worker 31*77c1e3ccSAndroid Build Coastguard Worker // get_msb: 32*77c1e3ccSAndroid Build Coastguard Worker // Returns (int)floor(log2(n)). n must be > 0. 33*77c1e3ccSAndroid Build Coastguard Worker // These versions of get_msb() are only valid when n != 0 because all 34*77c1e3ccSAndroid Build Coastguard Worker // of the optimized versions are undefined when n == 0: 35*77c1e3ccSAndroid Build Coastguard Worker 36*77c1e3ccSAndroid Build Coastguard Worker // GCC compiler: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html 37*77c1e3ccSAndroid Build Coastguard Worker // MSVC: https://learn.microsoft.com/en-us/cpp/intrinsics/compiler-intrinsics 38*77c1e3ccSAndroid Build Coastguard Worker 39*77c1e3ccSAndroid Build Coastguard Worker // use GNU builtins where available. 40*77c1e3ccSAndroid Build Coastguard Worker #if defined(__GNUC__) && \ 41*77c1e3ccSAndroid Build Coastguard Worker ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) get_msb(unsigned int n)42*77c1e3ccSAndroid Build Coastguard Workerstatic inline int get_msb(unsigned int n) { 43*77c1e3ccSAndroid Build Coastguard Worker assert(n != 0); 44*77c1e3ccSAndroid Build Coastguard Worker return 31 ^ __builtin_clz(n); 45*77c1e3ccSAndroid Build Coastguard Worker } 46*77c1e3ccSAndroid Build Coastguard Worker #elif defined(USE_MSC_INTRINSICS) 47*77c1e3ccSAndroid Build Coastguard Worker #pragma intrinsic(_BitScanReverse) 48*77c1e3ccSAndroid Build Coastguard Worker 49*77c1e3ccSAndroid Build Coastguard Worker static inline int get_msb(unsigned int n) { 50*77c1e3ccSAndroid Build Coastguard Worker unsigned long first_set_bit; 51*77c1e3ccSAndroid Build Coastguard Worker assert(n != 0); 52*77c1e3ccSAndroid Build Coastguard Worker _BitScanReverse(&first_set_bit, n); 53*77c1e3ccSAndroid Build Coastguard Worker return first_set_bit; 54*77c1e3ccSAndroid Build Coastguard Worker } 55*77c1e3ccSAndroid Build Coastguard Worker #else 56*77c1e3ccSAndroid Build Coastguard Worker static inline int get_msb(unsigned int n) { 57*77c1e3ccSAndroid Build Coastguard Worker int log = 0; 58*77c1e3ccSAndroid Build Coastguard Worker unsigned int value = n; 59*77c1e3ccSAndroid Build Coastguard Worker 60*77c1e3ccSAndroid Build Coastguard Worker assert(n != 0); 61*77c1e3ccSAndroid Build Coastguard Worker 62*77c1e3ccSAndroid Build Coastguard Worker for (int shift = 16; shift != 0; shift >>= 1) { 63*77c1e3ccSAndroid Build Coastguard Worker const unsigned int x = value >> shift; 64*77c1e3ccSAndroid Build Coastguard Worker if (x != 0) { 65*77c1e3ccSAndroid Build Coastguard Worker value = x; 66*77c1e3ccSAndroid Build Coastguard Worker log += shift; 67*77c1e3ccSAndroid Build Coastguard Worker } 68*77c1e3ccSAndroid Build Coastguard Worker } 69*77c1e3ccSAndroid Build Coastguard Worker return log; 70*77c1e3ccSAndroid Build Coastguard Worker } 71*77c1e3ccSAndroid Build Coastguard Worker #endif 72*77c1e3ccSAndroid Build Coastguard Worker 73*77c1e3ccSAndroid Build Coastguard Worker #if defined(__GNUC__) && \ 74*77c1e3ccSAndroid Build Coastguard Worker ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) aom_clzll(uint64_t n)75*77c1e3ccSAndroid Build Coastguard Workerstatic inline int aom_clzll(uint64_t n) { return __builtin_clzll(n); } 76*77c1e3ccSAndroid Build Coastguard Worker #elif defined(USE_MSC_INTRINSICS) 77*77c1e3ccSAndroid Build Coastguard Worker #if defined(_M_X64) || defined(_M_ARM64) 78*77c1e3ccSAndroid Build Coastguard Worker #pragma intrinsic(_BitScanReverse64) 79*77c1e3ccSAndroid Build Coastguard Worker #endif 80*77c1e3ccSAndroid Build Coastguard Worker aom_clzll(uint64_t n)81*77c1e3ccSAndroid Build Coastguard Workerstatic inline int aom_clzll(uint64_t n) { 82*77c1e3ccSAndroid Build Coastguard Worker assert(n != 0); 83*77c1e3ccSAndroid Build Coastguard Worker unsigned long first_set_bit; // NOLINT(runtime/int) 84*77c1e3ccSAndroid Build Coastguard Worker #if defined(_M_X64) || defined(_M_ARM64) 85*77c1e3ccSAndroid Build Coastguard Worker const unsigned char bit_set = 86*77c1e3ccSAndroid Build Coastguard Worker _BitScanReverse64(&first_set_bit, (unsigned __int64)n); 87*77c1e3ccSAndroid Build Coastguard Worker #else // !(defined(_M_X64) || defined(_M_ARM64)) 88*77c1e3ccSAndroid Build Coastguard Worker const unsigned long n_hi = (unsigned long)(n >> 32); // NOLINT(runtime/int) 89*77c1e3ccSAndroid Build Coastguard Worker if (n_hi != 0) { 90*77c1e3ccSAndroid Build Coastguard Worker const unsigned char bit_set = _BitScanReverse(&first_set_bit, n_hi); 91*77c1e3ccSAndroid Build Coastguard Worker assert(bit_set != 0); 92*77c1e3ccSAndroid Build Coastguard Worker (void)bit_set; 93*77c1e3ccSAndroid Build Coastguard Worker return 31 ^ (int)first_set_bit; 94*77c1e3ccSAndroid Build Coastguard Worker } 95*77c1e3ccSAndroid Build Coastguard Worker const unsigned char bit_set = 96*77c1e3ccSAndroid Build Coastguard Worker _BitScanReverse(&first_set_bit, (unsigned long)n); // NOLINT(runtime/int) 97*77c1e3ccSAndroid Build Coastguard Worker #endif 98*77c1e3ccSAndroid Build Coastguard Worker assert(bit_set != 0); 99*77c1e3ccSAndroid Build Coastguard Worker (void)bit_set; 100*77c1e3ccSAndroid Build Coastguard Worker return 63 ^ (int)first_set_bit; 101*77c1e3ccSAndroid Build Coastguard Worker } 102*77c1e3ccSAndroid Build Coastguard Worker #undef USE_MSC_INTRINSICS 103*77c1e3ccSAndroid Build Coastguard Worker #else aom_clzll(uint64_t n)104*77c1e3ccSAndroid Build Coastguard Workerstatic inline int aom_clzll(uint64_t n) { 105*77c1e3ccSAndroid Build Coastguard Worker assert(n != 0); 106*77c1e3ccSAndroid Build Coastguard Worker 107*77c1e3ccSAndroid Build Coastguard Worker int res = 0; 108*77c1e3ccSAndroid Build Coastguard Worker uint64_t high_bit = 1ULL << 63; 109*77c1e3ccSAndroid Build Coastguard Worker while (!(n & high_bit)) { 110*77c1e3ccSAndroid Build Coastguard Worker res++; 111*77c1e3ccSAndroid Build Coastguard Worker n <<= 1; 112*77c1e3ccSAndroid Build Coastguard Worker } 113*77c1e3ccSAndroid Build Coastguard Worker return res; 114*77c1e3ccSAndroid Build Coastguard Worker } 115*77c1e3ccSAndroid Build Coastguard Worker #endif 116*77c1e3ccSAndroid Build Coastguard Worker 117*77c1e3ccSAndroid Build Coastguard Worker #ifdef __cplusplus 118*77c1e3ccSAndroid Build Coastguard Worker } // extern "C" 119*77c1e3ccSAndroid Build Coastguard Worker #endif 120*77c1e3ccSAndroid Build Coastguard Worker 121*77c1e3ccSAndroid Build Coastguard Worker #endif // AOM_AOM_PORTS_BITOPS_H_ 122