15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*===-- mulodi4.c - Implement __mulodi4 -----------------------------------===
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This file is dual licensed under the MIT and the University of Illinois Open
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Source Licenses. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * ===----------------------------------------------------------------------===
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This file implements __mulodi4 for the compiler_rt library.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * ===----------------------------------------------------------------------===
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "int_lib.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Returns: a * b */
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Effects: sets *overflow to 1  if a * b overflows */
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochCOMPILER_RT_ABI di_int
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)__mulodi4(di_int a, di_int b, int* overflow)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const int N = (int)(sizeof(di_int) * CHAR_BIT);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const di_int MIN = (di_int)1 << (N-1);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const di_int MAX = ~MIN;
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *overflow = 0;
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    di_int result = a * b;
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (a == MIN)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (b != 0 && b != 1)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	    *overflow = 1;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	return result;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (b == MIN)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (a != 0 && a != 1)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *overflow = 1;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return result;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    di_int sa = a >> (N - 1);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    di_int abs_a = (a ^ sa) - sa;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    di_int sb = b >> (N - 1);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    di_int abs_b = (b ^ sb) - sb;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (abs_a < 2 || abs_b < 2)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return result;
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (sa == sb)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if (abs_a > MAX / abs_b)
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            *overflow = 1;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (abs_a > MIN / -abs_b)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *overflow = 1;
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)