/*1* Copyright (c) 2008-2020 Stefan Krah. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/262728#ifndef LIBMPDEC_BITS_H_29#define LIBMPDEC_BITS_H_303132#include "mpdecimal.h"333435/* Check if n is a power of 2. */36static inline int37ispower2(mpd_size_t n)38{39return n != 0 && (n & (n-1)) == 0;40}4142#if defined(ANSI)43/*44* Return the most significant bit position of n from 0 to 31 (63).45* Assumptions: n != 0.46*/47static inline int48mpd_bsr(mpd_size_t n)49{50int pos = 0;51mpd_size_t tmp;5253#ifdef CONFIG_6454tmp = n >> 32;55if (tmp != 0) { n = tmp; pos += 32; }56#endif57tmp = n >> 16;58if (tmp != 0) { n = tmp; pos += 16; }59tmp = n >> 8;60if (tmp != 0) { n = tmp; pos += 8; }61tmp = n >> 4;62if (tmp != 0) { n = tmp; pos += 4; }63tmp = n >> 2;64if (tmp != 0) { n = tmp; pos += 2; }65tmp = n >> 1;66if (tmp != 0) { n = tmp; pos += 1; }6768return pos + (int)n - 1;69}7071/*72* Return the least significant bit position of n from 0 to 31 (63).73* Assumptions: n != 0.74*/75static inline int76mpd_bsf(mpd_size_t n)77{78int pos;7980#ifdef CONFIG_6481pos = 63;82if (n & 0x00000000FFFFFFFFULL) { pos -= 32; } else { n >>= 32; }83if (n & 0x000000000000FFFFULL) { pos -= 16; } else { n >>= 16; }84if (n & 0x00000000000000FFULL) { pos -= 8; } else { n >>= 8; }85if (n & 0x000000000000000FULL) { pos -= 4; } else { n >>= 4; }86if (n & 0x0000000000000003ULL) { pos -= 2; } else { n >>= 2; }87if (n & 0x0000000000000001ULL) { pos -= 1; }88#else89pos = 31;90if (n & 0x000000000000FFFFUL) { pos -= 16; } else { n >>= 16; }91if (n & 0x00000000000000FFUL) { pos -= 8; } else { n >>= 8; }92if (n & 0x000000000000000FUL) { pos -= 4; } else { n >>= 4; }93if (n & 0x0000000000000003UL) { pos -= 2; } else { n >>= 2; }94if (n & 0x0000000000000001UL) { pos -= 1; }95#endif96return pos;97}98/* END ANSI */99100#elif defined(ASM)101/*102* Bit scan reverse. Assumptions: a != 0.103*/104static inline int105mpd_bsr(mpd_size_t a)106{107mpd_size_t retval;108109__asm__ (110#ifdef CONFIG_64111"bsrq %1, %0\n\t"112#else113"bsr %1, %0\n\t"114#endif115:"=r" (retval)116:"r" (a)117:"cc"118);119120return (int)retval;121}122123/*124* Bit scan forward. Assumptions: a != 0.125*/126static inline int127mpd_bsf(mpd_size_t a)128{129mpd_size_t retval;130131__asm__ (132#ifdef CONFIG_64133"bsfq %1, %0\n\t"134#else135"bsf %1, %0\n\t"136#endif137:"=r" (retval)138:"r" (a)139:"cc"140);141142return (int)retval;143}144/* END ASM */145146#elif defined(MASM)147#include <intrin.h>148/*149* Bit scan reverse. Assumptions: a != 0.150*/151static inline int __cdecl152mpd_bsr(mpd_size_t a)153{154unsigned long retval;155156#ifdef CONFIG_64157_BitScanReverse64(&retval, a);158#else159_BitScanReverse(&retval, a);160#endif161162return (int)retval;163}164165/*166* Bit scan forward. Assumptions: a != 0.167*/168static inline int __cdecl169mpd_bsf(mpd_size_t a)170{171unsigned long retval;172173#ifdef CONFIG_64174_BitScanForward64(&retval, a);175#else176_BitScanForward(&retval, a);177#endif178179return (int)retval;180}181/* END MASM (_MSC_VER) */182#else183#error "missing preprocessor definitions"184#endif /* BSR/BSF */185186187#endif /* LIBMPDEC_BITS_H_ */188189190