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