11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_BASE_BITS_H_ 61cb0ef41Sopenharmony_ci#define V8_BASE_BITS_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <stdint.h> 91cb0ef41Sopenharmony_ci#include <type_traits> 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci#include "src/base/base-export.h" 121cb0ef41Sopenharmony_ci#include "src/base/macros.h" 131cb0ef41Sopenharmony_ci#if V8_CC_MSVC 141cb0ef41Sopenharmony_ci#include <intrin.h> 151cb0ef41Sopenharmony_ci#endif 161cb0ef41Sopenharmony_ci#if V8_OS_WIN32 171cb0ef41Sopenharmony_ci#include "src/base/win32-headers.h" 181cb0ef41Sopenharmony_ci#endif 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_cinamespace v8 { 211cb0ef41Sopenharmony_cinamespace base { 221cb0ef41Sopenharmony_cinamespace bits { 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci// CountPopulation(value) returns the number of bits set in |value|. 251cb0ef41Sopenharmony_citemplate <typename T> 261cb0ef41Sopenharmony_ciconstexpr inline 271cb0ef41Sopenharmony_ci typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 8, 281cb0ef41Sopenharmony_ci unsigned>::type 291cb0ef41Sopenharmony_ci CountPopulation(T value) { 301cb0ef41Sopenharmony_ci STATIC_ASSERT(sizeof(T) <= 8); 311cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_POPCOUNT 321cb0ef41Sopenharmony_ci return sizeof(T) == 8 ? __builtin_popcountll(static_cast<uint64_t>(value)) 331cb0ef41Sopenharmony_ci : __builtin_popcount(static_cast<uint32_t>(value)); 341cb0ef41Sopenharmony_ci#else 351cb0ef41Sopenharmony_ci // Fall back to divide-and-conquer popcount (see "Hacker's Delight" by Henry 361cb0ef41Sopenharmony_ci // S. Warren, Jr.), chapter 5-1. 371cb0ef41Sopenharmony_ci constexpr uint64_t mask[] = {0x5555555555555555, 0x3333333333333333, 381cb0ef41Sopenharmony_ci 0x0f0f0f0f0f0f0f0f}; 391cb0ef41Sopenharmony_ci // Start with 64 buckets of 1 bits, holding values from [0,1]. 401cb0ef41Sopenharmony_ci value = ((value >> 1) & mask[0]) + (value & mask[0]); 411cb0ef41Sopenharmony_ci // Having 32 buckets of 2 bits, holding values from [0,2] now. 421cb0ef41Sopenharmony_ci value = ((value >> 2) & mask[1]) + (value & mask[1]); 431cb0ef41Sopenharmony_ci // Having 16 buckets of 4 bits, holding values from [0,4] now. 441cb0ef41Sopenharmony_ci value = ((value >> 4) & mask[2]) + (value & mask[2]); 451cb0ef41Sopenharmony_ci // Having 8 buckets of 8 bits, holding values from [0,8] now. 461cb0ef41Sopenharmony_ci // From this point on, the buckets are bigger than the number of bits 471cb0ef41Sopenharmony_ci // required to hold the values, and the buckets are bigger the maximum 481cb0ef41Sopenharmony_ci // result, so there's no need to mask value anymore, since there's no 491cb0ef41Sopenharmony_ci // more risk of overflow between buckets. 501cb0ef41Sopenharmony_ci if (sizeof(T) > 1) value = (value >> (sizeof(T) > 1 ? 8 : 0)) + value; 511cb0ef41Sopenharmony_ci // Having 4 buckets of 16 bits, holding values from [0,16] now. 521cb0ef41Sopenharmony_ci if (sizeof(T) > 2) value = (value >> (sizeof(T) > 2 ? 16 : 0)) + value; 531cb0ef41Sopenharmony_ci // Having 2 buckets of 32 bits, holding values from [0,32] now. 541cb0ef41Sopenharmony_ci if (sizeof(T) > 4) value = (value >> (sizeof(T) > 4 ? 32 : 0)) + value; 551cb0ef41Sopenharmony_ci // Having 1 buckets of 64 bits, holding values from [0,64] now. 561cb0ef41Sopenharmony_ci return static_cast<unsigned>(value & 0xff); 571cb0ef41Sopenharmony_ci#endif 581cb0ef41Sopenharmony_ci} 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci// ReverseBits(value) returns |value| in reverse bit order. 611cb0ef41Sopenharmony_citemplate <typename T> 621cb0ef41Sopenharmony_ciT ReverseBits(T value) { 631cb0ef41Sopenharmony_ci STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || 641cb0ef41Sopenharmony_ci (sizeof(value) == 4) || (sizeof(value) == 8)); 651cb0ef41Sopenharmony_ci T result = 0; 661cb0ef41Sopenharmony_ci for (unsigned i = 0; i < (sizeof(value) * 8); i++) { 671cb0ef41Sopenharmony_ci result = (result << 1) | (value & 1); 681cb0ef41Sopenharmony_ci value >>= 1; 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci return result; 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci// CountLeadingZeros(value) returns the number of zero bits following the most 741cb0ef41Sopenharmony_ci// significant 1 bit in |value| if |value| is non-zero, otherwise it returns 751cb0ef41Sopenharmony_ci// {sizeof(T) * 8}. 761cb0ef41Sopenharmony_citemplate <typename T, unsigned bits = sizeof(T) * 8> 771cb0ef41Sopenharmony_ciinline constexpr 781cb0ef41Sopenharmony_ci typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 8, 791cb0ef41Sopenharmony_ci unsigned>::type 801cb0ef41Sopenharmony_ci CountLeadingZeros(T value) { 811cb0ef41Sopenharmony_ci static_assert(bits > 0, "invalid instantiation"); 821cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_CLZ 831cb0ef41Sopenharmony_ci return value == 0 841cb0ef41Sopenharmony_ci ? bits 851cb0ef41Sopenharmony_ci : bits == 64 861cb0ef41Sopenharmony_ci ? __builtin_clzll(static_cast<uint64_t>(value)) 871cb0ef41Sopenharmony_ci : __builtin_clz(static_cast<uint32_t>(value)) - (32 - bits); 881cb0ef41Sopenharmony_ci#else 891cb0ef41Sopenharmony_ci // Binary search algorithm taken from "Hacker's Delight" (by Henry S. Warren, 901cb0ef41Sopenharmony_ci // Jr.), figures 5-11 and 5-12. 911cb0ef41Sopenharmony_ci if (bits == 1) return static_cast<unsigned>(value) ^ 1; 921cb0ef41Sopenharmony_ci T upper_half = value >> (bits / 2); 931cb0ef41Sopenharmony_ci T next_value = upper_half != 0 ? upper_half : value; 941cb0ef41Sopenharmony_ci unsigned add = upper_half != 0 ? 0 : bits / 2; 951cb0ef41Sopenharmony_ci constexpr unsigned next_bits = bits == 1 ? 1 : bits / 2; 961cb0ef41Sopenharmony_ci return CountLeadingZeros<T, next_bits>(next_value) + add; 971cb0ef41Sopenharmony_ci#endif 981cb0ef41Sopenharmony_ci} 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ciinline constexpr unsigned CountLeadingZeros32(uint32_t value) { 1011cb0ef41Sopenharmony_ci return CountLeadingZeros(value); 1021cb0ef41Sopenharmony_ci} 1031cb0ef41Sopenharmony_ciinline constexpr unsigned CountLeadingZeros64(uint64_t value) { 1041cb0ef41Sopenharmony_ci return CountLeadingZeros(value); 1051cb0ef41Sopenharmony_ci} 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci// CountTrailingZeros(value) returns the number of zero bits preceding the 1081cb0ef41Sopenharmony_ci// least significant 1 bit in |value| if |value| is non-zero, otherwise it 1091cb0ef41Sopenharmony_ci// returns {sizeof(T) * 8}. 1101cb0ef41Sopenharmony_ci// See CountTrailingZerosNonZero for an optimized version for the case that 1111cb0ef41Sopenharmony_ci// |value| is guaranteed to be non-zero. 1121cb0ef41Sopenharmony_citemplate <typename T, unsigned bits = sizeof(T) * 8> 1131cb0ef41Sopenharmony_ciinline constexpr 1141cb0ef41Sopenharmony_ci typename std::enable_if<std::is_integral<T>::value && sizeof(T) <= 8, 1151cb0ef41Sopenharmony_ci unsigned>::type 1161cb0ef41Sopenharmony_ci CountTrailingZeros(T value) { 1171cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_CTZ 1181cb0ef41Sopenharmony_ci return value == 0 ? bits 1191cb0ef41Sopenharmony_ci : bits == 64 ? __builtin_ctzll(static_cast<uint64_t>(value)) 1201cb0ef41Sopenharmony_ci : __builtin_ctz(static_cast<uint32_t>(value)); 1211cb0ef41Sopenharmony_ci#else 1221cb0ef41Sopenharmony_ci // Fall back to popcount (see "Hacker's Delight" by Henry S. Warren, Jr.), 1231cb0ef41Sopenharmony_ci // chapter 5-4. On x64, since is faster than counting in a loop and faster 1241cb0ef41Sopenharmony_ci // than doing binary search. 1251cb0ef41Sopenharmony_ci using U = typename std::make_unsigned<T>::type; 1261cb0ef41Sopenharmony_ci U u = value; 1271cb0ef41Sopenharmony_ci return CountPopulation(static_cast<U>(~u & (u - 1u))); 1281cb0ef41Sopenharmony_ci#endif 1291cb0ef41Sopenharmony_ci} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ciinline constexpr unsigned CountTrailingZeros32(uint32_t value) { 1321cb0ef41Sopenharmony_ci return CountTrailingZeros(value); 1331cb0ef41Sopenharmony_ci} 1341cb0ef41Sopenharmony_ciinline constexpr unsigned CountTrailingZeros64(uint64_t value) { 1351cb0ef41Sopenharmony_ci return CountTrailingZeros(value); 1361cb0ef41Sopenharmony_ci} 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci// CountTrailingZerosNonZero(value) returns the number of zero bits preceding 1391cb0ef41Sopenharmony_ci// the least significant 1 bit in |value| if |value| is non-zero, otherwise the 1401cb0ef41Sopenharmony_ci// behavior is undefined. 1411cb0ef41Sopenharmony_ci// See CountTrailingZeros for an alternative version that allows |value| == 0. 1421cb0ef41Sopenharmony_citemplate <typename T, unsigned bits = sizeof(T) * 8> 1431cb0ef41Sopenharmony_ciinline constexpr 1441cb0ef41Sopenharmony_ci typename std::enable_if<std::is_integral<T>::value && sizeof(T) <= 8, 1451cb0ef41Sopenharmony_ci unsigned>::type 1461cb0ef41Sopenharmony_ci CountTrailingZerosNonZero(T value) { 1471cb0ef41Sopenharmony_ci DCHECK_NE(0, value); 1481cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_CTZ 1491cb0ef41Sopenharmony_ci return bits == 64 ? __builtin_ctzll(static_cast<uint64_t>(value)) 1501cb0ef41Sopenharmony_ci : __builtin_ctz(static_cast<uint32_t>(value)); 1511cb0ef41Sopenharmony_ci#else 1521cb0ef41Sopenharmony_ci return CountTrailingZeros<T, bits>(value); 1531cb0ef41Sopenharmony_ci#endif 1541cb0ef41Sopenharmony_ci} 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci// Returns true iff |value| is a power of 2. 1571cb0ef41Sopenharmony_citemplate <typename T, 1581cb0ef41Sopenharmony_ci typename = typename std::enable_if<std::is_integral<T>::value || 1591cb0ef41Sopenharmony_ci std::is_enum<T>::value>::type> 1601cb0ef41Sopenharmony_ciconstexpr inline bool IsPowerOfTwo(T value) { 1611cb0ef41Sopenharmony_ci return value > 0 && (value & (value - 1)) == 0; 1621cb0ef41Sopenharmony_ci} 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci// Identical to {CountTrailingZeros}, but only works for powers of 2. 1651cb0ef41Sopenharmony_citemplate <typename T, 1661cb0ef41Sopenharmony_ci typename = typename std::enable_if<std::is_integral<T>::value>::type> 1671cb0ef41Sopenharmony_ciinline constexpr int WhichPowerOfTwo(T value) { 1681cb0ef41Sopenharmony_ci DCHECK(IsPowerOfTwo(value)); 1691cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_CTZ 1701cb0ef41Sopenharmony_ci STATIC_ASSERT(sizeof(T) <= 8); 1711cb0ef41Sopenharmony_ci return sizeof(T) == 8 ? __builtin_ctzll(static_cast<uint64_t>(value)) 1721cb0ef41Sopenharmony_ci : __builtin_ctz(static_cast<uint32_t>(value)); 1731cb0ef41Sopenharmony_ci#else 1741cb0ef41Sopenharmony_ci // Fall back to popcount (see "Hacker's Delight" by Henry S. Warren, Jr.), 1751cb0ef41Sopenharmony_ci // chapter 5-4. On x64, since is faster than counting in a loop and faster 1761cb0ef41Sopenharmony_ci // than doing binary search. 1771cb0ef41Sopenharmony_ci using U = typename std::make_unsigned<T>::type; 1781cb0ef41Sopenharmony_ci U u = value; 1791cb0ef41Sopenharmony_ci return CountPopulation(static_cast<U>(u - 1)); 1801cb0ef41Sopenharmony_ci#endif 1811cb0ef41Sopenharmony_ci} 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci// RoundUpToPowerOfTwo32(value) returns the smallest power of two which is 1841cb0ef41Sopenharmony_ci// greater than or equal to |value|. If you pass in a |value| that is already a 1851cb0ef41Sopenharmony_ci// power of two, it is returned as is. |value| must be less than or equal to 1861cb0ef41Sopenharmony_ci// 0x80000000u. Uses computation based on leading zeros if we have compiler 1871cb0ef41Sopenharmony_ci// support for that. Falls back to the implementation from "Hacker's Delight" by 1881cb0ef41Sopenharmony_ci// Henry S. Warren, Jr., figure 3-3, page 48, where the function is called clp2. 1891cb0ef41Sopenharmony_ciV8_BASE_EXPORT uint32_t RoundUpToPowerOfTwo32(uint32_t value); 1901cb0ef41Sopenharmony_ci// Same for 64 bit integers. |value| must be <= 2^63 1911cb0ef41Sopenharmony_ciV8_BASE_EXPORT uint64_t RoundUpToPowerOfTwo64(uint64_t value); 1921cb0ef41Sopenharmony_ci// Same for size_t integers. 1931cb0ef41Sopenharmony_ciinline size_t RoundUpToPowerOfTwo(size_t value) { 1941cb0ef41Sopenharmony_ci if (sizeof(size_t) == sizeof(uint64_t)) { 1951cb0ef41Sopenharmony_ci return RoundUpToPowerOfTwo64(value); 1961cb0ef41Sopenharmony_ci } else { 1971cb0ef41Sopenharmony_ci // Without windows.h included this line triggers a truncation warning on 1981cb0ef41Sopenharmony_ci // 64-bit builds. Presumably windows.h disables the relevant warning. 1991cb0ef41Sopenharmony_ci return RoundUpToPowerOfTwo32(static_cast<uint32_t>(value)); 2001cb0ef41Sopenharmony_ci } 2011cb0ef41Sopenharmony_ci} 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci// RoundDownToPowerOfTwo32(value) returns the greatest power of two which is 2041cb0ef41Sopenharmony_ci// less than or equal to |value|. If you pass in a |value| that is already a 2051cb0ef41Sopenharmony_ci// power of two, it is returned as is. 2061cb0ef41Sopenharmony_ciinline uint32_t RoundDownToPowerOfTwo32(uint32_t value) { 2071cb0ef41Sopenharmony_ci if (value > 0x80000000u) return 0x80000000u; 2081cb0ef41Sopenharmony_ci uint32_t result = RoundUpToPowerOfTwo32(value); 2091cb0ef41Sopenharmony_ci if (result > value) result >>= 1; 2101cb0ef41Sopenharmony_ci return result; 2111cb0ef41Sopenharmony_ci} 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci// Precondition: 0 <= shift < 32 2151cb0ef41Sopenharmony_ciinline constexpr uint32_t RotateRight32(uint32_t value, uint32_t shift) { 2161cb0ef41Sopenharmony_ci return (value >> shift) | (value << ((32 - shift) & 31)); 2171cb0ef41Sopenharmony_ci} 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci// Precondition: 0 <= shift < 32 2201cb0ef41Sopenharmony_ciinline constexpr uint32_t RotateLeft32(uint32_t value, uint32_t shift) { 2211cb0ef41Sopenharmony_ci return (value << shift) | (value >> ((32 - shift) & 31)); 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci// Precondition: 0 <= shift < 64 2251cb0ef41Sopenharmony_ciinline constexpr uint64_t RotateRight64(uint64_t value, uint64_t shift) { 2261cb0ef41Sopenharmony_ci return (value >> shift) | (value << ((64 - shift) & 63)); 2271cb0ef41Sopenharmony_ci} 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci// Precondition: 0 <= shift < 64 2301cb0ef41Sopenharmony_ciinline constexpr uint64_t RotateLeft64(uint64_t value, uint64_t shift) { 2311cb0ef41Sopenharmony_ci return (value << shift) | (value >> ((64 - shift) & 63)); 2321cb0ef41Sopenharmony_ci} 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci// SignedAddOverflow32(lhs,rhs,val) performs a signed summation of |lhs| and 2351cb0ef41Sopenharmony_ci// |rhs| and stores the result into the variable pointed to by |val| and 2361cb0ef41Sopenharmony_ci// returns true if the signed summation resulted in an overflow. 2371cb0ef41Sopenharmony_ciinline bool SignedAddOverflow32(int32_t lhs, int32_t rhs, int32_t* val) { 2381cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_SADD_OVERFLOW 2391cb0ef41Sopenharmony_ci return __builtin_sadd_overflow(lhs, rhs, val); 2401cb0ef41Sopenharmony_ci#else 2411cb0ef41Sopenharmony_ci uint32_t res = static_cast<uint32_t>(lhs) + static_cast<uint32_t>(rhs); 2421cb0ef41Sopenharmony_ci *val = bit_cast<int32_t>(res); 2431cb0ef41Sopenharmony_ci return ((res ^ lhs) & (res ^ rhs) & (1U << 31)) != 0; 2441cb0ef41Sopenharmony_ci#endif 2451cb0ef41Sopenharmony_ci} 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci// SignedSubOverflow32(lhs,rhs,val) performs a signed subtraction of |lhs| and 2491cb0ef41Sopenharmony_ci// |rhs| and stores the result into the variable pointed to by |val| and 2501cb0ef41Sopenharmony_ci// returns true if the signed subtraction resulted in an overflow. 2511cb0ef41Sopenharmony_ciinline bool SignedSubOverflow32(int32_t lhs, int32_t rhs, int32_t* val) { 2521cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_SSUB_OVERFLOW 2531cb0ef41Sopenharmony_ci return __builtin_ssub_overflow(lhs, rhs, val); 2541cb0ef41Sopenharmony_ci#else 2551cb0ef41Sopenharmony_ci uint32_t res = static_cast<uint32_t>(lhs) - static_cast<uint32_t>(rhs); 2561cb0ef41Sopenharmony_ci *val = bit_cast<int32_t>(res); 2571cb0ef41Sopenharmony_ci return ((res ^ lhs) & (res ^ ~rhs) & (1U << 31)) != 0; 2581cb0ef41Sopenharmony_ci#endif 2591cb0ef41Sopenharmony_ci} 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci// SignedMulOverflow32(lhs,rhs,val) performs a signed multiplication of |lhs| 2621cb0ef41Sopenharmony_ci// and |rhs| and stores the result into the variable pointed to by |val| and 2631cb0ef41Sopenharmony_ci// returns true if the signed multiplication resulted in an overflow. 2641cb0ef41Sopenharmony_ciV8_BASE_EXPORT bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t* val); 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci// SignedAddOverflow64(lhs,rhs,val) performs a signed summation of |lhs| and 2671cb0ef41Sopenharmony_ci// |rhs| and stores the result into the variable pointed to by |val| and 2681cb0ef41Sopenharmony_ci// returns true if the signed summation resulted in an overflow. 2691cb0ef41Sopenharmony_ciinline bool SignedAddOverflow64(int64_t lhs, int64_t rhs, int64_t* val) { 2701cb0ef41Sopenharmony_ci uint64_t res = static_cast<uint64_t>(lhs) + static_cast<uint64_t>(rhs); 2711cb0ef41Sopenharmony_ci *val = bit_cast<int64_t>(res); 2721cb0ef41Sopenharmony_ci return ((res ^ lhs) & (res ^ rhs) & (1ULL << 63)) != 0; 2731cb0ef41Sopenharmony_ci} 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci// SignedSubOverflow64(lhs,rhs,val) performs a signed subtraction of |lhs| and 2771cb0ef41Sopenharmony_ci// |rhs| and stores the result into the variable pointed to by |val| and 2781cb0ef41Sopenharmony_ci// returns true if the signed subtraction resulted in an overflow. 2791cb0ef41Sopenharmony_ciinline bool SignedSubOverflow64(int64_t lhs, int64_t rhs, int64_t* val) { 2801cb0ef41Sopenharmony_ci uint64_t res = static_cast<uint64_t>(lhs) - static_cast<uint64_t>(rhs); 2811cb0ef41Sopenharmony_ci *val = bit_cast<int64_t>(res); 2821cb0ef41Sopenharmony_ci return ((res ^ lhs) & (res ^ ~rhs) & (1ULL << 63)) != 0; 2831cb0ef41Sopenharmony_ci} 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci// SignedMulHigh32(lhs, rhs) multiplies two signed 32-bit values |lhs| and 2861cb0ef41Sopenharmony_ci// |rhs|, extracts the most significant 32 bits of the result, and returns 2871cb0ef41Sopenharmony_ci// those. 2881cb0ef41Sopenharmony_ciV8_BASE_EXPORT int32_t SignedMulHigh32(int32_t lhs, int32_t rhs); 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci// SignedMulHighAndAdd32(lhs, rhs, acc) multiplies two signed 32-bit values 2911cb0ef41Sopenharmony_ci// |lhs| and |rhs|, extracts the most significant 32 bits of the result, and 2921cb0ef41Sopenharmony_ci// adds the accumulate value |acc|. 2931cb0ef41Sopenharmony_ciV8_BASE_EXPORT int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, 2941cb0ef41Sopenharmony_ci int32_t acc); 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ci// SignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient 2971cb0ef41Sopenharmony_ci// truncated to int32. If |rhs| is zero, then zero is returned. If |lhs| 2981cb0ef41Sopenharmony_ci// is minint and |rhs| is -1, it returns minint. 2991cb0ef41Sopenharmony_ciV8_BASE_EXPORT int32_t SignedDiv32(int32_t lhs, int32_t rhs); 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci// SignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder 3021cb0ef41Sopenharmony_ci// truncated to int32. If either |rhs| is zero or |lhs| is minint and |rhs| 3031cb0ef41Sopenharmony_ci// is -1, it returns zero. 3041cb0ef41Sopenharmony_ciV8_BASE_EXPORT int32_t SignedMod32(int32_t lhs, int32_t rhs); 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci// UnsignedAddOverflow32(lhs,rhs,val) performs an unsigned summation of |lhs| 3071cb0ef41Sopenharmony_ci// and |rhs| and stores the result into the variable pointed to by |val| and 3081cb0ef41Sopenharmony_ci// returns true if the unsigned summation resulted in an overflow. 3091cb0ef41Sopenharmony_ciinline bool UnsignedAddOverflow32(uint32_t lhs, uint32_t rhs, uint32_t* val) { 3101cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_SADD_OVERFLOW 3111cb0ef41Sopenharmony_ci return __builtin_uadd_overflow(lhs, rhs, val); 3121cb0ef41Sopenharmony_ci#else 3131cb0ef41Sopenharmony_ci *val = lhs + rhs; 3141cb0ef41Sopenharmony_ci return *val < (lhs | rhs); 3151cb0ef41Sopenharmony_ci#endif 3161cb0ef41Sopenharmony_ci} 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci// UnsignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient 3201cb0ef41Sopenharmony_ci// truncated to uint32. If |rhs| is zero, then zero is returned. 3211cb0ef41Sopenharmony_ciinline uint32_t UnsignedDiv32(uint32_t lhs, uint32_t rhs) { 3221cb0ef41Sopenharmony_ci return rhs ? lhs / rhs : 0u; 3231cb0ef41Sopenharmony_ci} 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci// UnsignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder 3271cb0ef41Sopenharmony_ci// truncated to uint32. If |rhs| is zero, then zero is returned. 3281cb0ef41Sopenharmony_ciinline uint32_t UnsignedMod32(uint32_t lhs, uint32_t rhs) { 3291cb0ef41Sopenharmony_ci return rhs ? lhs % rhs : 0u; 3301cb0ef41Sopenharmony_ci} 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci// Wraparound integer arithmetic without undefined behavior. 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ciinline int32_t WraparoundAdd32(int32_t lhs, int32_t rhs) { 3351cb0ef41Sopenharmony_ci return static_cast<int32_t>(static_cast<uint32_t>(lhs) + 3361cb0ef41Sopenharmony_ci static_cast<uint32_t>(rhs)); 3371cb0ef41Sopenharmony_ci} 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ciinline int32_t WraparoundNeg32(int32_t x) { 3401cb0ef41Sopenharmony_ci return static_cast<int32_t>(-static_cast<uint32_t>(x)); 3411cb0ef41Sopenharmony_ci} 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci// SignedSaturatedAdd64(lhs, rhs) adds |lhs| and |rhs|, 3441cb0ef41Sopenharmony_ci// checks and returns the result. 3451cb0ef41Sopenharmony_ciV8_BASE_EXPORT int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs); 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ci// SignedSaturatedSub64(lhs, rhs) subtracts |lhs| by |rhs|, 3481cb0ef41Sopenharmony_ci// checks and returns the result. 3491cb0ef41Sopenharmony_ciV8_BASE_EXPORT int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs); 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci} // namespace bits 3521cb0ef41Sopenharmony_ci} // namespace base 3531cb0ef41Sopenharmony_ci} // namespace v8 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci#endif // V8_BASE_BITS_H_ 356