10b57cec5SDimitry Andric /*===-- int128_builtins.cpp - Implement __muloti4 --------------------------=== 20b57cec5SDimitry Andric * 30b57cec5SDimitry Andric * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric * See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric * 70b57cec5SDimitry Andric * ===----------------------------------------------------------------------=== 80b57cec5SDimitry Andric * 90b57cec5SDimitry Andric * This file implements __muloti4, and is stolen from the compiler_rt library. 100b57cec5SDimitry Andric * 110b57cec5SDimitry Andric * FIXME: we steal and re-compile it into filesystem, which uses __int128_t, 120b57cec5SDimitry Andric * and requires this builtin when sanitized. See llvm.org/PR30643 130b57cec5SDimitry Andric * 140b57cec5SDimitry Andric * ===----------------------------------------------------------------------=== 150b57cec5SDimitry Andric */ 1681ad6265SDimitry Andric #include <__config> 1781ad6265SDimitry Andric #include <climits> 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #if !defined(_LIBCPP_HAS_NO_INT128) 200b57cec5SDimitry Andric 21*cb14a3feSDimitry Andric extern "C" __attribute__((no_sanitize("undefined"))) _LIBCPP_EXPORTED_FROM_ABI __int128_t __muloti4(__int128_t a,__int128_t b,int * overflow)22*cb14a3feSDimitry Andric__muloti4(__int128_t a, __int128_t b, int* overflow) { 230b57cec5SDimitry Andric const int N = (int)(sizeof(__int128_t) * CHAR_BIT); 240b57cec5SDimitry Andric const __int128_t MIN = (__int128_t)1 << (N - 1); 250b57cec5SDimitry Andric const __int128_t MAX = ~MIN; 260b57cec5SDimitry Andric *overflow = 0; 270b57cec5SDimitry Andric __int128_t result = a * b; 280b57cec5SDimitry Andric if (a == MIN) { 290b57cec5SDimitry Andric if (b != 0 && b != 1) 300b57cec5SDimitry Andric *overflow = 1; 310b57cec5SDimitry Andric return result; 320b57cec5SDimitry Andric } 330b57cec5SDimitry Andric if (b == MIN) { 340b57cec5SDimitry Andric if (a != 0 && a != 1) 350b57cec5SDimitry Andric *overflow = 1; 360b57cec5SDimitry Andric return result; 370b57cec5SDimitry Andric } 380b57cec5SDimitry Andric __int128_t sa = a >> (N - 1); 390b57cec5SDimitry Andric __int128_t abs_a = (a ^ sa) - sa; 400b57cec5SDimitry Andric __int128_t sb = b >> (N - 1); 410b57cec5SDimitry Andric __int128_t abs_b = (b ^ sb) - sb; 420b57cec5SDimitry Andric if (abs_a < 2 || abs_b < 2) 430b57cec5SDimitry Andric return result; 440b57cec5SDimitry Andric if (sa == sb) { 450b57cec5SDimitry Andric if (abs_a > MAX / abs_b) 460b57cec5SDimitry Andric *overflow = 1; 470b57cec5SDimitry Andric } else { 480b57cec5SDimitry Andric if (abs_a > MIN / -abs_b) 490b57cec5SDimitry Andric *overflow = 1; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric return result; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric #endif 55