tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

mulodi4.c (1606B)


      1 /*===-- mulodi4.c - Implement __mulodi4 -----------------------------------===
      2 *
      3 *                     The LLVM Compiler Infrastructure
      4 *
      5 * This file is dual licensed under the MIT and the University of Illinois Open
      6 * Source Licenses. See LICENSE.TXT for details.
      7 *
      8 * ===----------------------------------------------------------------------===
      9 *
     10 * This file implements __mulodi4 for the compiler_rt library.
     11 *
     12 * ===----------------------------------------------------------------------===
     13 */
     14 
     15 #if 0
     16 #include "int_lib.h"
     17 #else
     18 #define COMPILER_RT_ABI
     19 #define di_int int64_t
     20 #define di_uint uint64_t
     21 #include "lib/cc/torint.h"
     22 
     23 di_int __mulodi4(di_int a, di_int b, int* overflow);
     24 #endif
     25 
     26 /* Returns: a * b */
     27 
     28 /* Effects: sets *overflow to 1  if a * b overflows */
     29 
     30 COMPILER_RT_ABI di_int
     31 __mulodi4(di_int a, di_int b, int* overflow)
     32 {
     33    const int N = (int)(sizeof(di_int) * CHAR_BIT);
     34    const di_int MIN = (di_int) ((di_uint)1 << (N-1));
     35    const di_int MAX = ~MIN;
     36    *overflow = 0;
     37    di_int result = a * b;
     38    if (a == MIN)
     39    {
     40        if (b != 0 && b != 1)
     41     *overflow = 1;
     42 return result;
     43    }
     44    if (b == MIN)
     45    {
     46        if (a != 0 && a != 1)
     47     *overflow = 1;
     48        return result;
     49    }
     50    di_int sa = a >> (N - 1);
     51    di_int abs_a = (a ^ sa) - sa;
     52    di_int sb = b >> (N - 1);
     53    di_int abs_b = (b ^ sb) - sb;
     54    if (abs_a < 2 || abs_b < 2)
     55        return result;
     56    if (sa == sb)
     57    {
     58        if (abs_a > MAX / abs_b)
     59            *overflow = 1;
     60    }
     61    else
     62    {
     63        if (abs_a > MIN / -abs_b)
     64            *overflow = 1;
     65    }
     66    return result;
     67 }