1229109Sed/*===-- mulodi4.c - Implement __mulodi4 -----------------------------------===
2229109Sed *
3229109Sed *                     The LLVM Compiler Infrastructure
4229109Sed *
5229109Sed * This file is dual licensed under the MIT and the University of Illinois Open
6229109Sed * Source Licenses. See LICENSE.TXT for details.
7229109Sed *
8229109Sed * ===----------------------------------------------------------------------===
9229109Sed *
10229109Sed * This file implements __mulodi4 for the compiler_rt library.
11229109Sed *
12229109Sed * ===----------------------------------------------------------------------===
13229109Sed */
14229109Sed
15229109Sed#include "int_lib.h"
16229109Sed
17229109Sed/* Returns: a * b */
18229109Sed
19229109Sed/* Effects: sets *overflow to 1  if a * b overflows */
20229109Sed
21229109Seddi_int
22229109Sed__mulodi4(di_int a, di_int b, int* overflow)
23229109Sed{
24229109Sed    const int N = (int)(sizeof(di_int) * CHAR_BIT);
25229109Sed    const di_int MIN = (di_int)1 << (N-1);
26229109Sed    const di_int MAX = ~MIN;
27229109Sed    *overflow = 0;
28229109Sed    di_int result = a * b;
29229109Sed    if (a == MIN)
30229109Sed    {
31229109Sed        if (b != 0 && b != 1)
32229109Sed	    *overflow = 1;
33229109Sed	return result;
34229109Sed    }
35229109Sed    if (b == MIN)
36229109Sed    {
37229109Sed        if (a != 0 && a != 1)
38229109Sed	    *overflow = 1;
39229109Sed        return result;
40229109Sed    }
41229109Sed    di_int sa = a >> (N - 1);
42229109Sed    di_int abs_a = (a ^ sa) - sa;
43229109Sed    di_int sb = b >> (N - 1);
44229109Sed    di_int abs_b = (b ^ sb) - sb;
45229109Sed    if (abs_a < 2 || abs_b < 2)
46229109Sed        return result;
47229109Sed    if (sa == sb)
48229109Sed    {
49229109Sed        if (abs_a > MAX / abs_b)
50229109Sed            *overflow = 1;
51229109Sed    }
52229109Sed    else
53229109Sed    {
54229109Sed        if (abs_a > MIN / -abs_b)
55229109Sed            *overflow = 1;
56229109Sed    }
57229109Sed    return result;
58229109Sed}
59