Path: blob/main/sys/contrib/openzfs/module/zstd/lib/common/bits.h
178701 views
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only1/*2* Copyright (c) Meta Platforms, Inc. and affiliates.3* All rights reserved.4*5* This source code is licensed under both the BSD-style license (found in the6* LICENSE file in the root directory of this source tree) and the GPLv2 (found7* in the COPYING file in the root directory of this source tree).8* You may select, at your option, one of the above-listed licenses.9*/1011#ifndef ZSTD_BITS_H12#define ZSTD_BITS_H1314#include "mem.h"1516MEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val)17{18assert(val != 0);19{20static const U32 DeBruijnBytePos[32] = {0, 1, 28, 2, 29, 14, 24, 3,2130, 22, 20, 15, 25, 17, 4, 8,2231, 27, 13, 23, 21, 19, 16, 7,2326, 12, 18, 6, 11, 5, 10, 9};24return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27];25}26}2728MEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val)29{30assert(val != 0);31#if defined(_MSC_VER)32# if STATIC_BMI233return (unsigned)_tzcnt_u32(val);34# else35if (val != 0) {36unsigned long r;37_BitScanForward(&r, val);38return (unsigned)r;39} else {40__assume(0); /* Should not reach this code path */41}42# endif43#elif defined(__GNUC__) && (__GNUC__ >= 4)44return (unsigned)__builtin_ctz(val);45#elif defined(__ICCARM__)46return (unsigned)__builtin_ctz(val);47#else48return ZSTD_countTrailingZeros32_fallback(val);49#endif50}5152MEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val)53{54assert(val != 0);55{56static const U32 DeBruijnClz[32] = {0, 9, 1, 10, 13, 21, 2, 29,5711, 14, 16, 18, 22, 25, 3, 30,588, 12, 20, 28, 15, 17, 24, 7,5919, 27, 23, 6, 26, 5, 4, 31};60val |= val >> 1;61val |= val >> 2;62val |= val >> 4;63val |= val >> 8;64val |= val >> 16;65return 31 - DeBruijnClz[(val * 0x07C4ACDDU) >> 27];66}67}6869MEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val)70{71assert(val != 0);72#if defined(_MSC_VER)73# if STATIC_BMI274return (unsigned)_lzcnt_u32(val);75# else76if (val != 0) {77unsigned long r;78_BitScanReverse(&r, val);79return (unsigned)(31 - r);80} else {81__assume(0); /* Should not reach this code path */82}83# endif84#elif defined(__GNUC__) && (__GNUC__ >= 4)85return (unsigned)__builtin_clz(val);86#elif defined(__ICCARM__)87return (unsigned)__builtin_clz(val);88#else89return ZSTD_countLeadingZeros32_fallback(val);90#endif91}9293MEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val)94{95assert(val != 0);96#if defined(_MSC_VER) && defined(_WIN64)97# if STATIC_BMI298return (unsigned)_tzcnt_u64(val);99# else100if (val != 0) {101unsigned long r;102_BitScanForward64(&r, val);103return (unsigned)r;104} else {105__assume(0); /* Should not reach this code path */106}107# endif108#elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__)109return (unsigned)__builtin_ctzll(val);110#elif defined(__ICCARM__)111return (unsigned)__builtin_ctzll(val);112#else113{114U32 mostSignificantWord = (U32)(val >> 32);115U32 leastSignificantWord = (U32)val;116if (leastSignificantWord == 0) {117return 32 + ZSTD_countTrailingZeros32(mostSignificantWord);118} else {119return ZSTD_countTrailingZeros32(leastSignificantWord);120}121}122#endif123}124125MEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val)126{127assert(val != 0);128#if defined(_MSC_VER) && defined(_WIN64)129# if STATIC_BMI2130return (unsigned)_lzcnt_u64(val);131# else132if (val != 0) {133unsigned long r;134_BitScanReverse64(&r, val);135return (unsigned)(63 - r);136} else {137__assume(0); /* Should not reach this code path */138}139# endif140#elif defined(__GNUC__) && (__GNUC__ >= 4)141return (unsigned)(__builtin_clzll(val));142#elif defined(__ICCARM__)143return (unsigned)(__builtin_clzll(val));144#else145{146U32 mostSignificantWord = (U32)(val >> 32);147U32 leastSignificantWord = (U32)val;148if (mostSignificantWord == 0) {149return 32 + ZSTD_countLeadingZeros32(leastSignificantWord);150} else {151return ZSTD_countLeadingZeros32(mostSignificantWord);152}153}154#endif155}156157MEM_STATIC unsigned ZSTD_NbCommonBytes(size_t val)158{159if (MEM_isLittleEndian()) {160if (MEM_64bits()) {161return ZSTD_countTrailingZeros64((U64)val) >> 3;162} else {163return ZSTD_countTrailingZeros32((U32)val) >> 3;164}165} else { /* Big Endian CPU */166if (MEM_64bits()) {167return ZSTD_countLeadingZeros64((U64)val) >> 3;168} else {169return ZSTD_countLeadingZeros32((U32)val) >> 3;170}171}172}173174MEM_STATIC unsigned ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */175{176assert(val != 0);177return 31 - ZSTD_countLeadingZeros32(val);178}179180/* ZSTD_rotateRight_*():181* Rotates a bitfield to the right by "count" bits.182* https://en.wikipedia.org/w/index.php?title=Circular_shift&oldid=991635599#Implementing_circular_shifts183*/184MEM_STATIC185U64 ZSTD_rotateRight_U64(U64 const value, U32 count) {186assert(count < 64);187count &= 0x3F; /* for fickle pattern recognition */188return (value >> count) | (U64)(value << ((0U - count) & 0x3F));189}190191MEM_STATIC192U32 ZSTD_rotateRight_U32(U32 const value, U32 count) {193assert(count < 32);194count &= 0x1F; /* for fickle pattern recognition */195return (value >> count) | (U32)(value << ((0U - count) & 0x1F));196}197198MEM_STATIC199U16 ZSTD_rotateRight_U16(U16 const value, U32 count) {200assert(count < 16);201count &= 0x0F; /* for fickle pattern recognition */202return (value >> count) | (U16)(value << ((0U - count) & 0x0F));203}204205#endif /* ZSTD_BITS_H */206207208