]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | /*===-- mulosi4.c - Implement __mulosi4 -----------------------------------=== |
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 __mulosi4 for the compiler_rt library. | |
11 | * | |
12 | * ===----------------------------------------------------------------------=== | |
13 | */ | |
14 | ||
15 | #include "int_lib.h" | |
16 | ||
17 | /* Returns: a * b */ | |
18 | ||
19 | /* Effects: sets *overflow to 1 if a * b overflows */ | |
20 | ||
21 | COMPILER_RT_ABI si_int | |
22 | __mulosi4(si_int a, si_int b, int* overflow) | |
23 | { | |
24 | const int N = (int)(sizeof(si_int) * CHAR_BIT); | |
25 | const si_int MIN = (si_int)1 << (N-1); | |
26 | const si_int MAX = ~MIN; | |
27 | *overflow = 0; | |
28 | si_int result = a * b; | |
29 | if (a == MIN) | |
30 | { | |
31 | if (b != 0 && b != 1) | |
32 | *overflow = 1; | |
33 | return result; | |
34 | } | |
35 | if (b == MIN) | |
36 | { | |
37 | if (a != 0 && a != 1) | |
38 | *overflow = 1; | |
39 | return result; | |
40 | } | |
41 | si_int sa = a >> (N - 1); | |
42 | si_int abs_a = (a ^ sa) - sa; | |
43 | si_int sb = b >> (N - 1); | |
44 | si_int abs_b = (b ^ sb) - sb; | |
45 | if (abs_a < 2 || abs_b < 2) | |
46 | return result; | |
47 | if (sa == sb) | |
48 | { | |
49 | if (abs_a > MAX / abs_b) | |
50 | *overflow = 1; | |
51 | } | |
52 | else | |
53 | { | |
54 | if (abs_a > MIN / -abs_b) | |
55 | *overflow = 1; | |
56 | } | |
57 | return result; | |
58 | } |