11fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan/* ===-- mulvti3.c - Implement __mulvti3 -----------------------------------===
21fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan *
31fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan *                     The LLVM Compiler Infrastructure
41fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan *
59ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * This file is dual licensed under the MIT and the University of Illinois Open
69ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * Source Licenses. See LICENSE.TXT for details.
71fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan *
81fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan * ===----------------------------------------------------------------------===
91fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan *
101fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan * This file implements __mulvti3 for the compiler_rt library.
111fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan *
121fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan * ===----------------------------------------------------------------------===
131fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan */
14b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
15b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#include "int_lib.h"
16b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#ifdef CRT_HAS_128BIT
187f2d7c75e713d778106d01a54e7aef40227bbf2dChandler Carruth
191fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan/* Returns: a * b */
20b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
211fcb40b79d8fbfcc9acb0966d5f9bba09431f832Edward O'Callaghan/* Effects: aborts if a * b overflows */
22b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesCOMPILER_RT_ABI ti_int
24b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar__mulvti3(ti_int a, ti_int b)
25b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar{
26b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    const int N = (int)(sizeof(ti_int) * CHAR_BIT);
27b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    const ti_int MIN = (ti_int)1 << (N-1);
28b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    const ti_int MAX = ~MIN;
29b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    if (a == MIN)
30b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
31b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        if (b == 0 || b == 1)
32b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            return a * b;
3348f46ac1d9a82210f6e469567cb60aa7e7cd2f3bDaniel Dunbar        compilerrt_abort();
34b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
35b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    if (b == MIN)
36b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
37b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        if (a == 0 || a == 1)
38b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            return a * b;
3948f46ac1d9a82210f6e469567cb60aa7e7cd2f3bDaniel Dunbar        compilerrt_abort();
40b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
41b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    ti_int sa = a >> (N - 1);
42b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    ti_int abs_a = (a ^ sa) - sa;
43b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    ti_int sb = b >> (N - 1);
44b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    ti_int abs_b = (b ^ sb) - sb;
45b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    if (abs_a < 2 || abs_b < 2)
46b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        return a * b;
47b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    if (sa == sb)
48b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
49b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        if (abs_a > MAX / abs_b)
5048f46ac1d9a82210f6e469567cb60aa7e7cd2f3bDaniel Dunbar            compilerrt_abort();
51b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
52b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    else
53b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
54b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        if (abs_a > MIN / -abs_b)
5548f46ac1d9a82210f6e469567cb60aa7e7cd2f3bDaniel Dunbar            compilerrt_abort();
56b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
57b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    return a * b;
58b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar}
59b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif /* CRT_HAS_128BIT */
61