| /* compiler-rt.c - compiler helpers. */ |
| /* |
| * GRUB -- GRand Unified Bootloader |
| * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010-2014 Free Software Foundation, Inc. |
| * |
| * GRUB is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation, either version 3 of the License, or |
| * (at your option) any later version. |
| * |
| * GRUB is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with GRUB. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <grub/misc.h> |
| #include <grub/compiler-rt.h> |
| |
| #ifndef GRUB_EMBED_DECOMPRESSOR |
| void * GRUB_BUILTIN_ATTR |
| memcpy (void *dest, const void *src, grub_size_t n) |
| { |
| return grub_memmove (dest, src, n); |
| } |
| void * GRUB_BUILTIN_ATTR |
| memmove (void *dest, const void *src, grub_size_t n) |
| { |
| return grub_memmove (dest, src, n); |
| } |
| int GRUB_BUILTIN_ATTR |
| memcmp (const void *s1, const void *s2, grub_size_t n) |
| { |
| return grub_memcmp (s1, s2, n); |
| } |
| void * GRUB_BUILTIN_ATTR |
| memset (void *s, int c, grub_size_t n) |
| { |
| return grub_memset (s, c, n); |
| } |
| |
| #ifdef __APPLE__ |
| |
| void GRUB_BUILTIN_ATTR |
| __bzero (void *s, grub_size_t n) |
| { |
| grub_memset (s, 0, n); |
| } |
| |
| #endif |
| |
| #if GRUB_DIVISION_IN_SOFTWARE |
| |
| grub_uint32_t |
| __udivsi3 (grub_uint32_t a, grub_uint32_t b) |
| { |
| return grub_divmod64 (a, b, 0); |
| } |
| |
| grub_int32_t |
| __divsi3 (grub_int32_t a, grub_int32_t b) |
| { |
| return grub_divmod64s (a, b, 0); |
| } |
| |
| grub_uint32_t |
| __umodsi3 (grub_uint32_t a, grub_uint32_t b) |
| { |
| grub_uint64_t ret; |
| grub_divmod64 (a, b, &ret); |
| return ret; |
| } |
| |
| grub_int32_t |
| __modsi3 (grub_int32_t a, grub_int32_t b) |
| { |
| grub_int64_t ret; |
| grub_divmod64s (a, b, &ret); |
| return ret; |
| } |
| |
| grub_uint64_t |
| __udivdi3 (grub_uint64_t a, grub_uint64_t b) |
| { |
| return grub_divmod64 (a, b, 0); |
| } |
| |
| grub_uint64_t |
| __umoddi3 (grub_uint64_t a, grub_uint64_t b) |
| { |
| grub_uint64_t ret; |
| grub_divmod64 (a, b, &ret); |
| return ret; |
| } |
| |
| grub_int64_t |
| __divdi3 (grub_int64_t a, grub_int64_t b) |
| { |
| return grub_divmod64s (a, b, 0); |
| } |
| |
| grub_int64_t |
| __moddi3 (grub_int64_t a, grub_int64_t b) |
| { |
| grub_int64_t ret; |
| grub_divmod64s (a, b, &ret); |
| return ret; |
| } |
| |
| #endif |
| |
| #endif |
| |
| #ifdef NEED_CTZDI2 |
| |
| unsigned |
| __ctzdi2 (grub_uint64_t x) |
| { |
| unsigned ret = 0; |
| if (!x) |
| return 64; |
| if (!(x & 0xffffffff)) |
| { |
| x >>= 32; |
| ret |= 32; |
| } |
| if (!(x & 0xffff)) |
| { |
| x >>= 16; |
| ret |= 16; |
| } |
| if (!(x & 0xff)) |
| { |
| x >>= 8; |
| ret |= 8; |
| } |
| if (!(x & 0xf)) |
| { |
| x >>= 4; |
| ret |= 4; |
| } |
| if (!(x & 0x3)) |
| { |
| x >>= 2; |
| ret |= 2; |
| } |
| if (!(x & 0x1)) |
| { |
| x >>= 1; |
| ret |= 1; |
| } |
| return ret; |
| } |
| #endif |
| |
| #ifdef NEED_CTZSI2 |
| unsigned |
| __ctzsi2 (grub_uint32_t x) |
| { |
| unsigned ret = 0; |
| if (!x) |
| return 32; |
| |
| if (!(x & 0xffff)) |
| { |
| x >>= 16; |
| ret |= 16; |
| } |
| if (!(x & 0xff)) |
| { |
| x >>= 8; |
| ret |= 8; |
| } |
| if (!(x & 0xf)) |
| { |
| x >>= 4; |
| ret |= 4; |
| } |
| if (!(x & 0x3)) |
| { |
| x >>= 2; |
| ret |= 2; |
| } |
| if (!(x & 0x1)) |
| { |
| x >>= 1; |
| ret |= 1; |
| } |
| return ret; |
| } |
| |
| #endif |
| |
| |
| #if defined (__clang__) && !defined(GRUB_EMBED_DECOMPRESSOR) |
| /* clang emits references to abort(). */ |
| void __attribute__ ((noreturn)) |
| abort (void) |
| { |
| grub_fatal ("compiler abort"); |
| } |
| #endif |
| |
| #if (defined (__MINGW32__) || defined (__CYGWIN__)) |
| void __register_frame_info (void) |
| { |
| } |
| |
| void __deregister_frame_info (void) |
| { |
| } |
| |
| void ___chkstk_ms (void) |
| { |
| } |
| |
| void __chkstk_ms (void) |
| { |
| } |
| #endif |
| |
| union component64 |
| { |
| grub_uint64_t full; |
| struct |
| { |
| #ifdef GRUB_CPU_WORDS_BIGENDIAN |
| grub_uint32_t high; |
| grub_uint32_t low; |
| #else |
| grub_uint32_t low; |
| grub_uint32_t high; |
| #endif |
| }; |
| }; |
| |
| #if defined (__powerpc__) || defined (__arm__) || defined(__mips__) |
| |
| /* Based on libgcc2.c from gcc suite. */ |
| grub_uint64_t |
| __lshrdi3 (grub_uint64_t u, int b) |
| { |
| if (b == 0) |
| return u; |
| |
| const union component64 uu = {.full = u}; |
| const int bm = 32 - b; |
| union component64 w; |
| |
| if (bm <= 0) |
| { |
| w.high = 0; |
| w.low = (grub_uint32_t) uu.high >> -bm; |
| } |
| else |
| { |
| const grub_uint32_t carries = (grub_uint32_t) uu.high << bm; |
| |
| w.high = (grub_uint32_t) uu.high >> b; |
| w.low = ((grub_uint32_t) uu.low >> b) | carries; |
| } |
| |
| return w.full; |
| } |
| |
| /* Based on libgcc2.c from gcc suite. */ |
| grub_uint64_t |
| __ashrdi3 (grub_uint64_t u, int b) |
| { |
| if (b == 0) |
| return u; |
| |
| const union component64 uu = {.full = u}; |
| const int bm = 32 - b; |
| union component64 w; |
| |
| if (bm <= 0) |
| { |
| /* w.high = 1..1 or 0..0 */ |
| w.high = ((grub_int32_t) uu.high) >> (32 - 1); |
| w.low = ((grub_int32_t) uu.high) >> -bm; |
| } |
| else |
| { |
| const grub_uint32_t carries = ((grub_uint32_t) uu.high) << bm; |
| |
| w.high = ((grub_int32_t) uu.high) >> b; |
| w.low = ((grub_uint32_t) uu.low >> b) | carries; |
| } |
| |
| return w.full; |
| } |
| |
| /* Based on libgcc2.c from gcc suite. */ |
| grub_uint64_t |
| __ashldi3 (grub_uint64_t u, int b) |
| { |
| if (b == 0) |
| return u; |
| |
| const union component64 uu = {.full = u}; |
| const int bm = 32 - b; |
| union component64 w; |
| |
| if (bm <= 0) |
| { |
| w.low = 0; |
| w.high = (grub_uint32_t) uu.low << -bm; |
| } |
| else |
| { |
| const grub_uint32_t carries = (grub_uint32_t) uu.low >> bm; |
| |
| w.low = (grub_uint32_t) uu.low << b; |
| w.high = ((grub_uint32_t) uu.high << b) | carries; |
| } |
| |
| return w.full; |
| } |
| |
| /* Based on libgcc2.c from gcc suite. */ |
| int |
| __ucmpdi2 (grub_uint64_t a, grub_uint64_t b) |
| { |
| union component64 ac, bc; |
| ac.full = a; |
| bc.full = b; |
| |
| if (ac.high < bc.high) |
| return 0; |
| else if (ac.high > bc.high) |
| return 2; |
| |
| if (ac.low < bc.low) |
| return 0; |
| else if (ac.low > bc.low) |
| return 2; |
| return 1; |
| } |
| |
| #endif |
| |
| #if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || defined(__arm__) |
| |
| /* Based on libgcc2.c from gcc suite. */ |
| grub_uint32_t |
| __bswapsi2 (grub_uint32_t u) |
| { |
| return ((((u) & 0xff000000) >> 24) |
| | (((u) & 0x00ff0000) >> 8) |
| | (((u) & 0x0000ff00) << 8) |
| | (((u) & 0x000000ff) << 24)); |
| } |
| |
| /* Based on libgcc2.c from gcc suite. */ |
| grub_uint64_t |
| __bswapdi2 (grub_uint64_t u) |
| { |
| return ((((u) & 0xff00000000000000ull) >> 56) |
| | (((u) & 0x00ff000000000000ull) >> 40) |
| | (((u) & 0x0000ff0000000000ull) >> 24) |
| | (((u) & 0x000000ff00000000ull) >> 8) |
| | (((u) & 0x00000000ff000000ull) << 8) |
| | (((u) & 0x0000000000ff0000ull) << 24) |
| | (((u) & 0x000000000000ff00ull) << 40) |
| | (((u) & 0x00000000000000ffull) << 56)); |
| } |
| |
| |
| #endif |
| |
| #ifdef __arm__ |
| grub_uint32_t |
| __aeabi_uidiv (grub_uint32_t a, grub_uint32_t b) |
| __attribute__ ((alias ("__udivsi3"))); |
| grub_int32_t |
| __aeabi_idiv (grub_int32_t a, grub_int32_t b) |
| __attribute__ ((alias ("__divsi3"))); |
| void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n) |
| __attribute__ ((alias ("grub_memcpy"))); |
| void *__aeabi_memcpy4 (void *dest, const void *src, grub_size_t n) |
| __attribute__ ((alias ("grub_memcpy"))); |
| void *__aeabi_memcpy8 (void *dest, const void *src, grub_size_t n) |
| __attribute__ ((alias ("grub_memcpy"))); |
| void *__aeabi_memset (void *s, int c, grub_size_t n) |
| __attribute__ ((alias ("memset"))); |
| |
| void |
| __aeabi_memclr (void *s, grub_size_t n) |
| { |
| grub_memset (s, 0, n); |
| } |
| |
| void __aeabi_memclr4 (void *s, grub_size_t n) |
| __attribute__ ((alias ("__aeabi_memclr"))); |
| void __aeabi_memclr8 (void *s, grub_size_t n) |
| __attribute__ ((alias ("__aeabi_memclr"))); |
| |
| int |
| __aeabi_ulcmp (grub_uint64_t a, grub_uint64_t b) |
| { |
| return __ucmpdi2 (a, b) - 1; |
| } |
| |
| grub_uint64_t |
| __aeabi_lasr (grub_uint64_t u, int b) |
| __attribute__ ((alias ("__ashrdi3"))); |
| grub_uint64_t |
| __aeabi_llsr (grub_uint64_t u, int b) |
| __attribute__ ((alias ("__lshrdi3"))); |
| |
| grub_uint64_t |
| __aeabi_llsl (grub_uint64_t u, int b) |
| __attribute__ ((alias ("__ashldi3"))); |
| |
| #endif |