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