/* compiler-rt.c - compiler helpers. */ /* * VAS_EBOOT -- GRand Unified Bootloader * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010-2014 Free Software Foundation, Inc. * * VAS_EBOOT 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. * * VAS_EBOOT 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 VAS_EBOOT. If not, see . */ #include #include #ifndef VAS_EBOOT_EMBED_DECOMPRESSOR void * VAS_EBOOT_BUILTIN_ATTR memcpy (void *dest, const void *src, VasEBoot_size_t n) { return VasEBoot_memcpy (dest, src, n); } void * VAS_EBOOT_BUILTIN_ATTR memmove (void *dest, const void *src, VasEBoot_size_t n) { return VasEBoot_memmove (dest, src, n); } int VAS_EBOOT_BUILTIN_ATTR memcmp (const void *s1, const void *s2, VasEBoot_size_t n) { return VasEBoot_memcmp (s1, s2, n); } void * VAS_EBOOT_BUILTIN_ATTR memset (void *s, int c, VasEBoot_size_t n) { return VasEBoot_memset (s, c, n); } #ifdef __APPLE__ void VAS_EBOOT_BUILTIN_ATTR __bzero (void *s, VasEBoot_size_t n) { VasEBoot_memset (s, 0, n); } #endif #if VAS_EBOOT_DIVISION_IN_SOFTWARE VasEBoot_uint32_t __udivsi3 (VasEBoot_uint32_t a, VasEBoot_uint32_t b) { return VasEBoot_divmod64 (a, b, 0); } VasEBoot_int32_t __divsi3 (VasEBoot_int32_t a, VasEBoot_int32_t b) { return VasEBoot_divmod64s (a, b, 0); } VasEBoot_uint32_t __umodsi3 (VasEBoot_uint32_t a, VasEBoot_uint32_t b) { VasEBoot_uint64_t ret; VasEBoot_divmod64 (a, b, &ret); return ret; } VasEBoot_int32_t __modsi3 (VasEBoot_int32_t a, VasEBoot_int32_t b) { VasEBoot_int64_t ret; VasEBoot_divmod64s (a, b, &ret); return ret; } VasEBoot_uint64_t __udivdi3 (VasEBoot_uint64_t a, VasEBoot_uint64_t b) { return VasEBoot_divmod64 (a, b, 0); } VasEBoot_uint64_t __umoddi3 (VasEBoot_uint64_t a, VasEBoot_uint64_t b) { VasEBoot_uint64_t ret; VasEBoot_divmod64 (a, b, &ret); return ret; } VasEBoot_int64_t __divdi3 (VasEBoot_int64_t a, VasEBoot_int64_t b) { return VasEBoot_divmod64s (a, b, 0); } VasEBoot_int64_t __moddi3 (VasEBoot_int64_t a, VasEBoot_int64_t b) { VasEBoot_int64_t ret; VasEBoot_divmod64s (a, b, &ret); return ret; } #endif #endif #ifdef NEED_CTZDI2 unsigned __ctzdi2 (VasEBoot_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 (VasEBoot_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 (__MINGW32__) || defined (__CYGWIN__)) void __register_frame_info (void) { } void __deregister_frame_info (void) { } void ___chkstk_ms (void) { } void __chkstk_ms (void) { } #endif union component64 { VasEBoot_uint64_t full; struct { #ifdef VAS_EBOOT_CPU_WORDS_BIGENDIAN VasEBoot_uint32_t high; VasEBoot_uint32_t low; #else VasEBoot_uint32_t low; VasEBoot_uint32_t high; #endif }; }; #if defined (__powerpc__) || defined (__arm__) || defined(__mips__) || \ (defined(__riscv) && (__riscv_xlen == 32)) /* Based on libgcc2.c from gcc suite. */ VasEBoot_uint64_t __lshrdi3 (VasEBoot_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 = (VasEBoot_uint32_t) uu.high >> -bm; } else { const VasEBoot_uint32_t carries = (VasEBoot_uint32_t) uu.high << bm; w.high = (VasEBoot_uint32_t) uu.high >> b; w.low = ((VasEBoot_uint32_t) uu.low >> b) | carries; } return w.full; } /* Based on libgcc2.c from gcc suite. */ VasEBoot_uint64_t __ashrdi3 (VasEBoot_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 = ((VasEBoot_int32_t) uu.high) >> (32 - 1); w.low = ((VasEBoot_int32_t) uu.high) >> -bm; } else { const VasEBoot_uint32_t carries = ((VasEBoot_uint32_t) uu.high) << bm; w.high = ((VasEBoot_int32_t) uu.high) >> b; w.low = ((VasEBoot_uint32_t) uu.low >> b) | carries; } return w.full; } /* Based on libgcc2.c from gcc suite. */ VasEBoot_uint64_t __ashldi3 (VasEBoot_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 = (VasEBoot_uint32_t) uu.low << -bm; } else { const VasEBoot_uint32_t carries = (VasEBoot_uint32_t) uu.low >> bm; w.low = (VasEBoot_uint32_t) uu.low << b; w.high = ((VasEBoot_uint32_t) uu.high << b) | carries; } return w.full; } /* Based on libgcc2.c from gcc suite. */ int __ucmpdi2 (VasEBoot_uint64_t a, VasEBoot_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__) || defined(__riscv) /* Based on libgcc2.c from gcc suite. */ VasEBoot_uint32_t __bswapsi2 (VasEBoot_uint32_t u) { return ((((u) & 0xff000000) >> 24) | (((u) & 0x00ff0000) >> 8) | (((u) & 0x0000ff00) << 8) | (((u) & 0x000000ff) << 24)); } /* Based on libgcc2.c from gcc suite. */ VasEBoot_uint64_t __bswapdi2 (VasEBoot_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__ VasEBoot_uint32_t __aeabi_uidiv (VasEBoot_uint32_t a, VasEBoot_uint32_t b) __attribute__ ((alias ("__udivsi3"))); VasEBoot_int32_t __aeabi_idiv (VasEBoot_int32_t a, VasEBoot_int32_t b) __attribute__ ((alias ("__divsi3"))); void *__aeabi_memcpy (void *dest, const void *src, VasEBoot_size_t n) __attribute__ ((alias ("memcpy"))); void *__aeabi_memcpy4 (void *dest, const void *src, VasEBoot_size_t n) __attribute__ ((alias ("memcpy"))); void *__aeabi_memcpy8 (void *dest, const void *src, VasEBoot_size_t n) __attribute__ ((alias ("memcpy"))); void *__aeabi_memset (void *s, int c, VasEBoot_size_t n) __attribute__ ((alias ("memset"))); void __aeabi_memclr (void *s, VasEBoot_size_t n) { VasEBoot_memset (s, 0, n); } void __aeabi_memclr4 (void *s, VasEBoot_size_t n) __attribute__ ((alias ("__aeabi_memclr"))); void __aeabi_memclr8 (void *s, VasEBoot_size_t n) __attribute__ ((alias ("__aeabi_memclr"))); int __aeabi_ulcmp (VasEBoot_uint64_t a, VasEBoot_uint64_t b) { return __ucmpdi2 (a, b) - 1; } VasEBoot_uint64_t __aeabi_lasr (VasEBoot_uint64_t u, int b) __attribute__ ((alias ("__ashrdi3"))); VasEBoot_uint64_t __aeabi_llsr (VasEBoot_uint64_t u, int b) __attribute__ ((alias ("__lshrdi3"))); VasEBoot_uint64_t __aeabi_llsl (VasEBoot_uint64_t u, int b) __attribute__ ((alias ("__ashldi3"))); #endif #if defined(__mips__) || defined(__riscv) || defined(__sparc__) /* Based on libgcc from gcc suite. */ int __clzsi2 (VasEBoot_uint32_t val) { int i = 32; int j = 16; int temp; for (; j; j >>= 1) { if ((temp = val >> j)) { if (j == 1) { return (i - 2); } else { i -= j; val = temp; } } } return (i - val); } #endif #if defined(__mips__) || defined(__riscv) || defined(__sparc__) int __clzdi2 (VasEBoot_uint64_t val) { if (val >> 32) { return __clzsi2 (val >> 32); } else { return __clzsi2 (val) + 32; } } #endif