1229109Sed/*===-- muloti4.c - Implement __muloti4 -----------------------------------===
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 __muloti4 for the compiler_rt library.
11229109Sed *
12229109Sed * ===----------------------------------------------------------------------===
13229109Sed */
14229109Sed
15263560Sdim#include "int_lib.h"
16263560Sdim
17263764Sdim#ifdef CRT_HAS_128BIT
18229109Sed
19229109Sed/* Returns: a * b */
20229109Sed
21229109Sed/* Effects: sets *overflow to 1  if a * b overflows */
22229109Sed
23229109Sedti_int
24229109Sed__muloti4(ti_int a, ti_int b, int* overflow)
25229109Sed{
26229109Sed    const int N = (int)(sizeof(ti_int) * CHAR_BIT);
27229109Sed    const ti_int MIN = (ti_int)1 << (N-1);
28229109Sed    const ti_int MAX = ~MIN;
29229109Sed    *overflow = 0;
30229109Sed    ti_int result = a * b;
31229109Sed    if (a == MIN)
32229109Sed    {
33229109Sed        if (b != 0 && b != 1)
34229109Sed	    *overflow = 1;
35229109Sed	return result;
36229109Sed    }
37229109Sed    if (b == MIN)
38229109Sed    {
39229109Sed        if (a != 0 && a != 1)
40229109Sed	    *overflow = 1;
41229109Sed        return result;
42229109Sed    }
43229109Sed    ti_int sa = a >> (N - 1);
44229109Sed    ti_int abs_a = (a ^ sa) - sa;
45229109Sed    ti_int sb = b >> (N - 1);
46229109Sed    ti_int abs_b = (b ^ sb) - sb;
47229109Sed    if (abs_a < 2 || abs_b < 2)
48229109Sed        return result;
49229109Sed    if (sa == sb)
50229109Sed    {
51229109Sed        if (abs_a > MAX / abs_b)
52229109Sed            *overflow = 1;
53229109Sed    }
54229109Sed    else
55229109Sed    {
56229109Sed        if (abs_a > MIN / -abs_b)
57229109Sed            *overflow = 1;
58229109Sed    }
59229109Sed    return result;
60229109Sed}
61229109Sed
62263764Sdim#endif /* CRT_HAS_128BIT */
63