1e8d8bef9SDimitry Andric//===-- int_mulv_impl.inc - Implement __mulv[sdt]i3 ---------------*- C -*-===// 2e8d8bef9SDimitry Andric// 3e8d8bef9SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric// 7e8d8bef9SDimitry Andric//===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric// 9e8d8bef9SDimitry Andric// Helper used by __mulvsi3, __mulvdi3 and __mulvti3. 10e8d8bef9SDimitry Andric// 11e8d8bef9SDimitry Andric//===----------------------------------------------------------------------===// 12e8d8bef9SDimitry Andric 13e8d8bef9SDimitry Andric#include "int_lib.h" 14e8d8bef9SDimitry Andric 15e8d8bef9SDimitry Andric// Returns: a * b 16e8d8bef9SDimitry Andric 17e8d8bef9SDimitry Andric// Effects: aborts if a * b overflows 18e8d8bef9SDimitry Andric 19e8d8bef9SDimitry Andricstatic __inline fixint_t __mulvXi3(fixint_t a, fixint_t b) { 20e8d8bef9SDimitry Andric const int N = (int)(sizeof(fixint_t) * CHAR_BIT); 21*06c3fb27SDimitry Andric const fixint_t MIN = (fixint_t)((fixuint_t)1 << (N - 1)); 22e8d8bef9SDimitry Andric const fixint_t MAX = ~MIN; 23e8d8bef9SDimitry Andric if (a == MIN) { 24e8d8bef9SDimitry Andric if (b == 0 || b == 1) 25e8d8bef9SDimitry Andric return a * b; 26e8d8bef9SDimitry Andric compilerrt_abort(); 27e8d8bef9SDimitry Andric } 28e8d8bef9SDimitry Andric if (b == MIN) { 29e8d8bef9SDimitry Andric if (a == 0 || a == 1) 30e8d8bef9SDimitry Andric return a * b; 31e8d8bef9SDimitry Andric compilerrt_abort(); 32e8d8bef9SDimitry Andric } 33e8d8bef9SDimitry Andric fixint_t sa = a >> (N - 1); 34e8d8bef9SDimitry Andric fixint_t abs_a = (a ^ sa) - sa; 35e8d8bef9SDimitry Andric fixint_t sb = b >> (N - 1); 36e8d8bef9SDimitry Andric fixint_t abs_b = (b ^ sb) - sb; 37e8d8bef9SDimitry Andric if (abs_a < 2 || abs_b < 2) 38e8d8bef9SDimitry Andric return a * b; 39e8d8bef9SDimitry Andric if (sa == sb) { 40e8d8bef9SDimitry Andric if (abs_a > MAX / abs_b) 41e8d8bef9SDimitry Andric compilerrt_abort(); 42e8d8bef9SDimitry Andric } else { 43e8d8bef9SDimitry Andric if (abs_a > MIN / -abs_b) 44e8d8bef9SDimitry Andric compilerrt_abort(); 45e8d8bef9SDimitry Andric } 46e8d8bef9SDimitry Andric return a * b; 47e8d8bef9SDimitry Andric} 48