17db96d56Sopenharmony_ci/* 27db96d56Sopenharmony_ci * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. 37db96d56Sopenharmony_ci * 47db96d56Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 57db96d56Sopenharmony_ci * modification, are permitted provided that the following conditions 67db96d56Sopenharmony_ci * are met: 77db96d56Sopenharmony_ci * 87db96d56Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 97db96d56Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 107db96d56Sopenharmony_ci * 117db96d56Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 127db96d56Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 137db96d56Sopenharmony_ci * documentation and/or other materials provided with the distribution. 147db96d56Sopenharmony_ci * 157db96d56Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND 167db96d56Sopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 177db96d56Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 187db96d56Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 197db96d56Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 207db96d56Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 217db96d56Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 227db96d56Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 237db96d56Sopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 247db96d56Sopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 257db96d56Sopenharmony_ci * SUCH DAMAGE. 267db96d56Sopenharmony_ci */ 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci#ifndef LIBMPDEC_BITS_H_ 307db96d56Sopenharmony_ci#define LIBMPDEC_BITS_H_ 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci#include "mpdecimal.h" 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci/* Check if n is a power of 2. */ 377db96d56Sopenharmony_cistatic inline int 387db96d56Sopenharmony_ciispower2(mpd_size_t n) 397db96d56Sopenharmony_ci{ 407db96d56Sopenharmony_ci return n != 0 && (n & (n-1)) == 0; 417db96d56Sopenharmony_ci} 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ci#if defined(ANSI) 447db96d56Sopenharmony_ci/* 457db96d56Sopenharmony_ci * Return the most significant bit position of n from 0 to 31 (63). 467db96d56Sopenharmony_ci * Assumptions: n != 0. 477db96d56Sopenharmony_ci */ 487db96d56Sopenharmony_cistatic inline int 497db96d56Sopenharmony_cimpd_bsr(mpd_size_t n) 507db96d56Sopenharmony_ci{ 517db96d56Sopenharmony_ci int pos = 0; 527db96d56Sopenharmony_ci mpd_size_t tmp; 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci#ifdef CONFIG_64 557db96d56Sopenharmony_ci tmp = n >> 32; 567db96d56Sopenharmony_ci if (tmp != 0) { n = tmp; pos += 32; } 577db96d56Sopenharmony_ci#endif 587db96d56Sopenharmony_ci tmp = n >> 16; 597db96d56Sopenharmony_ci if (tmp != 0) { n = tmp; pos += 16; } 607db96d56Sopenharmony_ci tmp = n >> 8; 617db96d56Sopenharmony_ci if (tmp != 0) { n = tmp; pos += 8; } 627db96d56Sopenharmony_ci tmp = n >> 4; 637db96d56Sopenharmony_ci if (tmp != 0) { n = tmp; pos += 4; } 647db96d56Sopenharmony_ci tmp = n >> 2; 657db96d56Sopenharmony_ci if (tmp != 0) { n = tmp; pos += 2; } 667db96d56Sopenharmony_ci tmp = n >> 1; 677db96d56Sopenharmony_ci if (tmp != 0) { n = tmp; pos += 1; } 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci return pos + (int)n - 1; 707db96d56Sopenharmony_ci} 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci/* 737db96d56Sopenharmony_ci * Return the least significant bit position of n from 0 to 31 (63). 747db96d56Sopenharmony_ci * Assumptions: n != 0. 757db96d56Sopenharmony_ci */ 767db96d56Sopenharmony_cistatic inline int 777db96d56Sopenharmony_cimpd_bsf(mpd_size_t n) 787db96d56Sopenharmony_ci{ 797db96d56Sopenharmony_ci int pos; 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci#ifdef CONFIG_64 827db96d56Sopenharmony_ci pos = 63; 837db96d56Sopenharmony_ci if (n & 0x00000000FFFFFFFFULL) { pos -= 32; } else { n >>= 32; } 847db96d56Sopenharmony_ci if (n & 0x000000000000FFFFULL) { pos -= 16; } else { n >>= 16; } 857db96d56Sopenharmony_ci if (n & 0x00000000000000FFULL) { pos -= 8; } else { n >>= 8; } 867db96d56Sopenharmony_ci if (n & 0x000000000000000FULL) { pos -= 4; } else { n >>= 4; } 877db96d56Sopenharmony_ci if (n & 0x0000000000000003ULL) { pos -= 2; } else { n >>= 2; } 887db96d56Sopenharmony_ci if (n & 0x0000000000000001ULL) { pos -= 1; } 897db96d56Sopenharmony_ci#else 907db96d56Sopenharmony_ci pos = 31; 917db96d56Sopenharmony_ci if (n & 0x000000000000FFFFUL) { pos -= 16; } else { n >>= 16; } 927db96d56Sopenharmony_ci if (n & 0x00000000000000FFUL) { pos -= 8; } else { n >>= 8; } 937db96d56Sopenharmony_ci if (n & 0x000000000000000FUL) { pos -= 4; } else { n >>= 4; } 947db96d56Sopenharmony_ci if (n & 0x0000000000000003UL) { pos -= 2; } else { n >>= 2; } 957db96d56Sopenharmony_ci if (n & 0x0000000000000001UL) { pos -= 1; } 967db96d56Sopenharmony_ci#endif 977db96d56Sopenharmony_ci return pos; 987db96d56Sopenharmony_ci} 997db96d56Sopenharmony_ci/* END ANSI */ 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci#elif defined(ASM) 1027db96d56Sopenharmony_ci/* 1037db96d56Sopenharmony_ci * Bit scan reverse. Assumptions: a != 0. 1047db96d56Sopenharmony_ci */ 1057db96d56Sopenharmony_cistatic inline int 1067db96d56Sopenharmony_cimpd_bsr(mpd_size_t a) 1077db96d56Sopenharmony_ci{ 1087db96d56Sopenharmony_ci mpd_size_t retval; 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci __asm__ ( 1117db96d56Sopenharmony_ci#ifdef CONFIG_64 1127db96d56Sopenharmony_ci "bsrq %1, %0\n\t" 1137db96d56Sopenharmony_ci#else 1147db96d56Sopenharmony_ci "bsr %1, %0\n\t" 1157db96d56Sopenharmony_ci#endif 1167db96d56Sopenharmony_ci :"=r" (retval) 1177db96d56Sopenharmony_ci :"r" (a) 1187db96d56Sopenharmony_ci :"cc" 1197db96d56Sopenharmony_ci ); 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci return (int)retval; 1227db96d56Sopenharmony_ci} 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci/* 1257db96d56Sopenharmony_ci * Bit scan forward. Assumptions: a != 0. 1267db96d56Sopenharmony_ci */ 1277db96d56Sopenharmony_cistatic inline int 1287db96d56Sopenharmony_cimpd_bsf(mpd_size_t a) 1297db96d56Sopenharmony_ci{ 1307db96d56Sopenharmony_ci mpd_size_t retval; 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci __asm__ ( 1337db96d56Sopenharmony_ci#ifdef CONFIG_64 1347db96d56Sopenharmony_ci "bsfq %1, %0\n\t" 1357db96d56Sopenharmony_ci#else 1367db96d56Sopenharmony_ci "bsf %1, %0\n\t" 1377db96d56Sopenharmony_ci#endif 1387db96d56Sopenharmony_ci :"=r" (retval) 1397db96d56Sopenharmony_ci :"r" (a) 1407db96d56Sopenharmony_ci :"cc" 1417db96d56Sopenharmony_ci ); 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ci return (int)retval; 1447db96d56Sopenharmony_ci} 1457db96d56Sopenharmony_ci/* END ASM */ 1467db96d56Sopenharmony_ci 1477db96d56Sopenharmony_ci#elif defined(MASM) 1487db96d56Sopenharmony_ci#include <intrin.h> 1497db96d56Sopenharmony_ci/* 1507db96d56Sopenharmony_ci * Bit scan reverse. Assumptions: a != 0. 1517db96d56Sopenharmony_ci */ 1527db96d56Sopenharmony_cistatic inline int __cdecl 1537db96d56Sopenharmony_cimpd_bsr(mpd_size_t a) 1547db96d56Sopenharmony_ci{ 1557db96d56Sopenharmony_ci unsigned long retval; 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_ci#ifdef CONFIG_64 1587db96d56Sopenharmony_ci _BitScanReverse64(&retval, a); 1597db96d56Sopenharmony_ci#else 1607db96d56Sopenharmony_ci _BitScanReverse(&retval, a); 1617db96d56Sopenharmony_ci#endif 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_ci return (int)retval; 1647db96d56Sopenharmony_ci} 1657db96d56Sopenharmony_ci 1667db96d56Sopenharmony_ci/* 1677db96d56Sopenharmony_ci * Bit scan forward. Assumptions: a != 0. 1687db96d56Sopenharmony_ci */ 1697db96d56Sopenharmony_cistatic inline int __cdecl 1707db96d56Sopenharmony_cimpd_bsf(mpd_size_t a) 1717db96d56Sopenharmony_ci{ 1727db96d56Sopenharmony_ci unsigned long retval; 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci#ifdef CONFIG_64 1757db96d56Sopenharmony_ci _BitScanForward64(&retval, a); 1767db96d56Sopenharmony_ci#else 1777db96d56Sopenharmony_ci _BitScanForward(&retval, a); 1787db96d56Sopenharmony_ci#endif 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci return (int)retval; 1817db96d56Sopenharmony_ci} 1827db96d56Sopenharmony_ci/* END MASM (_MSC_VER) */ 1837db96d56Sopenharmony_ci#else 1847db96d56Sopenharmony_ci #error "missing preprocessor definitions" 1857db96d56Sopenharmony_ci#endif /* BSR/BSF */ 1867db96d56Sopenharmony_ci 1877db96d56Sopenharmony_ci 1887db96d56Sopenharmony_ci#endif /* LIBMPDEC_BITS_H_ */ 189